// @ts-check // LibriVox / Wikimedia search + import in "Get Voices Online" (mocked routes only). const { test, expect } = require('@playwright/test'); const ITEMS = [{ source: 'librivox', title: 'Pride - Ch 1', reader: 'Ann', author: 'Jane Austen', language: 'English', duration: 600, licence: 'Public domain (LibriVox, USA)', licence_url: 'https://librivox.org/pages/public-domain/', source_url: 'https://librivox.org/b/', audio_url: 'https://www.archive.org/download/x/a.mp3', attribution: '' }]; test('search shows licence, import sends provenance fields', async ({ page }) => { let imported = null, searched = ''; await page.route('**/api/voice-sources/librivox*', r => { searched = r.request().url(); return r.fulfill({ json: { source: 'librivox', items: ITEMS } }); }); await page.route('**/api/proxy-audio*', r => r.fulfill({ body: '', contentType: 'audio/mpeg' })); await page.route('**/api/quick-import-voice', r => { imported = r.request().postDataJSON(); return r.fulfill({ json: { voice_id: 'EN_N_Pride' } }); }); await page.route('**/api/voices*', r => r.fulfill({ json: [] })); await page.route('**/api/settings*', r => r.fulfill({ json: {} })); await page.goto('/', { waitUntil: 'domcontentloaded' }); await page.waitForFunction(() => typeof window.navTo === 'function' && !!document.getElementById('os-form'), null, { timeout: 15_000 }); await page.evaluate(() => window.navTo('s-studio')); await page.locator('.gvo-tab[data-src="open"]').click(); await page.fill('#os-q', 'pride'); await page.press('#os-q', 'Enter'); await expect(page.locator('#os-list')).toContainText('Public domain (LibriVox, USA)'); expect(searched).toContain('q=pride'); const b = page.locator('.os-import'); const h = await b.evaluate(el => el.getBoundingClientRect().height); expect(h).toBeGreaterThanOrEqual(44); await b.click(); await expect(page.locator('#os-status')).toContainText('Saved as EN_N_Pride'); expect(imported).toMatchObject({ source_kind: 'librivox', page_url: 'https://librivox.org/b/', start: 0, length: 30 }); }); test('search error is shown in the status region', async ({ page }) => { await page.route('**/api/voice-sources/wikimedia*', r => r.fulfill({ status: 502, json: { detail: 'wikimedia is unavailable right now' } })); await page.route('**/api/voices*', r => r.fulfill({ json: [] })); await page.goto('/', { waitUntil: 'domcontentloaded' }); await page.waitForFunction(() => typeof window.navTo === 'function' && !!document.getElementById('os-form'), null, { timeout: 15_000 }); await page.evaluate(() => window.navTo('s-studio')); await page.locator('.gvo-tab[data-src="open"]').click(); await page.selectOption('#os-source', 'wikimedia'); await page.fill('#os-q', 'speech'); await page.evaluate(() => document.getElementById('os-form').requestSubmit()); await expect(page.locator('#os-status')).toContainText('unavailable'); }); test('librivox list without audio: preview and import resolve the chapter on demand', async ({ page }) => { let imported = null, resolved = 0; const light = [{ ...ITEMS[0], book_id: '855', audio_url: '', reader: '' }]; await page.route('**/api/voice-sources/librivox/book/855', r => { resolved++; return r.fulfill({ json: { audio_url: 'https://www.archive.org/download/x/a.mp3', section: 'Ch 1', reader: 'Ann', duration: 600 } }); }); await page.route('**/api/voice-sources/librivox?*', r => r.fulfill({ json: { source: 'librivox', items: light } })); await page.route('**/api/proxy-audio*', r => r.fulfill({ body: '', contentType: 'audio/mpeg' })); await page.route('**/api/quick-import-voice', r => { imported = r.request().postDataJSON(); return r.fulfill({ json: { voice_id: 'EN_N_Pride' } }); }); await page.route('**/api/voices*', r => r.fulfill({ json: [] })); await page.route('**/api/settings*', r => r.fulfill({ json: {} })); await page.goto('/', { waitUntil: 'domcontentloaded' }); await page.waitForFunction(() => typeof window.navTo === 'function' && !!document.getElementById('os-form'), null, { timeout: 15_000 }); await page.evaluate(() => window.navTo('s-studio')); await page.locator('.gvo-tab[data-src="open"]').click(); await page.fill('#os-q', 'pride'); await page.press('#os-q', 'Enter'); await page.locator('.os-load').click(); await expect(page.locator('#os-list audio')).toHaveCount(1); await page.locator('.os-import').click(); await expect(page.locator('#os-status')).toContainText('Saved as EN_N_Pride'); expect(resolved).toBe(1); expect(imported.audio_url).toContain('archive.org'); });