import { test, expect } from "@playwright/test"; import { buildIndex, pathExists, readJson, resetData, writeSite, } from "./helpers"; test("build index against an empty site writes a 0-transcript manifest", async ({ page, }) => { await resetData("empty"); await writeSite("testsite", { channels: [] }); await buildIndex(page); const manifest = await readJson<{ totalCount: number; siteId: string }>( "test-transcripts/.export-index/sites/testsite/summaries/manifest.json", ); expect(manifest.totalCount).toBe(0); expect(manifest.siteId).toBe("testsite"); }); test("build index ingests synthetic video data into shared + per-site output", async ({ page, }) => { await resetData("one-youtube-channel-with-data"); await writeSite("testsite", { channels: [{ slug: "test-youtube", groupId: "default" }], }); await buildIndex(page); const manifest = await readJson<{ totalCount: number; channels: { name: string }[]; }>("test-transcripts/.export-index/sites/testsite/summaries/manifest.json"); expect(manifest.totalCount).toBe(1); expect(manifest.channels.map((c) => c.name)).toContain("Test YouTube Channel"); // Per-channel transcript pages are written ONCE to the shared tree. expect( await pathExists( "test-transcripts/.export-index/shared/transcripts/test-youtube/page-0000.json", ), ).toBe(true); }); test("two sites over a shared pool get isolated, differently-filtered summaries", async ({ page, }) => { await resetData("one-youtube-channel-with-data"); await writeSite("with-channel", { channels: [{ slug: "test-youtube", groupId: "default" }], }); await writeSite("without-channel", { channels: [] }); await buildIndex(page); const withChannel = await readJson<{ totalCount: number }>( "test-transcripts/.export-index/sites/with-channel/summaries/manifest.json", ); const without = await readJson<{ totalCount: number }>( "test-transcripts/.export-index/sites/without-channel/summaries/manifest.json", ); expect(withChannel.totalCount).toBe(1); expect(without.totalCount).toBe(0); }); test("build static export lives on the site's Publish tab, not the family page", async ({ page, }) => { await resetData("empty"); // A configured site is the build target; the Publish tab needs one to exist // at all, and the enabled check below is about that site. await writeSite("testsite", {}); // Not in the family page's Pool. await page.goto("/sites"); await page.getByText("Pool jobs", { exact: true }).click(); await expect( page.getByRole("heading", { name: "Build static export" }), ).toHaveCount(0); await expect(page.getByRole("heading", { name: "Build index" })).toBeVisible(); // On the site's Publish tab, under the "Individual steps" disclosure. await page.goto("/sites/testsite/publish"); await page.getByText("Individual steps").click(); const exportHeading = page.getByRole("heading", { name: "Build static export", }); await expect(exportHeading).toBeVisible(); const exportButton = page.getByRole("button", { name: "Build static export", }); await expect(exportButton).toBeEnabled(); // No "skip data rebuild" any more (release 18): the data is the index // stage, shared by every site, and a build updates it first when it is // stale. The archive opt-out stays, default off. await expect(page.getByLabel("Skip data rebuild (index, stats, charts)")).toHaveCount(0); const skipArchives = page.getByLabel("Skip archive zips (transcript & live-chat downloads)"); await expect(skipArchives).toBeVisible(); await expect(skipArchives).not.toBeChecked(); });