import { beforeEach, describe, expect, it, vi } from "vite-plus/test"; const { confirmMock, readLocalApiMock } = vi.hoisted(() => { const confirmMock = vi.fn<(message: string, options?: unknown) => Promise>(); const readLocalApiMock = vi.fn< () => | { dialogs: { confirm: (message: string, options?: unknown) => Promise }; } | undefined >(); return { confirmMock, readLocalApiMock }; }); vi.mock("~/localApi", () => ({ readLocalApi: () => readLocalApiMock(), })); import { confirmTerminalClose, isTerminalCloseConfirmPending } from "./terminalCloseConfirm"; describe("terminal close confirmation", () => { beforeEach(() => { confirmMock.mockReset(); readLocalApiMock.mockReset(); readLocalApiMock.mockReturnValue({ dialogs: { confirm: confirmMock } }); }); it("tracks pending state until the confirmation settles", async () => { let settle: (value: boolean) => void = () => undefined; confirmMock.mockImplementation(() => new Promise((resolve) => (settle = resolve))); expect(isTerminalCloseConfirmPending()).toBe(false); const confirmation = confirmTerminalClose(["Terminal 1"]); expect(isTerminalCloseConfirmPending()).toBe(true); settle(true); await expect(confirmation).resolves.toBe(true); expect(isTerminalCloseConfirmPending()).toBe(false); }); it("clears pending state and resolves false when the dialog rejects", async () => { let reject: (reason?: unknown) => void = () => undefined; confirmMock.mockImplementation( () => new Promise((_resolve, rejectPromise) => { reject = rejectPromise; }), ); const confirmation = confirmTerminalClose(["Terminal 1"]); expect(isTerminalCloseConfirmPending()).toBe(true); reject(new Error("dialog failed")); await expect(confirmation).resolves.toBe(false); expect(isTerminalCloseConfirmPending()).toBe(false); }); it("names every terminal in a multi-terminal close", async () => { confirmMock.mockResolvedValue(true); await expect(confirmTerminalClose(["Terminal 1", "Development server"])).resolves.toBe(true); expect(confirmMock).toHaveBeenCalledWith( [ "Close 2 terminals?", 'This stops their running processes and clears their histories: "Terminal 1", "Development server".', ].join("\n"), { variant: "destructive" }, ); }); it("closes without prompting when no local API is available", async () => { readLocalApiMock.mockReturnValue(undefined); await expect(confirmTerminalClose(["Terminal 1"])).resolves.toBe(true); expect(confirmMock).not.toHaveBeenCalled(); }); });