import { describe, it, expect, vi, beforeEach } from "vitest"; // Mock next/headers to provide a simple in-memory cookie store vi.mock("next/headers", () => { let store = new Map(); return { cookies() { return { get(name) { const entry = store.get(name); if (!entry) return undefined; return { name, value: entry.value }; }, set(name, value, options) { store.set(name, { value, options }); }, }; }, __cookieStore: { clear() { store = new Map(); }, dump() { return store; }, }, }; }); // Import after the mock so the module under test uses the mocked cookies() import { createSession, getSession, destroySession, SESSION_COOKIE_NAME, SESSION_MAX_AGE_SECONDS, } from "./session"; import { __cookieStore } from "next/headers"; describe("auth session utilities", () => { beforeEach(() => { __cookieStore.clear(); process.env.SESSION_SECRET = "x".repeat(64); process.env.NODE_ENV = "test"; }); it("creates a session cookie with a signed JWT", async () => { const jwt = await createSession({ userId: "user123", role: "branch", branchId: "NL01", }); expect(typeof jwt).toBe("string"); expect(jwt.length).toBeGreaterThan(10); const store = __cookieStore.dump(); const cookie = store.get(SESSION_COOKIE_NAME); expect(cookie).toBeDefined(); expect(cookie.value).toBe(jwt); expect(cookie.options).toMatchObject({ httpOnly: true, secure: false, // NODE_ENV = "test" sameSite: "lax", path: "/", maxAge: SESSION_MAX_AGE_SECONDS, }); }); it("reads a valid session from cookie", async () => { await createSession({ userId: "user456", role: "admin", branchId: null, }); const session = await getSession(); expect(session).toEqual({ userId: "user456", role: "admin", branchId: null, }); }); it("returns null when no session cookie is present", async () => { const session = await getSession(); expect(session).toBeNull(); }); it("returns null and clears cookie when token is invalid", async () => { // Manually set an invalid JWT value const store = __cookieStore.dump(); store.set(SESSION_COOKIE_NAME, { value: "not-a-valid-jwt", options: { httpOnly: true, secure: false, sameSite: "lax", path: "/", maxAge: SESSION_MAX_AGE_SECONDS, }, }); const session = await getSession(); expect(session).toBeNull(); const updatedStore = __cookieStore.dump(); const cookie = updatedStore.get(SESSION_COOKIE_NAME); expect(cookie).toBeDefined(); expect(cookie.value).toBe(""); expect(cookie.options.maxAge).toBe(0); }); it("destroySession clears the session cookie when it exists", async () => { await createSession({ userId: "user789", role: "branch", branchId: "NL02", }); await destroySession(); const store = __cookieStore.dump(); const cookie = store.get(SESSION_COOKIE_NAME); expect(cookie).toBeDefined(); expect(cookie.value).toBe(""); expect(cookie.options.maxAge).toBe(0); }); it("destroySession sets an empty cookie even if none existed before", async () => { await destroySession(); const store = __cookieStore.dump(); const cookie = store.get(SESSION_COOKIE_NAME); expect(cookie).toBeDefined(); expect(cookie.value).toBe(""); expect(cookie.options.maxAge).toBe(0); }); });