import { describe, expect, it, vi } from "vitest"; // The pure set logic lives in a vscode-free helper the class wraps, so unit-test the class // with a Memento stub (vitest runs vscode-free; the module imports vscode only for types + // EventEmitter — mock it). vi.mock("vscode", () => ({ EventEmitter: class { private handlers: Array<(e: unknown) => void> = []; event = (h: (e: unknown) => void) => { this.handlers.push(h); return { dispose() {} }; }; fire(e: unknown) { for (const h of this.handlers) h(e); } dispose() {} }, Uri: { parse: (s: string) => ({ toString: () => s }) }, commands: { executeCommand: vi.fn() }, window: { activeTextEditor: undefined }, })); import { CoeditingRegistry } from "../src/coeditingRegistry"; function memento(): { store: Map } & { get: any; update: any } { const store = new Map(); return { store, get: (k: string, dflt?: unknown) => (store.has(k) ? store.get(k) : dflt), update: (k: string, v: unknown) => { store.set(k, v); return Promise.resolve(); }, } as any; } describe("CoeditingRegistry", () => { it("enter/exit flips membership and fires onDidChange", () => { const reg = new CoeditingRegistry(memento() as any); const events: Array<{ uri: string; coediting: boolean }> = []; reg.onDidChange((e) => events.push(e as any)); const uri = { toString: () => "file:///a.md" } as any; expect(reg.isCoediting(uri)).toBe(false); reg.enter(uri); expect(reg.isCoediting(uri)).toBe(true); reg.exit(uri); expect(reg.isCoediting(uri)).toBe(false); expect(events).toEqual([ { uri: "file:///a.md", coediting: true }, { uri: "file:///a.md", coediting: false }, ]); }); it("persists the set across construction (reload survival)", () => { const m = memento(); const reg1 = new CoeditingRegistry(m as any); reg1.enter({ toString: () => "file:///a.md" } as any); const reg2 = new CoeditingRegistry(m as any); expect(reg2.isCoediting({ toString: () => "file:///a.md" } as any)).toBe(true); expect(reg2.list()).toEqual(["file:///a.md"]); }); it("enter is idempotent (no duplicate events)", () => { const reg = new CoeditingRegistry(memento() as any); const events: unknown[] = []; reg.onDidChange((e) => events.push(e)); const uri = { toString: () => "file:///a.md" } as any; reg.enter(uri); reg.enter(uri); expect(events).toHaveLength(1); }); });