mirror of
https://github.com/l0ng-ai/openidea.git
synced 2026-11-08 08:52:12 +00:00
Adds the API 1.3 `endpoints-provider` export and `[[contributes.endpoints]]` (file globs, ^1.3, `project.read`). A plugin's routes join the Spring ones in Search Everywhere, `.http` URL completion and the declaration's Open in HTTP Client gutter action. The UI asks `plugin_endpoints` on demand; the host runs the plugin on a blocking thread, validates the whole list (bounds, project-relative locations, UTF-16 ranges) and caches it per project until a file matching the globs changes, then emits `EndpointsChanged`. A failed or invalid run keeps the last list; disabling, crashing or closing the project withdraws it, and late results can't restore it. Closes #1960. Co-authored-by: arnaud-ritti <[email protected]>
64 lines
2.8 KiB
TypeScript
64 lines
2.8 KiB
TypeScript
import { doubleShift, expect, test } from "./fixtures";
|
|
|
|
test("plugin routes feed search, HTTP completion and the declaration gutter and disappear on removal", async ({
|
|
workbench: page,
|
|
}) => {
|
|
await page.evaluate(async () => {
|
|
const c = "/src/workbench/contributions.ts";
|
|
const b = "/src/editor/core/backend.ts";
|
|
const { registerEndpointProvider, editorService } = await import(c);
|
|
const { docBackend } = await import(b);
|
|
docBackend().files.set("/dev/acme-api/routes.txt", "route declaration\n");
|
|
docBackend().files.set("/dev/acme-api/routes.http", "GET {{host}}/pe");
|
|
(window as unknown as { removeRoutes: () => void }).removeRoutes = registerEndpointProvider({
|
|
id: "plugin:routes:test",
|
|
endpoints: async (root: string) =>
|
|
root === "/dev/acme-api"
|
|
? [
|
|
{
|
|
method: "*",
|
|
url: "/people/{id}",
|
|
framework: "Rails",
|
|
handler: "People#show",
|
|
pluginId: "routes",
|
|
controller: "Rails",
|
|
methodName: "People#show",
|
|
path: "/dev/acme-api/routes.txt",
|
|
rel: "routes.txt",
|
|
line: 0,
|
|
col: 0,
|
|
},
|
|
]
|
|
: [],
|
|
});
|
|
await editorService().openFile("/dev/acme-api/routes.txt");
|
|
});
|
|
await expect(page.locator('.cm-openidea-gutter-endpoints button[title="Open in HTTP Client"]')).toBeVisible();
|
|
await doubleShift(page);
|
|
const search = page.getByRole("dialog", { name: "Search Everywhere" });
|
|
await search.getByRole("combobox").fill("/people");
|
|
await expect(search.getByRole("option", { name: /people/ })).toBeVisible();
|
|
await page.keyboard.press("Escape");
|
|
await page.evaluate(async () => {
|
|
const path = "/src/workbench/contributions.ts";
|
|
await (await import(path)).editorService().openFile("/dev/acme-api/routes.http");
|
|
});
|
|
const content = page.locator(".cm-content").last();
|
|
await content.click();
|
|
await page.keyboard.press("Meta+End");
|
|
await page.keyboard.press("Control+Space");
|
|
await expect(page.locator(".cm-tooltip-autocomplete").getByText("/people/{{id}}", { exact: true })).toBeVisible();
|
|
await page.keyboard.press("Escape");
|
|
await doubleShift(page);
|
|
await search.getByRole("combobox").fill("/people");
|
|
await expect(search.getByRole("option", { name: /people/ })).toBeVisible();
|
|
await page.evaluate(() => (window as unknown as { removeRoutes: () => void }).removeRoutes());
|
|
await expect(search.getByRole("option", { name: /people/ })).toBeHidden();
|
|
await page.keyboard.press("Escape");
|
|
await page.evaluate(async () => {
|
|
const path = "/src/workbench/contributions.ts";
|
|
await (await import(path)).editorService().openFile("/dev/acme-api/routes.txt");
|
|
});
|
|
await expect(page.locator('.cm-openidea-gutter-endpoints button[title="Open in HTTP Client"]')).toBeHidden();
|
|
});
|