import { beforeEach, describe, expect, it, vi } from "vitest"; import type { AgentStoreSeed } from "@/features/agents/state/store"; import type { GatewayModelPolicySnapshot } from "@/lib/gateway/models"; import type { StudioSettingsPatch } from "@/lib/studio/settings"; vi.mock("@/features/agents/operations/agentFleetHydration", () => ({ hydrateAgentFleetFromGateway: vi.fn(), })); import { hydrateAgentFleetFromGateway } from "@/features/agents/operations/agentFleetHydration"; import { executeStudioBootstrapLoadCommands, executeStudioFocusedPatchCommands, executeStudioFocusedPreferenceLoadCommands, runStudioBootstrapLoadOperation, runStudioFocusFilterPersistenceOperation, runStudioFocusedPreferenceLoadOperation, runStudioFocusedSelectionPersistenceOperation, type StudioBootstrapLoadCommand, } from "@/features/agents/operations/studioBootstrapOperation"; const hydrateAgentFleetFromGatewayMock = vi.mocked(hydrateAgentFleetFromGateway); describe("studioBootstrapOperation", () => { beforeEach(() => { hydrateAgentFleetFromGatewayMock.mockReset(); }); it("builds bootstrap commands from hydrated fleet result", async () => { const seeds: AgentStoreSeed[] = [ { agentId: "agent-1", name: "Agent One", sessionKey: "agent:agent-1:main", }, { agentId: "agent-2", name: "Agent Two", sessionKey: "agent:agent-2:main", }, ]; const snapshot = { config: {} } as GatewayModelPolicySnapshot; hydrateAgentFleetFromGatewayMock.mockResolvedValue({ seeds, sessionCreatedAgentIds: ["agent-1"], sessionSettingsSyncedAgentIds: ["agent-1"], summaryPatches: [{ agentId: "agent-2", patch: { latestPreview: "hello" } }], suggestedSelectedAgentId: "agent-2", configSnapshot: snapshot, }); const commands = await runStudioBootstrapLoadOperation({ client: { call: async () => null }, gatewayUrl: "https://gateway.test", cachedConfigSnapshot: null, loadStudioSettings: async () => null, isDisconnectLikeError: () => false, preferredSelectedAgentId: "agent-1", hasCurrentSelection: false, }); expect(commands).toEqual([ { kind: "set-gateway-config-snapshot", snapshot }, { kind: "hydrate-agents", seeds, initialSelectedAgentId: "agent-1", }, { kind: "mark-session-created", agentId: "agent-1", sessionSettingsSynced: true, }, { kind: "apply-summary-patch", agentId: "agent-2", patch: { latestPreview: "hello" }, }, ]); }); it("returns set-error command when fleet hydration fails", async () => { hydrateAgentFleetFromGatewayMock.mockRejectedValue(new Error("load failed")); const commands = await runStudioBootstrapLoadOperation({ client: { call: async () => null }, gatewayUrl: "https://gateway.test", cachedConfigSnapshot: null, loadStudioSettings: async () => null, isDisconnectLikeError: () => false, preferredSelectedAgentId: null, hasCurrentSelection: false, }); expect(commands).toEqual([{ kind: "set-error", message: "load failed" }]); }); it("executes bootstrap commands with injected callbacks", () => { const commands: StudioBootstrapLoadCommand[] = [ { kind: "set-gateway-config-snapshot", snapshot: { config: {} } as GatewayModelPolicySnapshot, }, { kind: "hydrate-agents", seeds: [{ agentId: "agent-1", name: "Agent One", sessionKey: "s1" }], initialSelectedAgentId: "agent-1", }, { kind: "mark-session-created", agentId: "agent-1", sessionSettingsSynced: true, }, { kind: "apply-summary-patch", agentId: "agent-1", patch: { latestPreview: "preview" }, }, { kind: "set-error", message: "failed", }, ]; const setGatewayConfigSnapshot = vi.fn(); const hydrateAgents = vi.fn(); const dispatchUpdateAgent = vi.fn(); const setError = vi.fn(); executeStudioBootstrapLoadCommands({ commands, setGatewayConfigSnapshot, hydrateAgents, dispatchUpdateAgent, setError, }); expect(setGatewayConfigSnapshot).toHaveBeenCalledTimes(1); expect(hydrateAgents).toHaveBeenCalledWith( [{ agentId: "agent-1", name: "Agent One", sessionKey: "s1" }], "agent-1" ); expect(dispatchUpdateAgent).toHaveBeenCalledWith("agent-1", { sessionCreated: true, sessionSettingsSynced: true, }); expect(dispatchUpdateAgent).toHaveBeenCalledWith("agent-1", { latestPreview: "preview" }); expect(setError).toHaveBeenCalledWith("failed"); }); it("loads focused preference and emits restore commands", async () => { const commands = await runStudioFocusedPreferenceLoadOperation({ gatewayUrl: "https://gateway.test", loadStudioSettings: async () => ({ version: 1, gateway: null, focused: { "https://gateway.test": { mode: "focused", selectedAgentId: "agent-9", filter: "running", }, }, avatars: {}, deskAssignments: {}, analytics: {}, voiceReplies: {}, office: {}, }), isFocusFilterTouched: () => false, }); expect(commands).toEqual([ { kind: "set-preferred-selected-agent-id", agentId: "agent-9", }, { kind: "set-focus-filter", filter: "all", }, { kind: "set-focused-preferences-loaded", value: true, }, ]); }); it("skips focused preference restore when user touched filter during load", async () => { const commands = await runStudioFocusedPreferenceLoadOperation({ gatewayUrl: "https://gateway.test", loadStudioSettings: async () => ({ version: 1, gateway: null, focused: { "https://gateway.test": { mode: "focused", selectedAgentId: "agent-9", filter: "running", }, }, avatars: {}, deskAssignments: {}, analytics: {}, voiceReplies: {}, office: {}, }), isFocusFilterTouched: () => true, }); expect(commands).toEqual([ { kind: "set-focused-preferences-loaded", value: true, }, ]); }); it("returns focused preference load error command on failure", async () => { const commands = await runStudioFocusedPreferenceLoadOperation({ gatewayUrl: "https://gateway.test", loadStudioSettings: async () => { throw new Error("settings failed"); }, isFocusFilterTouched: () => false, }); expect(commands[0]).toMatchObject({ kind: "log-error", message: "Failed to load focused preference.", }); expect(commands[1]).toEqual({ kind: "set-focused-preferences-loaded", value: true, }); }); it("executes focused preference load commands", () => { const setFocusedPreferencesLoaded = vi.fn(); const setPreferredSelectedAgentId = vi.fn(); const setFocusFilter = vi.fn(); const logError = vi.fn(); executeStudioFocusedPreferenceLoadCommands({ commands: [ { kind: "set-focused-preferences-loaded", value: false }, { kind: "set-preferred-selected-agent-id", agentId: "agent-1" }, { kind: "set-focus-filter", filter: "approvals" }, { kind: "log-error", message: "failed", error: new Error("boom") }, ], setFocusedPreferencesLoaded, setPreferredSelectedAgentId, setFocusFilter, logError, }); expect(setFocusedPreferencesLoaded).toHaveBeenCalledWith(false); expect(setPreferredSelectedAgentId).toHaveBeenCalledWith("agent-1"); expect(setFocusFilter).toHaveBeenCalledWith("approvals"); expect(logError).toHaveBeenCalledTimes(1); }); it("plans focused persistence patch commands and executes scheduler", () => { const filterCommands = runStudioFocusFilterPersistenceOperation({ gatewayUrl: "https://gateway.test", focusFilterTouched: true, focusFilter: "running", }); const selectionCommands = runStudioFocusedSelectionPersistenceOperation({ gatewayUrl: "https://gateway.test", status: "connected", focusedPreferencesLoaded: true, agentsLoadedOnce: true, selectedAgentId: "agent-2", }); const schedulePatch = vi.fn(); executeStudioFocusedPatchCommands({ commands: [...filterCommands, ...selectionCommands], schedulePatch, }); expect(schedulePatch).toHaveBeenCalledTimes(2); const firstCall = schedulePatch.mock.calls[0] as [StudioSettingsPatch, number]; const secondCall = schedulePatch.mock.calls[1] as [StudioSettingsPatch, number]; expect(firstCall[1]).toBe(300); expect(secondCall[1]).toBe(300); }); });