{"version":3,"file":"interactive-resume-delegation.test.d.ts","sourceRoot":"","sources":["../../../src/modes/interactive/interactive-resume-delegation.test.ts"],"names":[],"mappings":"","sourcesContent":["import { describe, expect, it, vi } from \"vitest\";\nimport { InteractiveMode } from \"./interactive-mode.js\";\n\ntype ResumeHarness = {\n\thandleResumeSession: (sessionPath: string) => Promise<void>;\n\tsession: { switchSession: (sessionPath: string) => Promise<boolean> };\n\tloadingAnimation?: { dispose: () => void };\n\tclearStatusOwner: (options: { requestRender: boolean }) => void;\n\tpendingMessagesContainer: { clear: () => void };\n\tcompactionQueuedMessages: string[];\n\tresetInteractiveSessionUI: (renderInitialMessages?: boolean) => void;\n\tshowStatus: (message: string) => void;\n};\n\ndescribe(\"InteractiveMode /resume delegation boundary\", () => {\n\tit(\"delegates resume to AgentSession.switchSession(sessionPath) before interactive UI reset\", async () => {\n\t\tconst events: string[] = [];\n\t\tlet resolveSwitch: ((value: boolean) => void) | undefined;\n\n\t\tconst switchSession = vi.fn<(sessionPath: string) => Promise<boolean>>((sessionPath: string) => {\n\t\t\tevents.push(`switch:${sessionPath}`);\n\t\t\treturn new Promise<boolean>((resolve) => {\n\t\t\t\tresolveSwitch = resolve;\n\t\t\t});\n\t\t});\n\t\tconst dispose = vi.fn(() => {\n\t\t\tevents.push(\"disposeLoading\");\n\t\t});\n\t\tconst clearStatusOwner = vi.fn(() => {\n\t\t\tevents.push(\"clearStatusOwner\");\n\t\t});\n\t\tconst clearPendingMessages = vi.fn(() => {\n\t\t\tevents.push(\"clearPendingMessages\");\n\t\t});\n\t\tconst resetInteractiveSessionUI = vi.fn(() => {\n\t\t\tevents.push(\"resetInteractiveSessionUI\");\n\t\t});\n\t\tconst showStatus = vi.fn(() => {\n\t\t\tevents.push(\"showStatus\");\n\t\t});\n\n\t\tconst mode = Object.assign(Object.create(InteractiveMode.prototype), {\n\t\t\tsession: { switchSession },\n\t\t\tloadingAnimation: { dispose },\n\t\t\tclearStatusOwner,\n\t\t\tpendingMessagesContainer: { clear: clearPendingMessages },\n\t\t\tcompactionQueuedMessages: [\"queued\"],\n\t\t\tresetInteractiveSessionUI,\n\t\t\tshowStatus,\n\t\t}) as ResumeHarness;\n\n\t\tconst resumePromise = mode.handleResumeSession(\"/tmp/resumed-session.jsonl\");\n\n\t\texpect(switchSession).toHaveBeenCalledWith(\"/tmp/resumed-session.jsonl\");\n\t\texpect(resetInteractiveSessionUI).not.toHaveBeenCalled();\n\t\texpect(showStatus).not.toHaveBeenCalled();\n\n\t\tresolveSwitch?.(true);\n\t\tawait resumePromise;\n\n\t\texpect(events).toEqual([\n\t\t\t\"disposeLoading\",\n\t\t\t\"clearStatusOwner\",\n\t\t\t\"switch:/tmp/resumed-session.jsonl\",\n\t\t\t\"clearPendingMessages\",\n\t\t\t\"resetInteractiveSessionUI\",\n\t\t\t\"showStatus\",\n\t\t]);\n\t\texpect(mode.compactionQueuedMessages).toEqual([]);\n\t\texpect(resetInteractiveSessionUI).toHaveBeenCalledWith(true);\n\t\texpect(showStatus).toHaveBeenCalledWith(\"Resumed session\");\n\t});\n\n\tit(\"preserves local UI state and avoids success signals when resume is cancelled before switching\", async () => {\n\t\tconst events: string[] = [];\n\t\tconst switchSession = vi.fn<(sessionPath: string) => Promise<boolean>>((sessionPath: string) => {\n\t\t\tevents.push(`switch:${sessionPath}`);\n\t\t\treturn Promise.resolve(false);\n\t\t});\n\t\tconst dispose = vi.fn(() => {\n\t\t\tevents.push(\"disposeLoading\");\n\t\t});\n\t\tconst clearStatusOwner = vi.fn(() => {\n\t\t\tevents.push(\"clearStatusOwner\");\n\t\t});\n\t\tconst clearPendingMessages = vi.fn(() => {\n\t\t\tevents.push(\"clearPendingMessages\");\n\t\t});\n\t\tconst resetInteractiveSessionUI = vi.fn(() => {\n\t\t\tevents.push(\"resetInteractiveSessionUI\");\n\t\t});\n\t\tconst showStatus = vi.fn(() => {\n\t\t\tevents.push(\"showStatus\");\n\t\t});\n\n\t\tconst mode = Object.assign(Object.create(InteractiveMode.prototype), {\n\t\t\tsession: { switchSession },\n\t\t\tloadingAnimation: { dispose },\n\t\t\tclearStatusOwner,\n\t\t\tpendingMessagesContainer: { clear: clearPendingMessages },\n\t\t\tcompactionQueuedMessages: [\"queued\"],\n\t\t\tresetInteractiveSessionUI,\n\t\t\tshowStatus,\n\t\t}) as ResumeHarness;\n\n\t\tawait expect(mode.handleResumeSession(\"/tmp/cancelled-session.jsonl\")).resolves.toBeUndefined();\n\n\t\texpect(events).toEqual([\"disposeLoading\", \"clearStatusOwner\", \"switch:/tmp/cancelled-session.jsonl\"]);\n\t\texpect(mode.compactionQueuedMessages).toEqual([\"queued\"]);\n\t\texpect(clearPendingMessages).not.toHaveBeenCalled();\n\t\texpect(resetInteractiveSessionUI).not.toHaveBeenCalled();\n\t\texpect(showStatus).not.toHaveBeenCalled();\n\t});\n\n\tit(\"preserves local UI state and avoids success signals when resume fails\", async () => {\n\t\tconst events: string[] = [];\n\t\tconst switchSession = vi.fn<(sessionPath: string) => Promise<boolean>>((sessionPath: string) => {\n\t\t\tevents.push(`switch:${sessionPath}`);\n\t\t\treturn Promise.reject(new Error(\"Session not found\"));\n\t\t});\n\t\tconst dispose = vi.fn(() => {\n\t\t\tevents.push(\"disposeLoading\");\n\t\t});\n\t\tconst clearStatusOwner = vi.fn(() => {\n\t\t\tevents.push(\"clearStatusOwner\");\n\t\t});\n\t\tconst clearPendingMessages = vi.fn(() => {\n\t\t\tevents.push(\"clearPendingMessages\");\n\t\t});\n\t\tconst resetInteractiveSessionUI = vi.fn(() => {\n\t\t\tevents.push(\"resetInteractiveSessionUI\");\n\t\t});\n\t\tconst showStatus = vi.fn(() => {\n\t\t\tevents.push(\"showStatus\");\n\t\t});\n\n\t\tconst mode = Object.assign(Object.create(InteractiveMode.prototype), {\n\t\t\tsession: { switchSession },\n\t\t\tloadingAnimation: { dispose },\n\t\t\tclearStatusOwner,\n\t\t\tpendingMessagesContainer: { clear: clearPendingMessages },\n\t\t\tcompactionQueuedMessages: [\"queued\"],\n\t\t\tresetInteractiveSessionUI,\n\t\t\tshowStatus,\n\t\t}) as ResumeHarness;\n\n\t\tawait expect(mode.handleResumeSession(\"/tmp/missing-session.jsonl\")).rejects.toThrow(\"Session not found\");\n\n\t\texpect(events).toEqual([\"disposeLoading\", \"clearStatusOwner\", \"switch:/tmp/missing-session.jsonl\"]);\n\t\texpect(mode.compactionQueuedMessages).toEqual([\"queued\"]);\n\t\texpect(clearPendingMessages).not.toHaveBeenCalled();\n\t\texpect(resetInteractiveSessionUI).not.toHaveBeenCalled();\n\t\texpect(showStatus).not.toHaveBeenCalled();\n\t});\n});\n"]}