import { beforeEach, describe, expect, it, vi } from "vitest"; import { generateSsoTicket } from "./sso-ticket"; const UUID_RE = /^[0-9a-f]{8}-[0-9a-f]{4}-4[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/; const mockWhere = vi.hoisted(() => vi.fn().mockResolvedValue(undefined)); const mockSet = vi.hoisted(() => vi.fn(() => ({ where: mockWhere }))); const mockUpdate = vi.hoisted(() => vi.fn(() => ({ set: mockSet }))); vi.mock("@/lib/db", () => ({ db: { update: mockUpdate }, User: { id: "id" }, })); describe("generateSsoTicket", () => { it("uses '{hotelName-without-spaces}-{uuidv4}'", () => { const t = generateSsoTicket("Atom Hotel"); expect(t.startsWith("AtomHotel-")).toBe(true); expect(UUID_RE.test(t.slice("AtomHotel-".length))).toBe(true); }); it("strips every space in the hotel name", () => { expect(generateSsoTicket("My Cool Hotel").startsWith("MyCoolHotel-")).toBe( true, ); }); it("produces a fresh ticket each call", () => { expect(generateSsoTicket("Atom")).not.toBe(generateSsoTicket("Atom")); }); }); describe("issueSsoTicket", () => { beforeEach(() => { vi.clearAllMocks(); mockSet.mockReturnValue({ where: mockWhere }); mockUpdate.mockReturnValue({ set: mockSet }); mockWhere.mockResolvedValue(undefined); }); it("writes auth_ticket AND ip_current and returns the ticket", async () => { const { issueSsoTicket } = await import("./sso-ticket"); const ticket = await issueSsoTicket(42, "Atom Hotel", "1.2.3.4"); expect(ticket.startsWith("AtomHotel-")).toBe(true); expect(mockUpdate).toHaveBeenCalled(); expect(mockSet).toHaveBeenCalledWith({ authTicket: ticket, ipCurrent: "1.2.3.4", }); expect(mockWhere).toHaveBeenCalled(); }); });