import { Request } from "express"; import { describe, expect, it } from "vitest"; import { CSRF_CLIENT_COOKIE_NAME, getCsrfClientCookieValue, getCsrfValidationClientIds, getLegacyClientId, parseCookies, } from "./csrfClient"; const makeRequest = (overrides?: Partial): Request => ({ headers: { cookie: "", "user-agent": "UnitTestAgent/1.0", }, ip: "203.0.113.10", connection: { remoteAddress: "198.51.100.8" }, ...overrides, }) as unknown as Request; describe("csrfClient helpers", () => { it("parses cookies and tolerates bad encoding", () => { const parsed = parseCookies("a=1; b=hello%20world; c=%E0%A4%A"); expect(parsed).toEqual({ a: "1", b: "hello world", c: "%E0%A4%A", }); }); it("reads only valid csrf cookie values", () => { const validReq = makeRequest({ headers: { cookie: `${CSRF_CLIENT_COOKIE_NAME}=abcDEF1234567890_-`, }, }); expect(getCsrfClientCookieValue(validReq)).toBe("abcDEF1234567890_-"); const invalidReq = makeRequest({ headers: { cookie: `${CSRF_CLIENT_COOKIE_NAME}=bad!`, }, }); expect(getCsrfClientCookieValue(invalidReq)).toBeNull(); }); it("builds legacy client id from IP + user agent and truncates", () => { const longAgent = "x".repeat(600); const req = makeRequest({ headers: { "user-agent": longAgent, }, }); const id = getLegacyClientId(req); expect(id.startsWith("203.0.113.10:")).toBe(true); expect(id.length).toBeLessThanOrEqual(256); }); it("returns validation candidates with cookie id first when present", () => { const req = makeRequest({ headers: { cookie: `${CSRF_CLIENT_COOKIE_NAME}=cookieToken123456`, "user-agent": "Agent", }, ip: "10.0.0.1", }); const candidates = getCsrfValidationClientIds(req); expect(candidates[0]).toBe("cookie:cookieToken123456"); expect(candidates[1]).toContain("10.0.0.1:Agent"); expect(new Set(candidates).size).toBe(candidates.length); }); });