import { EventEmitter } from "node:events"; import { afterEach, describe, expect, it, vi } from "vitest"; const spawnMock = vi.hoisted(() => vi.fn()); const execFileMock = vi.hoisted(() => vi.fn()); vi.mock("node:child_process", async (importOriginal) => { const actual = await importOriginal(); return { ...actual, spawn: spawnMock, execFile: execFileMock, }; }); import { runCommandWithTimeout, runExec } from "./exec.js"; type MockChild = EventEmitter & { stdout: EventEmitter; stderr: EventEmitter; stdin: { write: ReturnType; end: ReturnType }; kill: ReturnType; pid?: number; killed?: boolean; }; function createMockChild(params?: { code?: number; signal?: NodeJS.Signals | null }): MockChild { const child = new EventEmitter() as MockChild; child.stdout = new EventEmitter(); child.stderr = new EventEmitter(); child.stdin = { write: vi.fn(), end: vi.fn(), }; child.kill = vi.fn(() => true); child.pid = 1234; child.killed = false; queueMicrotask(() => { child.emit("close", params?.code ?? 0, params?.signal ?? null); }); return child; } type SpawnCall = [string, string[], Record]; type ExecCall = [ string, string[], Record, (err: Error | null, stdout: string, stderr: string) => void, ]; function expectCmdWrappedInvocation(params: { captured: SpawnCall | ExecCall | undefined; expectedComSpec: string; }) { if (!params.captured) { throw new Error("expected command wrapper to be called"); } expect(params.captured[0]).toBe(params.expectedComSpec); expect(params.captured[1].slice(0, 3)).toEqual(["/d", "/s", "/c"]); expect(params.captured[1][3]).toContain("pnpm.cmd --version"); expect(params.captured[2].windowsVerbatimArguments).toBe(true); } describe("windows command wrapper behavior", () => { afterEach(() => { spawnMock.mockReset(); execFileMock.mockReset(); vi.restoreAllMocks(); }); it("wraps .cmd commands via cmd.exe in runCommandWithTimeout", async () => { const platformSpy = vi.spyOn(process, "platform", "get").mockReturnValue("win32"); const expectedComSpec = process.env.ComSpec ?? "cmd.exe"; spawnMock.mockImplementation( (_command: string, _args: string[], _options: Record) => createMockChild(), ); try { const result = await runCommandWithTimeout(["pnpm", "--version"], { timeoutMs: 1000 }); expect(result.code).toBe(0); const captured = spawnMock.mock.calls[0] as SpawnCall | undefined; expectCmdWrappedInvocation({ captured, expectedComSpec }); } finally { platformSpy.mockRestore(); } }); it("uses cmd.exe wrapper with windowsVerbatimArguments in runExec for .cmd shims", async () => { const platformSpy = vi.spyOn(process, "platform", "get").mockReturnValue("win32"); const expectedComSpec = process.env.ComSpec ?? "cmd.exe"; execFileMock.mockImplementation( ( _command: string, _args: string[], _options: Record, cb: (err: Error | null, stdout: string, stderr: string) => void, ) => { cb(null, "ok", ""); }, ); try { await runExec("pnpm", ["--version"], 1000); const captured = execFileMock.mock.calls[0] as ExecCall | undefined; expectCmdWrappedInvocation({ captured, expectedComSpec }); } finally { platformSpy.mockRestore(); } }); });