import { beforeAll, beforeEach, describe, expect, it, vi } from "vitest"; const randomMocks = vi.hoisted(() => ({ generateSecureInt: vi.fn(), })); vi.mock("../infra/secure-random.js", () => ({ generateSecureInt: randomMocks.generateSecureInt, })); let createSessionSlug: typeof import("./session-slug.js").createSessionSlug; beforeAll(async () => { ({ createSessionSlug } = await import("./session-slug.js")); }); describe("session slug", () => { beforeEach(() => { randomMocks.generateSecureInt.mockReset(); }); it("generates a two-word slug by default", () => { randomMocks.generateSecureInt.mockReturnValue(0); const slug = createSessionSlug(); expect(slug).toBe("amber-atlas"); }); it("adds a numeric suffix when the base slug is taken", () => { randomMocks.generateSecureInt.mockReturnValue(0); const slug = createSessionSlug((id) => id === "amber-atlas"); expect(slug).toBe("amber-atlas-2"); }); it("falls back to three words when collisions persist", () => { randomMocks.generateSecureInt.mockReturnValue(0); const slug = createSessionSlug((id) => /^amber-atlas(-\d+)?$/.test(id)); expect(slug).toBe("amber-atlas-atlas"); }); it("uses secure fallback suffix entropy when word collisions persist", () => { randomMocks.generateSecureInt.mockReturnValue(0); const nowSpy = vi.spyOn(Date, "now").mockReturnValue(1_717_171_717_171); const slug = createSessionSlug( (id) => /^amber-atlas(?:-\d+)?$/.test(id) || /^amber-atlas-atlas(?:-\d+)?$/.test(id), ); expect(slug).toBe("amber-atlas-atlas-aaa"); nowSpy.mockRestore(); }); });