import { describe, expect, it } from "vitest"; import { decodeTokenExp, getSessionExpMs } from "@/lib/session/token"; /** Build a JWT-shaped string with the given payload object. */ function makeToken(payload: Record): string { const header = btoa(JSON.stringify({ alg: "HS256", typ: "JWT" })); const body = btoa(JSON.stringify(payload)); return `${header}.${body}.signature`; } describe("decodeTokenExp", () => { it("returns the numeric exp claim from a well-formed token", () => { const exp = 1_800_000_000; expect(decodeTokenExp(makeToken({ sub: "1", exp }))).toBe(exp); }); it("returns null when the token has no payload segment", () => { expect(decodeTokenExp("header")).toBeNull(); expect(decodeTokenExp("")).toBeNull(); }); it("returns null when the payload is not valid base64 JSON", () => { expect(decodeTokenExp("header.not-json.signature")).toBeNull(); }); it("returns null when exp is missing or not a finite number", () => { expect(decodeTokenExp(makeToken({ sub: "1" }))).toBeNull(); expect(decodeTokenExp(makeToken({ exp: "soon" }))).toBeNull(); expect(decodeTokenExp(makeToken({ exp: null }))).toBeNull(); expect(decodeTokenExp(makeToken({ exp: Number.NaN }))).toBeNull(); }); it("handles URL-safe base64 (JWT padding) in the payload", () => { // A payload whose base64 would contain - and _ after URL-safe encoding. const payload = { exp: 1_800_000_000, data: "a+b/c=d" }; const body = btoa(JSON.stringify(payload)).replace(/\+/g, "-").replace(/\//g, "_"); const token = `header.${body}.signature`; expect(decodeTokenExp(token)).toBe(1_800_000_000); }); }); describe("getSessionExpMs", () => { const exp = 1_800_000_000; const token = makeToken({ sub: "1", exp }); it("returns the exp in milliseconds from the cookie header", () => { const headers = { get: (name: string) => (name === "cookie" ? `payload-token=${token}` : null) }; expect(getSessionExpMs(headers)).toBe(exp * 1000); }); it("returns null when there is no cookie header", () => { const headers = { get: () => null }; expect(getSessionExpMs(headers)).toBeNull(); }); it("returns null when the payload-token cookie is absent", () => { const headers = { get: () => "other=value" }; expect(getSessionExpMs(headers)).toBeNull(); }); it("parses the token among other cookies", () => { const headers = { get: () => `foo=1; payload-token=${token}; bar=2` }; expect(getSessionExpMs(headers)).toBe(exp * 1000); }); it("returns null when the token is malformed", () => { const headers = { get: () => "payload-token=not-a-jwt" }; expect(getSessionExpMs(headers)).toBeNull(); }); });