import { afterEach, beforeAll, describe, expect, it, vi } from "bun:test"; import { CommandController } from "@oh-my-pi/pi-coding-agent/modes/controllers/command-controller"; import { getThemeByName, setThemeInstance } from "@oh-my-pi/pi-coding-agent/modes/theme/theme"; import type { InteractiveModeContext } from "@oh-my-pi/pi-coding-agent/modes/types"; function createContainer() { return { children: [] as unknown[], addChild(child: unknown) { this.children.push(child); }, clear() { this.children = []; }, }; } describe("/handoff command", () => { beforeAll(async () => { const theme = await getThemeByName("dark"); if (!theme) throw new Error("Expected dark theme"); setThemeInstance(theme); }); afterEach(() => { vi.restoreAllMocks(); }); it("shows a cancellable loader while handoff generation is running", async () => { const handoffStarted = Promise.withResolvers(); const handoffDone = Promise.withResolvers<{ document: string }>(); const originalOnEscape = vi.fn(); const statusContainer = createContainer(); const chatContainer = createContainer(); const abortHandoff = vi.fn(); const requestRender = vi.fn(); const ctx = { sessionManager: { getEntries: () => [{ type: "message" }, { type: "message" }], }, session: { handoff: vi.fn(() => { handoffStarted.resolve(); return handoffDone.promise; }), abortHandoff, }, loadingAnimation: undefined, statusContainer, chatContainer, ui: { requestRender }, editor: { onEscape: originalOnEscape }, rebuildChatFromMessages: vi.fn(), statusLine: { invalidate: vi.fn() }, updateEditorTopBorder: vi.fn(), updateEditorBorderColor: vi.fn(), reloadTodos: vi.fn(async () => undefined), showStatus: vi.fn(), showWarning: vi.fn(), showError: vi.fn(), } as unknown as InteractiveModeContext; const controller = new CommandController(ctx); const commandPromise = controller.handleHandoffCommand("focus on tests"); await handoffStarted.promise; expect(statusContainer.children).toHaveLength(1); expect(ctx.editor.onEscape).not.toBe(originalOnEscape); ctx.editor.onEscape?.(); expect(abortHandoff).toHaveBeenCalledTimes(1); handoffDone.resolve({ document: "## Goal\nContinue" }); await commandPromise; expect(statusContainer.children).toHaveLength(0); expect(ctx.editor.onEscape).toBe(originalOnEscape); expect(ctx.session.handoff).toHaveBeenCalledWith("focus on tests"); }); });