import { mkdirSync, mkdtempSync, rmSync, writeFileSync } from "node:fs"; import { tmpdir } from "node:os"; import path from "node:path"; import { afterEach, describe, expect, it, vi } from "vitest"; import { createTestSession, type TestSession } from "../../../test/harness"; const extensionPath = path.resolve(import.meta.dirname, "../index.ts"); type Case = { user?: unknown; project?: unknown }; const mask = (name: string, shortcut: string) => ({ name, model: "openai/gpt-4o", thinkingLevel: "low", shortcut, }); describe("masks settings resolution", () => { let t: TestSession | undefined; let root: string | undefined; afterEach(() => { vi.restoreAllMocks(); t?.dispose(); t = undefined; if (root) rmSync(root, { recursive: true, force: true }); root = undefined; }); async function start(input: Case) { root = mkdtempSync(path.join(tmpdir(), "pi-ext-masks-settings-")); const write = (dir: string, value: unknown) => { mkdirSync(dir, { recursive: true }); writeFileSync( path.join(dir, "settings.json"), JSON.stringify({ masks: value }), ); }; if ("user" in input) write(path.join(root, ".test-home/.pi/agent"), input.user); if ("project" in input) write(path.join(root, ".pi"), input.project); // Masks load before any session, from process.cwd(). vi.spyOn(process, "cwd").mockReturnValue(root); t = await createTestSession({ cwd: root, extensions: [extensionPath] }); const extension = t.session.extensionRunner.extensions[0]; const warnings = t.events .uiCallsFor("notify") .filter((call) => call.args[1] === "warning") .map((call) => call.args[0]); return { shortcuts: [...extension.shortcuts.keys()], warnings }; } it.each([ ["default", {}, ["alt+m"]], [ "user", { user: { pickerShortcut: "alt+p", items: [mask("a", "alt+1")] } }, ["alt+p", "alt+1"], ], [ "trusted project ignored", { user: { items: [mask("a", "alt+1")] }, project: { pickerShortcut: "alt+p", items: [mask("b", "alt+2")] }, }, ["alt+m", "alt+1"], ], ] satisfies [string, Case, string[]][])( "%s", async (_name, input, expected) => { const { shortcuts, warnings } = await start(input); expect(shortcuts).toEqual(expected); expect(warnings).toEqual([]); }, ); it("reports invalid user settings without falling back to project", async () => { const { shortcuts, warnings } = await start({ user: "alt+p", project: { items: [mask("b", "alt+2")] }, }); expect(shortcuts).toEqual(["alt+m"]); expect(warnings).toEqual(["masks must be an object"]); }); });