import { describe, it, expect, beforeEach, vi, afterEach } from "vitest"; import { CookieSessionStore, type CookieSession } from "../cookie-session-store.js"; describe("CookieSessionStore", () => { let store: CookieSessionStore; beforeEach(() => { store = new CookieSessionStore(); vi.useFakeTimers(); }); afterEach(() => { store.destroy(); vi.useRealTimers(); }); it("stores and retrieves cookie sessions", () => { const session: CookieSession = { did: "did:plc:test123", handle: "testuser.test", expiresAt: new Date(Date.now() + 7 * 24 * 3600 * 1000), // 7 days from now createdAt: new Date(), }; store.set("cookie-token-1", session); const retrieved = store.get("cookie-token-1"); expect(retrieved).toEqual(session); }); it("returns null for non-existent tokens", () => { const result = store.get("nonexistent-token"); expect(result).toBeNull(); }); it("enforces expiresAt boundary correctly", () => { const now = Date.now(); const session: CookieSession = { did: "did:plc:test123", handle: "testuser.test", expiresAt: new Date(now + 3600 * 1000), // Expires in 1 hour createdAt: new Date(now), }; store.set("cookie-token-1", session); // Before expiration - session available vi.advanceTimersByTime(3599 * 1000); // 59 minutes 59 seconds expect(store.get("cookie-token-1")).toEqual(session); // After expiration - session should be evicted vi.advanceTimersByTime(2 * 1000); // Total: 1 hour 1 second expect(store.get("cookie-token-1")).toBeNull(); }); it("handles sessions without handle field", () => { const session: CookieSession = { did: "did:plc:test123", // No handle field expiresAt: new Date(Date.now() + 7 * 24 * 3600 * 1000), createdAt: new Date(), }; store.set("cookie-token-1", session); const retrieved = store.get("cookie-token-1"); expect(retrieved).toEqual(session); expect(retrieved?.handle).toBeUndefined(); }); it("deletes sessions immediately", () => { const session: CookieSession = { did: "did:plc:test123", handle: "testuser.test", expiresAt: new Date(Date.now() + 7 * 24 * 3600 * 1000), createdAt: new Date(), }; store.set("cookie-token-1", session); expect(store.get("cookie-token-1")).toEqual(session); store.delete("cookie-token-1"); expect(store.get("cookie-token-1")).toBeNull(); }); it("handles multiple sessions independently", () => { const session1: CookieSession = { did: "did:plc:user1", handle: "user1.test", expiresAt: new Date(Date.now() + 7 * 24 * 3600 * 1000), createdAt: new Date(), }; const session2: CookieSession = { did: "did:plc:user2", handle: "user2.test", expiresAt: new Date(Date.now() + 14 * 24 * 3600 * 1000), // Different expiration createdAt: new Date(), }; store.set("token1", session1); store.set("token2", session2); expect(store.get("token1")).toEqual(session1); expect(store.get("token2")).toEqual(session2); store.delete("token1"); expect(store.get("token1")).toBeNull(); expect(store.get("token2")).toEqual(session2); }); it("correctly compares Date objects for expiration", () => { // Test the Date comparison logic works correctly const now = new Date(); const past = new Date(now.getTime() - 1000); // 1 second ago const future = new Date(now.getTime() + 1000); // 1 second from now const expiredSession: CookieSession = { did: "did:plc:expired", expiresAt: past, createdAt: new Date(past.getTime() - 3600 * 1000), }; const validSession: CookieSession = { did: "did:plc:valid", expiresAt: future, createdAt: now, }; store.set("expired", expiredSession); store.set("valid", validSession); // Expired session should return null expect(store.get("expired")).toBeNull(); // Valid session should be available expect(store.get("valid")).toEqual(validSession); }); it("maps undefined to null for missing entries", () => { // The adapter should return null (not undefined) for missing entries // to match the public API contract const result = store.get("missing-key"); expect(result).toBeNull(); expect(result).not.toBeUndefined(); }); });