/** * L5 — the in-memory {@link MockProfileGateway}: first-run flag lifecycle, * reference catalogue, simulated detection (only `claude` installed), and the * save/list/delete/configure CRUD. */ import { describe, it, expect } from "vitest"; import type { AgentProfile } from "@/domain"; import { MockProfileGateway, MOCK_REFERENCE_PROFILES } from "./index"; function customProfile(id: string, command: string): AgentProfile { return { id, name: `Custom ${id}`, command, args: [], contextInjection: { strategy: "stdin" }, detect: null, cwdTemplate: "{projectRoot}", }; } describe("MockProfileGateway", () => { it("firstRunState is first-run with the four reference profiles", async () => { const gw = new MockProfileGateway(); const state = await gw.firstRunState(); expect(state.isFirstRun).toBe(true); expect(state.referenceProfiles.map((p) => p.command)).toEqual([ "claude", "codex", "gemini", "aider", ]); }); it("referenceProfiles returns a clone of the catalogue", async () => { const gw = new MockProfileGateway(); const refs = await gw.referenceProfiles(); expect(refs).toEqual(MOCK_REFERENCE_PROFILES); refs[0].command = "mutated"; const again = await gw.referenceProfiles(); expect(again[0].command).toBe("claude"); }); it("detectProfiles marks only claude as installed", async () => { const gw = new MockProfileGateway(); const results = await gw.detectProfiles([...MOCK_REFERENCE_PROFILES]); const byCommand = Object.fromEntries( results.map((r) => [r.profile.command, r.available]), ); expect(byCommand).toEqual({ claude: true, codex: false, gemini: false, aider: false, }); }); it("saveProfile upserts and listProfiles reflects it", async () => { const gw = new MockProfileGateway(); await gw.saveProfile(customProfile("c1", "foo")); await gw.saveProfile(customProfile("c1", "bar")); // same id ⇒ replace const list = await gw.listProfiles(); expect(list).toHaveLength(1); expect(list[0].command).toBe("bar"); }); it("deleteProfile removes by id", async () => { const gw = new MockProfileGateway(); await gw.saveProfile(customProfile("a", "a")); await gw.saveProfile(customProfile("b", "b")); await gw.deleteProfile("a"); const list = await gw.listProfiles(); expect(list.map((p) => p.id)).toEqual(["b"]); }); it("configureProfiles persists the batch and closes the first run", async () => { const gw = new MockProfileGateway(); expect((await gw.firstRunState()).isFirstRun).toBe(true); const chosen = [customProfile("x", "x")]; const out = await gw.configureProfiles(chosen); expect(out).toEqual(chosen); expect((await gw.firstRunState()).isFirstRun).toBe(false); expect(await gw.listProfiles()).toEqual(chosen); }); it("configureProfiles with an empty list still closes the first run", async () => { const gw = new MockProfileGateway(); await gw.configureProfiles([]); expect((await gw.firstRunState()).isFirstRun).toBe(false); }); });