import fs from "node:fs"; import os from "node:os"; import path from "node:path"; import { expect, test } from "@playwright/test"; import { citedBuildProblem } from "yt-dlp-transcript-common/lib/builtExport"; import { CORPUS_ROOT_ENTRIES } from "./helpers"; import { REPORT_SITE_OUT, reportSiteAuditProblem } from "./stage"; // The cited out/ allowlist audit (common/lib/builtExport.ts), held to a REAL // `next build` of a cited site — the one this suite serves. The audit's list // was written from what compose puts in public/ and what Next was expected to // emit; this is where the two meet: if Next emits a file the list does not // name, the build fails here, and every deploy of it would be refused. const out = REPORT_SITE_OUT; const has = (rel: string) => fs.existsSync(path.join(out, ...rel.split("/"))); test("the built cited site passes the audit every deploy path asks", () => { expect(reportSiteAuditProblem()).toBeNull(); }); test("it holds the reports, the moments, the cited media and the contract", () => { for (const rel of [ "index.html", "reports/index.html", "reports/index.json", "reports/demo-factcheck/index.html", "reports/demo-factcheck/page.json", "reports/demo-factcheck/citations.json", "reports/demo-factcheck/citations.csv", "reports/demo-factcheck/report.html", "reports/demo-factcheck/report.pdf", "reports/demo-factcheck/report.md", "reports/demo-factcheck/slides.html", "reports/demo-factcheck/slides.pdf", "reports/demo-factcheck/evidence-pack.zip", "reports/demo-factcheck/stills/a01.png", "reports/demo-factcheck/history/index.html", "reports/demo-factcheck/history/history.json", "reports/demo-factcheck/history/repo/HEAD", "reports/demo-factcheck/history/repo/info/refs", "reports/demo-factcheck/history/repo/objects/info/packs", "reports/demo-factcheck/history/repo/refs/heads/main", "m/index.json", "m/demo-channel/abc123/3126.00-3151.00/index.html", "m/demo-channel/abc123/3126.00-3151.00/moment.json", "m/demo-podcast/ep-042/610.50-628.00/index.html", "m/demo-social/1234567890/index.html", "media/clips/demo-channel/abc123/3126.00-3151.00.mp4", "media/clips/demo-podcast/ep-042/610.50-628.00.m4a", "media/posts/demo-social/1234567890/shot.png", "site.json", "corpus.json", "llms.txt", "sitemap.xml", ]) { expect(has(rel), rel).toBe(true); } const corpus = JSON.parse(fs.readFileSync(path.join(out, "corpus.json"), "utf8")); expect(corpus.site).toMatchObject({ id: "reportsite", scope: "cited" }); expect(corpus.reports.count).toBe(1); const site = JSON.parse(fs.readFileSync(path.join(out, "site.json"), "utf8")); expect(site).toMatchObject({ siteId: "reportsite", channels: [], pwa: false }); }); test("it holds nothing of the corpus", () => { expect(CORPUS_ROOT_ENTRIES.filter(has)).toEqual([]); }); test("the audit refuses the same build with a corpus entry beside it", () => { const copy = fs.mkdtempSync(path.join(os.tmpdir(), "report-site-audit-")); try { fs.cpSync(out, copy, { recursive: true }); expect(citedBuildProblem(copy)).toBeNull(); fs.mkdirSync(path.join(copy, "summaries")); fs.writeFileSync(path.join(copy, "summaries", "manifest.json"), "{}"); expect(citedBuildProblem(copy)).toMatch(/summaries\//); } finally { fs.rmSync(copy, { recursive: true, force: true }); } });