import { describe, it, expect, vi, beforeEach } from "vitest"; import { ExitGuardManagerImpl } from "./exit-guard-manager"; describe("ExitGuardManagerImpl", () => { let manager: ExitGuardManagerImpl; beforeEach(() => { manager = new ExitGuardManagerImpl(); }); it("canExit resolves true when no guards are registered", async () => { await expect(manager.canExit()).resolves.toBe(true); }); it("canExit resolves true when every guard returns true", async () => { manager.register("a", async () => true); manager.register("b", async () => true); await expect(manager.canExit()).resolves.toBe(true); }); it("canExit resolves false when any guard returns false", async () => { manager.register("a", async () => true); manager.register("b", async () => false); await expect(manager.canExit()).resolves.toBe(false); }); it("canExit short-circuits and does not run guards after a false", async () => { const guardA = vi.fn(async () => false); const guardB = vi.fn(async () => true); manager.register("a", guardA); manager.register("b", guardB); await manager.canExit(); expect(guardA).toHaveBeenCalled(); expect(guardB).not.toHaveBeenCalled(); }); it("unregister removes the guard", async () => { const guard = vi.fn(async () => false); manager.register("a", guard); manager.unregister("a"); await expect(manager.canExit()).resolves.toBe(true); expect(guard).not.toHaveBeenCalled(); }); it("register overwrites an existing guard with the same id", async () => { manager.register("a", async () => false); manager.register("a", async () => true); await expect(manager.canExit()).resolves.toBe(true); }); it("swallows errors in guards and continues with the remaining ones", async () => { const consoleErrorSpy = vi.spyOn(console, "error").mockImplementation(() => {}); const failing = vi.fn(async () => { throw new Error("boom"); }); const allowing = vi.fn(async () => true); manager.register("a", failing); manager.register("b", allowing); await expect(manager.canExit()).resolves.toBe(true); expect(failing).toHaveBeenCalled(); expect(allowing).toHaveBeenCalled(); expect(consoleErrorSpy).toHaveBeenCalledWith("Exit guard failed:", expect.any(Error)); consoleErrorSpy.mockRestore(); }); });