import { test, expect } from "@playwright/test"; // Exercises the FlexSearch web worker end to end: /offline builds a channel's // index off the main thread from the transcript shards, then searches it. The // SW is disabled in dev (production-only), so the worker's shard fetches hit the // network and are mocked here via context.route (which reaches worker requests). const SLUG = "test-youtube"; // testsite's channel (see e2e/fixtures/sites) test("builds a channel index in the worker and searches it offline", async ({ page, }) => { await page.context().route( `**/transcripts/${SLUG}/manifest.json`, async (route) => { await route.fulfill({ contentType: "application/json", body: JSON.stringify({ version: 2, channelSlug: SLUG, pageCount: 1, maxPageBytes: 1000, generatedAt: "2026-06-30T00:00:00.000Z", slugToPage: {}, }), }); }, ); await page.context().route( `**/transcripts/${SLUG}/page-0000.json`, async (route) => { await route.fulfill({ contentType: "application/json", body: JSON.stringify([ { slug: "vidA", cues: [ { start: 0, text: "a constitutional hearing began today" }, { start: 12, text: "the witness testified under oath" }, ], }, { slug: "vidB", cues: [{ start: 3, text: "an unrelated cooking segment" }], }, ]), }); }, ); await page.goto("/offline/"); const build = page.getByRole("button", { name: `build search index for ${SLUG}`, }); await expect(build).toBeVisible(); await build.click(); // The worker finishes → an "Indexed · N" badge appears. await expect(page.getByLabel(`${SLUG} indexed`)).toBeVisible({ timeout: 20_000, }); // The offline search box is now available; a word query returns the matching // cue via the worker's FlexSearch index. const box = page.getByLabel("offline search", { exact: true }); await expect(box).toBeVisible(); await box.fill("constitutional"); const results = page.getByLabel("offline search results"); await expect(results).toContainText("constitutional hearing", { timeout: 10_000, }); // A non-matching term yields no hit for that cue. await box.fill("cooking"); await expect(results).toContainText("cooking segment", { timeout: 10_000 }); });