import { beforeEach, describe, expect, mock, test } from "bun:test"; mock.module("cloudflare:workers", () => ({ env: { PUBLIC_URL: "https://forge.example.com", SECRETS_KEY: "k".repeat(32) }, waitUntil: () => undefined, })); const { memoryScopes } = await import("../scoped-db/testing"); let scopes = memoryScopes(); mock.module("../scoped-db", () => ({ accountDb: (id: string) => scopes.accountDb(id), repoDb: (id: string) => scopes.repoDb(id), stmt: scopes.module.stmt, })); mock.module("../db", () => ({ first: async () => null, run: async () => ({ meta: { changes: 0 } }), all: async () => [], stmt: () => ({}), chunks: (items: T[]) => [items], placeholders: (count: number) => Array(count).fill("?").join(","), })); const { emailFooter, userForUnsubscribeToken, revokeUnsubscribeTokens, canUnsubscribe } = await import("./prefs"); function tokenOf(url: string | null): string { return new URL(url ?? "").searchParams.get("token") ?? ""; } beforeEach(() => { scopes = memoryScopes(); }); describe("unsubscribe tokens", () => { test("a fresh token resolves to its user for its own category only", async () => { const footer = await emailFooter("u1", "ci"); const token = tokenOf(footer.unsubscribeUrl); expect(token).not.toBe(""); expect(await userForUnsubscribeToken(token, "ci")).toBe("u1"); expect(await userForUnsubscribeToken(token, "deploy")).toBeNull(); expect(await userForUnsubscribeToken(token, "security_alert")).toBeNull(); }); test("tampered payload or signature is rejected", async () => { const token = tokenOf((await emailFooter("u1", "ci")).unsubscribeUrl); const [payload, signature] = token.split("."); const flipped = signature?.startsWith("0") ? `1${signature.slice(1)}` : `0${signature?.slice(1)}`; expect(await userForUnsubscribeToken(`${payload}.${flipped}`, "ci")).toBeNull(); expect(await userForUnsubscribeToken(`${payload}x.${signature}`, "ci")).toBeNull(); expect(await userForUnsubscribeToken("garbage", "ci")).toBeNull(); }); test("tokens expire after 30 days", async () => { const realNow = Date.now; const token = tokenOf((await emailFooter("u1", "ci")).unsubscribeUrl); Date.now = () => realNow() + 31 * 24 * 60 * 60 * 1000; try { expect(await userForUnsubscribeToken(token, "ci")).toBeNull(); } finally { Date.now = realNow; } }); test("revoking the per-user secret invalidates earlier links", async () => { const token = tokenOf((await emailFooter("u1", "ci")).unsubscribeUrl); await revokeUnsubscribeTokens("u1"); expect(await userForUnsubscribeToken(token, "ci")).toBeNull(); }); test("security alert mail has no unsubscribe link", async () => { expect(canUnsubscribe("security_alert")).toBe(false); expect((await emailFooter("u1", "security_alert")).unsubscribeUrl).toBeNull(); }); });