import { test, expect } from "@playwright/test"; import { channelStage, generateReport, resetData, } from "./helpers"; // /channels counts come from each channel's last generated REPORT, not from a // live disk walk — that swap is what took the page from ~4.5s to ~0.1s. The // report is rewritten on the snapshot scheduler's debounce, so a count checked // immediately after a job finishes can legitimately still be the old one. // Reload until it lands rather than asserting once. (Same pattern the channel // page's post-mutation assertions use.) async function expectCountEventually( page: import("@playwright/test").Page, label: string, text: string, ): Promise { await expect .poll( async () => { await page.goto("/channels"); return page.getByLabel(label).textContent(); }, { timeout: 30_000, intervals: [500, 1000, 2000] }, ) .toBe(text); } test("shows zero/em-dash when no data exists", async ({ page }) => { await resetData("one-youtube-channel"); await page.goto("/channels"); await expect( page.getByLabel("playlist count for test-youtube"), ).toContainText("—"); await expect( page.getByLabel("transcripts count for test-youtube"), ).toHaveText("0"); await expect( page.getByLabel("downloads count for test-youtube"), ).toHaveText("0"); }); test("shows playlist length when playlist exists", async ({ page }) => { await resetData("channel-with-counts"); await page.goto("/channels"); await expect(page.getByLabel("playlist count for counted")).toHaveText("7"); // Fixture has playlist + archive but no data/ dirs, so neither transcripts // nor downloads have anything to count. await expect(page.getByLabel("transcripts count for counted")).toHaveText( "0", ); await expect(page.getByLabel("downloads count for counted")).toHaveText("0"); }); test("counts update after store-playlist and download", async ({ page }) => { test.setTimeout(120_000); await resetData("test-pipeline"); await page.goto("/channels"); await expect( page.getByLabel("playlist count for test-pipeline"), ).toContainText("—"); await expect( page.getByLabel("transcripts count for test-pipeline"), ).toHaveText("0"); await expect( page.getByLabel("downloads count for test-pipeline"), ).toHaveText("0"); await generateReport(page, "test-pipeline"); await page.goto(channelStage("test-pipeline", "playlist")); await page.getByRole("button", { name: "Store playlist" }).click(); await expect(page.getByLabel("Store playlist output")).toContainText( "Wrote 5 URLs", { timeout: 20_000 }, ); await expectCountEventually(page, "playlist count for test-pipeline", "5"); await expect( page.getByLabel("downloads count for test-pipeline"), ).toHaveText("0"); await generateReport(page, "test-pipeline"); await page.goto(channelStage("test-pipeline", "download")); await page.getByRole("button", { name: "Download from playlist" }).click(); await expect( page.getByLabel("Download from playlist output"), ).toContainText("Managed download complete", { timeout: 60_000 }); await expectCountEventually(page, "downloads count for test-pipeline", "5"); // YouTube channels: each downloaded video also counts as a transcript // because the .vtt is the destination file. await expect( page.getByLabel("transcripts count for test-pipeline"), ).toHaveText("5"); });