// The per-channel video list shows what each video is CALLED, and searches by // it; an undownloaded video's own page is not a bare id. // // Three rows, one per title source that can reach a fixture (the transcript // index is exercised by common/controller/videoTitles.test.ts): // - fake00000001 — downloaded; its title is in data//metadata.info.json. // - fake00000002 — listed, never downloaded; titled by the channel's // metadata-scan.json (the listing scan's store). // - fake00000003 — listed, never downloaded, never scanned: the bare id. import { writeFile } from "node:fs/promises"; import { test, expect } from "@playwright/test"; import { channelVideos, generateReport, resetData, resolvePath, } from "./helpers"; const CHANNEL = "test-youtube"; const ROOT = `test-transcripts/channels/${CHANNEL}`; const DOWNLOADED = "fake00000001"; const SCANNED = "fake00000002"; const BARE = "fake00000003"; const SCANNED_TITLE = "Moonlit Harbor Interview"; const SCANNED_DESCRIPTION = "A long talk on the pier.\nSecond line of notes."; async function seed() { await resetData("youtube-with-playlist"); // The store's on-disk shape (common/controller/metadataScanStore.ts, // METADATA_SCAN_FILENAME) — the scan writes exactly this, and never a // data// directory. await writeFile( resolvePath(`${ROOT}/metadata-scan.json`), JSON.stringify( { version: 1, updatedAt: "2026-09-25T00:00:00.000Z", lastRun: null, entries: { [SCANNED]: { title: SCANNED_TITLE, description: SCANNED_DESCRIPTION, uploadDate: "20240315", duration: 754, scannedAt: "2026-09-25T00:00:00.000Z", }, }, errors: {}, }, null, 2, ), ); } test("the video list shows titles and searches them", async ({ page }) => { await seed(); await generateReport(page, CHANNEL); await page.goto(channelVideos(CHANNEL)); const list = page.getByLabel("videos", { exact: true }); const downloaded = list.getByLabel(`open ${DOWNLOADED}`); const scanned = list.getByLabel(`open ${SCANNED}`); const bare = list.getByLabel(`open ${BARE}`); // Titles where known, the id beneath them; the bare id alone otherwise. await expect(downloaded).toContainText("Synthetic Test Video 1"); await expect(downloaded).toContainText(DOWNLOADED); await expect(scanned).toContainText(SCANNED_TITLE); await expect(scanned).toContainText(SCANNED); await expect(bare).toHaveText(BARE); // A word from the scan-store title, in the wrong case, leaves that one row. const search = page.getByLabel("search videos"); await search.fill("harbor"); await expect(scanned).toBeVisible(); await expect(list.getByLabel(/^open fake/)).toHaveCount(1); // The id still matches, as it always has. await search.fill(BARE); await expect(bare).toBeVisible(); await expect(list.getByLabel(/^open fake/)).toHaveCount(1); }); test("an undownloaded video's page shows the listing scan's metadata", async ({ page, }) => { await seed(); await page.goto(`/channels/${CHANNEL}/videos/${SCANNED}`); await expect( page.getByRole("heading", { name: SCANNED_TITLE }), ).toBeVisible(); await expect(page.getByLabel("metadata source")).toHaveText( "from the listing scan — not downloaded", ); // Date and duration come from the scan entry too. await expect(page.getByText("2024-03-15")).toBeVisible(); await expect(page.getByText("12:34")).toBeVisible(); // Collapsed by default; opening it shows the description. const summary = page.getByText("Description", { exact: true }); await expect(summary).toBeVisible(); const body = page.getByText("A long talk on the pier."); await expect(body).toBeHidden(); await summary.click(); await expect(body).toBeVisible(); // A downloaded video's page has no scan note. await page.goto(`/channels/${CHANNEL}/videos/${DOWNLOADED}`); await expect( page.getByRole("heading", { name: "Synthetic Test Video 1" }), ).toBeVisible(); await expect(page.getByLabel("metadata source")).toHaveCount(0); });