import { describe, expect, it, vi } from "vitest"; import { forwardSignalToVitestProcessGroup, installVitestProcessGroupCleanup, resolveVitestProcessGroupSignalTarget, shouldUseDetachedVitestProcessGroup, } from "../../scripts/vitest-process-group.mjs"; describe("vitest process group helpers", () => { it("uses detached process groups on non-Windows hosts", () => { expect(shouldUseDetachedVitestProcessGroup("darwin")).toBe(true); expect(shouldUseDetachedVitestProcessGroup("linux")).toBe(true); expect(shouldUseDetachedVitestProcessGroup("win32")).toBe(false); }); it("targets the process group on Unix and the direct pid on Windows", () => { expect(resolveVitestProcessGroupSignalTarget({ childPid: 4200, platform: "darwin" })).toBe( -4200, ); expect(resolveVitestProcessGroupSignalTarget({ childPid: 4200, platform: "win32" })).toBe(4200); expect(resolveVitestProcessGroupSignalTarget({ childPid: undefined, platform: "darwin" })).toBe( null, ); }); it("forwards signals to the computed target and ignores ESRCH", () => { const kill = vi.fn(); expect( forwardSignalToVitestProcessGroup({ child: { pid: 4200 }, signal: "SIGTERM", platform: "darwin", kill, }), ).toBe(true); expect(kill).toHaveBeenCalledWith(-4200, "SIGTERM"); kill.mockImplementationOnce(() => { const error = new Error("gone") as NodeJS.ErrnoException; error.code = "ESRCH"; throw error; }); expect( forwardSignalToVitestProcessGroup({ child: { pid: 4200 }, signal: "SIGTERM", platform: "darwin", kill, }), ).toBe(false); }); it("installs and removes process cleanup listeners", () => { const listeners = new Map void>>(); const fakeProcess = { on(event: string, handler: () => void) { const set = listeners.get(event) ?? new Set(); set.add(handler); listeners.set(event, set); }, off(event: string, handler: () => void) { listeners.get(event)?.delete(handler); }, }; const kill = vi.fn(); const teardown = installVitestProcessGroupCleanup({ child: { pid: 4200 }, processObject: fakeProcess as unknown as NodeJS.Process, platform: "darwin", kill, }); expect(listeners.get("SIGINT")?.size).toBe(1); expect(listeners.get("SIGTERM")?.size).toBe(1); expect(listeners.get("exit")?.size).toBe(1); listeners.get("SIGTERM")?.values().next().value?.(); expect(kill).toHaveBeenCalledWith(-4200, "SIGTERM"); teardown(); expect(listeners.get("SIGINT")?.size ?? 0).toBe(0); expect(listeners.get("SIGTERM")?.size ?? 0).toBe(0); expect(listeners.get("exit")?.size ?? 0).toBe(0); }); });