Файли
openidea/src/features/plugins/markerStore.test.ts
T
Pedro Pessoa e0982cc51d feat(plugins): brand document-indexer gutter markers with marker icons (#2196)
Indexed markers (Edges.markers) were always drawn with the navigation glyph,
so a plugin couldn't tell its marker kinds apart. A [[contributes.markerIcons]]
entry can now claim them by key prefix (`markers`), with an optional
`tooltip` shown above the targets. The host matches the longest prefix and
sends the declaration id with each marker; the editor resolves the icon and
the translated tooltip from the projected declaration. Manifest only, under
the existing API 1.3 gate of markerIcons.

Closes #2194
2026-11-09 04:53:03 +08:00

54 рядки
2.1 KiB
TypeScript

import { afterEach, expect, it, vi } from "vitest";
import { watchPluginMarkers, usePluginMarkers, invalidatePluginMarkers } from "./markerStore";
import { invalidateNavigationProviders } from "@/editor/navigationProviders";
const mock = vi.hoisted(() => vi.fn());
vi.mock("@/platform/ipc", async (original) => ({
...(await original<typeof import("@/platform/ipc")>()),
isTauri: () => true,
commands: { pluginNavigationMarkers: mock },
}));
const off: (() => void)[] = [];
afterEach(() => {
off.splice(0).forEach((f) => f());
vi.useRealTimers();
mock.mockReset();
});
it("batches visible paths, shares watchers and does no polling while idle", async () => {
vi.useFakeTimers();
mock.mockResolvedValue({ status: "ok", data: [] });
for (let i = 0; i < 130; i++) off.push(watchPluginMarkers(`/p/${i}.java`));
off.push(watchPluginMarkers("/p/0.java"));
await vi.advanceTimersByTimeAsync(250);
expect(mock.mock.calls.map((a) => a[0].length)).toEqual([64, 64, 2]);
await vi.advanceTimersByTimeAsync(5000);
expect(mock).toHaveBeenCalledTimes(3);
});
it("discards in-flight results after the project/provider epoch changes", async () => {
vi.useFakeTimers();
let finish!: (r: unknown) => void;
mock.mockImplementationOnce(() => new Promise((r) => (finish = r))).mockResolvedValue({ status: "ok", data: [] });
off.push(watchPluginMarkers("/old/A.xml"));
await vi.advanceTimersByTimeAsync(250);
invalidateNavigationProviders();
finish({ status: "ok", data: [{ path: "/old/A.xml", version: 1, markers: [] }] });
await vi.advanceTimersByTimeAsync(250);
expect(usePluginMarkers.getState().entries.size).toBe(0);
});
it("invalidates both changed files and markers targeting them", () => {
const range = { start: { line: 0, col: 0 }, end: { line: 0, col: 1 } };
usePluginMarkers.setState({
entries: new Map([
[
"/p/A.xml",
{
path: "/p/A.xml",
version: 1,
markers: [{ range, targets: [{ path: "/p/A.java", range }], pluginId: "p", icon: null }],
},
],
]),
});
invalidatePluginMarkers(["/p/A.java"]);
expect(usePluginMarkers.getState().entries.size).toBe(0);
});