import { test } from "node:test"; import assert from "node:assert/strict"; import { resetReaders } from "../lib/archive/readers"; import { fetchTranscript } from "./transcriptCache"; import { fetchSubs } from "./subsCache"; import { fetchPost, fetchThread, peekPost } from "./postsCache"; import { fetchDigest, hasDigest } from "./digestCache"; import { fetchDuplicates, fetchDuplicateReport } from "./duplicatesCache"; import { fetchAliases } from "./aliasesCache"; // ─── the eight caches as WRAPPERS ─── // // Each of these used to hand-roll the manifest -> slugToPage -> page walk; each // now calls the shared ArchiveReader. What must survive that move is the memo // behaviour, because it is what makes the viewer usable: a hit returns the same // promise (so N components asking for the same video do not each re-render on a // different tick) and a miss costs ONE read of each document, not one per // caller and not one per record. // // So every test below counts fetches. The caches hold module-level state with // no reset hook — that is deliberate, it is a page-lifetime cache — so each // test uses its own channel slug and its own origin rather than trying to wipe // them. type Archive = { fetches: string[]; body: Map }; function installFetch(entries: Record): { archive: Archive; restore: () => void; } { const archive: Archive = { fetches: [], body: new Map(Object.entries(entries)), }; const real = globalThis.fetch; globalThis.fetch = (async (input: RequestInfo | URL) => { const url = String(input); archive.fetches.push(url); if (!archive.body.has(url)) { return new Response("not found", { status: 404, statusText: "Not Found" }); } return new Response(JSON.stringify(archive.body.get(url)), { status: 200 }); }) as typeof fetch; return { archive, restore: () => { globalThis.fetch = real; resetReaders(); }, }; } function count(archive: Archive, url: string): number { return archive.fetches.filter((u) => u === url).length; } test("transcriptCache: one manifest + one page, and the whole page is warmed", async () => { const { archive, restore } = installFetch({ "/transcripts/tc/manifest.json": { version: 1, slugToPage: { a: 0, b: 0 }, pageCount: 1, generatedAt: "", }, "/transcripts/tc/page-0000.json": [ { slug: "tc/a", id: "a", title: "A", cues: [] }, { slug: "tc/b", id: "b", title: "B", cues: [] }, ], }); try { // Two concurrent callers for the same id share one promise — not two reads // that happen to agree. const p1 = fetchTranscript("tc/a"); const p2 = fetchTranscript("tc/a"); assert.equal(p1, p2); assert.equal((await p1).title, "A"); // A hit resolves without touching the network at all. const after = archive.fetches.length; assert.equal((await fetchTranscript("tc/a")).title, "A"); assert.equal(archive.fetches.length, after); // And the OTHER record of the page we already paid for is a hit too: the // opportunistic warming is what makes a search over one channel cheap. assert.equal((await fetchTranscript("tc/b")).title, "B"); assert.equal(count(archive, "/transcripts/tc/manifest.json"), 1); assert.equal(count(archive, "/transcripts/tc/page-0000.json"), 1); assert.equal(archive.fetches.length, 2); } finally { restore(); } }); test("transcriptCache: a video the manifest does not list never costs a page read", async () => { const { archive, restore } = installFetch({ "/transcripts/tcmiss/manifest.json": { version: 1, slugToPage: {}, pageCount: 0, generatedAt: "", }, }); try { await assert.rejects(() => fetchTranscript("tcmiss/nope"), /Unknown transcript slug/); assert.deepEqual(archive.fetches, ["/transcripts/tcmiss/manifest.json"]); } finally { restore(); } }); test("subsCache: same walk, same sharing, over the subs tree", async () => { const { archive, restore } = installFetch({ "/subs/sc/manifest.json": { version: 1, slugToPage: { a: 0, b: 0 }, pageCount: 1, generatedAt: "", }, "/subs/sc/page-0000.json": [ { slug: "sc/a", id: "a", tracks: {} }, { slug: "sc/b", id: "b", tracks: {} }, ], }); try { const p1 = fetchSubs("sc/a"); assert.equal(fetchSubs("sc/a"), p1); assert.equal((await p1).id, "a"); assert.equal((await fetchSubs("sc/b")).id, "b"); assert.deepEqual(archive.fetches, [ "/subs/sc/manifest.json", "/subs/sc/page-0000.json", ]); } finally { restore(); } }); test("subsCache: an unreachable channel manifest is NOT memoised as absent", async () => { const { archive, restore } = installFetch({}); try { await assert.rejects(() => fetchSubs("scfail/a")); await assert.rejects(() => fetchSubs("scfail/a")); // Twice, because a failure is a failure and not an answer. The reader's own // tolerant subsManifest() would have cached `null` here and the panel would // stay empty for the session. assert.equal(count(archive, "/subs/scfail/manifest.json"), 2); } finally { restore(); } }); test("postsCache: a thread walks every page of the channel exactly once", async () => { const { archive, restore } = installFetch({ "/posts/pc/manifest.json": { version: 1, slugToPage: { p1: 0, p2: 1 }, pageCount: 2, generatedAt: "", }, "/posts/pc/page-0000.json": [ { slug: "pc/p1", id: "p1", threadId: "p1", createdAt: "2026-01-01" }, ], "/posts/pc/page-0001.json": [ { slug: "pc/p2", id: "p2", threadId: "p1", createdAt: "2026-01-02" }, ], }); try { assert.equal((await fetchPost("pc/p1")).id, "p1"); // Fetching the post warmed the page it came from, so peekPost is sync. assert.equal(peekPost("pc/p1")?.id, "p1"); const thread = await fetchThread("pc/p1"); assert.deepEqual( thread.map((t) => t.id), ["p1", "p2"], ); // A second thread read is free: the page memo is what stops fetchThread // re-downloading the whole channel per post opened. await fetchThread("pc/p1"); assert.equal(count(archive, "/posts/pc/manifest.json"), 1); assert.equal(count(archive, "/posts/pc/page-0000.json"), 1); assert.equal(count(archive, "/posts/pc/page-0001.json"), 1); } finally { restore(); } }); test("digestCache: a channel with no digests costs ONE 404, ever", async () => { const { archive, restore } = installFetch({}); try { assert.equal(await hasDigest("dcnone/a"), false); assert.equal(await fetchDigest("dcnone/a"), null); assert.equal(await fetchDigest("dcnone/b"), null); // The sparse layer's whole cost model: absence is an answer and is cached, // so opening video after video in an undigested channel is free. assert.equal(count(archive, "/digests/dcnone/manifest.json"), 1); } finally { restore(); } }); test("digestCache: present, page-warmed, and not-in-slugToPage means null not throw", async () => { const { archive, restore } = installFetch({ "/digests/dc/manifest.json": { version: 1, slugToPage: { a: 0, b: 0 }, pageCount: 1, pageHashes: ["h0"], generatedAt: "", }, "/digests/dc/page-0000.json": [ { slug: "dc/a", id: "a", chapters: [] }, { slug: "dc/b", id: "b", chapters: [] }, ], }); try { assert.equal(await hasDigest("dc/a"), true); assert.equal((await fetchDigest("dc/a"))?.id, "a"); assert.equal((await fetchDigest("dc/b"))?.id, "b"); // An undigested video in a digested channel: normal, and not an error. assert.equal(await hasDigest("dc/c"), false); assert.equal(await fetchDigest("dc/c"), null); assert.equal(count(archive, "/digests/dc/manifest.json"), 1); assert.equal(count(archive, "/digests/dc/page-0000.json"), 1); } finally { restore(); } }); test("duplicatesCache: absent is empty, present is a slug-keyed lookup", async () => { const absent = installFetch({}); try { assert.equal(await fetchDuplicateReport("https://dup-absent.example"), null); assert.equal((await fetchDuplicates("https://dup-absent.example")).size, 0); } finally { absent.restore(); } const O = "https://dup-present.example"; const present = installFetch({ [`${O}/duplicates.json`]: { clusters: [ { clusterId: "c1", videoRefs: [{ slug: "x/1" }, { slug: "y/2" }], }, ], }, }); try { const lookup = await fetchDuplicates(O); assert.equal(lookup.size, 2); assert.equal(lookup.get("x/1")?.clusterId, "c1"); assert.equal(lookup.get("y/2")?.clusterId, "c1"); assert.equal(count(present.archive, `${O}/duplicates.json`), 1); } finally { present.restore(); } }); test("aliasesCache: a 404 is an empty dictionary; a transport failure is rethrown", async () => { const missing = installFetch({}); try { assert.deepEqual(await fetchAliases("https://alias-404.example"), []); } finally { missing.restore(); } const present = installFetch({ "https://alias-ok.example/search-aliases.json": { aliases: [ { id: "kcup", label: "k cups", triggers: ["k cups"], suggestion: "(k|cake)[ -]?cup", useRegex: true, }, ], }, }); try { const aliases = await fetchAliases("https://alias-ok.example"); assert.equal(aliases.length, 1); assert.equal(aliases[0].id, "kcup"); } finally { present.restore(); } // The distinction that matters: the query holding this has staleTime // Infinity, so swallowing a blip would mean "this site has no aliases" for // the rest of the session. const real = globalThis.fetch; globalThis.fetch = (async () => { throw new TypeError("network down"); }) as typeof fetch; try { await assert.rejects(() => fetchAliases("https://alias-down.example"), /network down/); } finally { globalThis.fetch = real; resetReaders(); } });