import { mkdir, writeFile } from "node:fs/promises"; import { dirname } from "node:path"; import { test, expect } from "@playwright/test"; import { channelStage, generateReport, resetData, resolvePath, } from "./helpers"; const CHANNEL = "test-transcribe"; const FIXTURE = "one-transcribe-channel-with-audio"; type AvailabilityStatus = | "public" | "unlisted" | "private" | "members_only" | "needs_auth" | "deleted" | "error"; async function writeAvailability(id: string, status: AvailabilityStatus) { const path = resolvePath( `test-transcripts/channels/${CHANNEL}/data/${id}/availability.json`, ); await mkdir(dirname(path), { recursive: true }); await writeFile( path, JSON.stringify({ checkedAt: new Date().toISOString(), availability: status, webpageUrl: `https://www.youtube.com/watch?v=${id}`, }), ); } test("members-only video is hidden from the Missing metadata bucket", async ({ page, }) => { // Fixture has vidA, vidB, vidC — each with audio.m4a but no metadata.info.json. // Without filtering, all three would show as "Missing metadata.info.json (3)". await resetData(FIXTURE); await writeAvailability("vidA", "members_only"); await generateReport(page, CHANNEL); await page.goto(channelStage(CHANNEL, "diagnostics")); await expect( page.getByRole("heading", { name: /Missing metadata\.info\.json \(2\)/ }), ).toBeVisible(); const list = page.getByLabel("missing metadata list"); await expect(list.getByLabel("missing metadata vidA")).toHaveCount(0); await expect(list.getByLabel("missing metadata vidB")).toBeVisible(); await expect(list.getByLabel("missing metadata vidC")).toBeVisible(); }); test("members-only video is hidden from the Failed transcriptions list", async ({ page, }) => { await resetData(FIXTURE); await writeAvailability("vidA", "members_only"); await writeFile( resolvePath(`test-transcripts/channels/${CHANNEL}/failed-transcriptions`), "vidA\nvidB\n", ); await generateReport(page, CHANNEL); await page.goto(channelStage(CHANNEL, "transcribe")); await expect( page.getByRole("heading", { name: /Failed transcriptions \(1\)/ }), ).toBeVisible(); const list = page.getByLabel("failed transcriptions list"); await expect(list.getByLabel("failed transcription vidA")).toHaveCount(0); await expect(list.getByLabel("failed transcription vidB")).toBeVisible(); }); test("stage badge counts exclude members-only videos", async ({ page }) => { await resetData(FIXTURE); // vidA: members_only — should drop out of both buckets. // vidB: stays in both buckets (no availability sidecar). await writeAvailability("vidA", "members_only"); await writeFile( resolvePath(`test-transcripts/channels/${CHANNEL}/failed-transcriptions`), "vidA\nvidB\n", ); await generateReport(page, CHANNEL); await page.goto(`/channels/${CHANNEL}`); // Diagnostics pending = noMetadata (2: vidB, vidC) + missingFromArchive + duplicateDirs. // The fixture has no archive or duplicates, so the count is just the // filtered noMetadata count. Both the side-rail and the stage card surface // this label; assert every instance reads "2". const diagPending = page.getByLabel("Diagnostics pending count"); await expect(diagPending).not.toHaveCount(0); for (const el of await diagPending.all()) { await expect(el).toHaveText("2"); } // Transcribe failed = filtered failedVideoIds count (1: vidB). const transcribeFailed = page.getByLabel("Transcribe failed count"); await expect(transcribeFailed).not.toHaveCount(0); for (const el of await transcribeFailed.all()) { await expect(el).toHaveText(/^1( failed)?$/); } });