import { test } from "node:test"; import assert from "node:assert/strict"; import { ArchiveHttpError, RemoteSource } from "./reader"; import { channelRef, readerFor, resetReaders } from "./readers"; // The same in-memory-archive trick as reader.test.ts: a Map from URL to JSON // body installed as `fetch`, so every assertion below is about the URLs the // reader actually asks for. The viewer's caches are thin wrappers over these // reads, so pinning the reads pins the wire. 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(); }, }; } test("readerFor: one reader per origin, kept for the life of the page", () => { resetReaders(); const same = readerFor(""); assert.equal(readerFor(""), same); assert.equal(readerFor(), same, "the default argument is the same-origin key"); const other = readerFor("https://b.example"); assert.notEqual(other, same); assert.equal(readerFor("https://b.example"), other); assert.ok(same instanceof RemoteSource); resetReaders(); assert.notEqual(readerFor(""), same, "resetReaders drops the caches with it"); }); test("the same-origin reader emits ROOT-RELATIVE urls, byte-identical to the old walk", async () => { const { archive, restore } = installFetch({ "/summaries/manifest.json": { version: 3, pageCount: 2, channels: [] }, "/summaries/page-0001.json": [], "/stats/manifest.json": { version: 1, pageCount: 1, channels: [] }, "/stats/page-0000.json": [], "/subs/manifest.json": { version: 4, channels: [] }, "/posts/manifest.json": { version: 1, channels: [] }, "/search-aliases.json": { aliases: [] }, "/duplicates.json": { clusters: [] }, "/transcripts/alpha/manifest.json": { slugToPage: {}, pageCount: 1 }, "/subs/alpha/manifest.json": { slugToPage: {}, pageCount: 1 }, "/posts/alpha/manifest.json": { slugToPage: {}, pageCount: 1 }, }); try { const r = readerFor(""); await r.readSummariesManifest(); await r.readSummariesPage(1); await r.readStatsManifest(); await r.readStatsPage(0); await r.readSubsSiteManifest(); await r.readPostsSiteManifest(); await r.readAliasConfig(); await r.readDuplicates(); await r.readChannelSubsManifest("alpha"); await r.readChannelPostsManifest("alpha"); assert.deepEqual(archive.fetches, [ "/summaries/manifest.json", "/summaries/page-0001.json", "/stats/manifest.json", "/stats/page-0000.json", "/subs/manifest.json", "/posts/manifest.json", "/search-aliases.json", "/duplicates.json", "/subs/alpha/manifest.json", "/posts/alpha/manifest.json", ]); } finally { restore(); } }); test("a federated origin prefixes every one of those, and nothing else changes", async () => { const O = "https://member.example"; const { archive, restore } = installFetch({ [`${O}/summaries/manifest.json`]: { version: 3, pageCount: 0, channels: [] }, [`${O}/duplicates.json`]: { clusters: [] }, }); try { const r = readerFor(O); await r.readSummariesManifest(); await r.readDuplicates(); assert.deepEqual(archive.fetches, [ `${O}/summaries/manifest.json`, `${O}/duplicates.json`, ]); } finally { restore(); } }); test("a raw read rejects with the status; the tolerant fold over it resolves empty", async () => { const { restore } = installFetch({}); try { const r = readerFor(""); await assert.rejects( () => r.readDuplicates(), (err: unknown) => err instanceof ArchiveHttpError && err.status === 404 && /GET \/duplicates\.json -> 404/.test((err as Error).message), ); // Same document, same 404, through the fold the MCP uses. assert.equal((await r.duplicateIndex()).size, 0); // And through the summaries fold, which a partial/absent index must not // turn into an error — the page planner reads empty as "scan anyway". assert.equal((await r.videoIndex()).size, 0); assert.deepEqual(await r.loadAliases(), []); } finally { restore(); } }); test("a digests manifest 404 is the layer's own answer; any other status is not", async () => { const { archive, restore } = installFetch({ "/digests/beta/manifest.json": { slugToPage: { v1: 0 }, pageCount: 1 }, }); try { const r = readerFor(""); assert.equal(await r.readChannelDigestsManifest("alpha"), null); assert.ok(await r.readChannelDigestsManifest("beta")); assert.deepEqual(archive.fetches, [ "/digests/alpha/manifest.json", "/digests/beta/manifest.json", ]); } finally { restore(); } const bad = installFetch({}); const realFetch = globalThis.fetch; globalThis.fetch = (async (input: RequestInfo | URL) => { void input; return new Response("boom", { status: 500, statusText: "Server Error" }); }) as typeof fetch; try { await assert.rejects( () => readerFor("").readChannelDigestsManifest("alpha"), /-> 500/, ); } finally { globalThis.fetch = realFetch; bad.restore(); } }); test("channelRef: slug-addressed, and carries the origin only when there is one", () => { assert.deepEqual(channelRef("alpha"), { key: "alpha", slug: "alpha", name: "alpha", }); assert.deepEqual(channelRef("alpha", "https://b.example"), { key: "alpha", slug: "alpha", name: "alpha", siteUrl: "https://b.example", }); });