// @ts-check // Browser-level checks for span-mode casting: the modules load with the audiobook // section, the pure segmenter works in the real page, and the engine switch honours // localStorage. The LLM-driven flow itself is covered by the unit tests and the // scored regression runs (architecture/audiobook-attribution.md). const { test, expect } = require('@playwright/test'); async function openReader(page) { await page.goto('/', { waitUntil: 'domcontentloaded' }); await page.waitForSelector('#app-skeleton', { state: 'detached', timeout: 15_000 }); await page.waitForFunction(() => typeof window.navTo === 'function', null, { timeout: 15_000 }); await page.evaluate(() => window.navTo('s-reader')); await page.waitForFunction(() => typeof window.audiobookCastSpans === 'function', null, { timeout: 15_000 }); } test('span-mode modules load and segment quoted speech in the page', async ({ page }) => { await openReader(page); const out = await page.evaluate(() => { const filler = Array.from({ length: 6 }, (_, i) => `»Zeile ${i} ist ein Satz.« sagte er.`).join(' '); const spans = window.TTVC.audiobook.spans.segmentByQuotes(`${filler} Der Zwerg schneuzte sich. »Na los!« Er ging.`); return spans.slice(-3).map((s) => `${s.kind}:${s.text}`); }); expect(out.some((s) => s === 'dialogue:Na los!')).toBe(true); expect(out[out.length - 1].startsWith('narration:')).toBe(true); }); test('span mode is on by default and can be switched off per browser', async ({ page }) => { await openReader(page); expect(await page.evaluate(() => window.audiobookSpanModeEnabled())).toBe(true); await page.evaluate(() => localStorage.setItem('ab-span-mode', '0')); expect(await page.evaluate(() => window.audiobookSpanModeEnabled())).toBe(false); await page.evaluate(() => localStorage.removeItem('ab-span-mode')); });