diff --git a/test/coeditingRegistry.test.ts b/test/coeditingRegistry.test.ts index 05ff076..915cfc5 100644 --- a/test/coeditingRegistry.test.ts +++ b/test/coeditingRegistry.test.ts @@ -14,6 +14,7 @@ vi.mock("vscode", () => ({ commands: { executeCommand: vi.fn() }, window: { activeTextEditor: undefined }, })); +import * as vscode from "vscode"; import { CoeditingRegistry } from "../src/coeditingRegistry"; function memento(): { store: Map } & { get: any; update: any } { @@ -60,4 +61,109 @@ describe("CoeditingRegistry", () => { reg.enter(uri); expect(events).toHaveLength(1); }); + + it("exit is idempotent (no duplicate events on double exit)", () => { + 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.exit(uri); + reg.exit(uri); + expect(events).toHaveLength(2); // enter, then exit (second exit fires nothing) + }); + + it("syncContext: active editor with coediting doc sets isCoediting=true", () => { + const reg = new CoeditingRegistry(memento() as any); + const uri = { toString: () => "file:///a.md" } as any; + reg.enter(uri); + + const mockExecuteCommand = vscode.commands.executeCommand as any; + mockExecuteCommand.mockClear(); + + const editor = { document: { uri } } as any; + reg.syncContext(editor); + + expect(mockExecuteCommand).toHaveBeenCalledWith("setContext", "cowriting.isCoediting", true); + }); + + it("syncContext: undefined editor sets isCoediting=false", () => { + const reg = new CoeditingRegistry(memento() as any); + const mockExecuteCommand = vscode.commands.executeCommand as any; + mockExecuteCommand.mockClear(); + + reg.syncContext(undefined); + + expect(mockExecuteCommand).toHaveBeenCalledWith("setContext", "cowriting.isCoediting", false); + }); + + it("syncContext: non-coediting doc sets isCoediting=false", () => { + const reg = new CoeditingRegistry(memento() as any); + const mockExecuteCommand = vscode.commands.executeCommand as any; + mockExecuteCommand.mockClear(); + + const uri = { toString: () => "file:///nonexistent.md" } as any; + const editor = { document: { uri } } as any; + reg.syncContext(editor); + + expect(mockExecuteCommand).toHaveBeenCalledWith("setContext", "cowriting.isCoediting", false); + }); + + it("syncContext: baselineMode defaults to empty string when not coediting", () => { + const reg = new CoeditingRegistry(memento() as any); + const mockExecuteCommand = vscode.commands.executeCommand as any; + mockExecuteCommand.mockClear(); + + const uri = { toString: () => "file:///a.md" } as any; + const editor = { document: { uri } } as any; + reg.syncContext(editor); + + expect(mockExecuteCommand).toHaveBeenCalledWith("setContext", "cowriting.baselineMode", ""); + }); + + it("syncContext: baselineMode uses hook result when coediting and hook is set", () => { + const reg = new CoeditingRegistry(memento() as any); + const uri = { toString: () => "file:///a.md" } as any; + reg.enter(uri); + + reg.baselineModeOf = vi.fn((): "head" | "snapshot" | undefined => "snapshot"); + + const mockExecuteCommand = vscode.commands.executeCommand as any; + mockExecuteCommand.mockClear(); + + const editor = { document: { uri } } as any; + reg.syncContext(editor); + + expect(mockExecuteCommand).toHaveBeenCalledWith("setContext", "cowriting.baselineMode", "snapshot"); + }); + + it("syncContext: baselineMode defaults to empty string when hook returns undefined", () => { + const reg = new CoeditingRegistry(memento() as any); + const uri = { toString: () => "file:///a.md" } as any; + reg.enter(uri); + + reg.baselineModeOf = vi.fn((): "head" | "snapshot" | undefined => undefined); + + const mockExecuteCommand = vscode.commands.executeCommand as any; + mockExecuteCommand.mockClear(); + + const editor = { document: { uri } } as any; + reg.syncContext(editor); + + expect(mockExecuteCommand).toHaveBeenCalledWith("setContext", "cowriting.baselineMode", ""); + }); + + it("syncContext: calls executeCommand twice (isCoediting and baselineMode)", () => { + const reg = new CoeditingRegistry(memento() as any); + const uri = { toString: () => "file:///a.md" } as any; + reg.enter(uri); + + const mockExecuteCommand = vscode.commands.executeCommand as any; + mockExecuteCommand.mockClear(); + + const editor = { document: { uri } } as any; + reg.syncContext(editor); + + expect(mockExecuteCommand).toHaveBeenCalledTimes(2); + }); });