Files
hope-voice-api/tests/unit/test_voice_settings_ui.py
T
2026-10-02 16:07:24 -04:00

64 lines
3.5 KiB
Python

"""Offline browser coverage of the English voice picker using local assets."""
from pathlib import Path
from playwright.sync_api import sync_playwright, expect
ROOT = Path(__file__).resolve().parents[2]
def test_english_voice_search_selection_and_retry():
available = True
account = {'id': 'alice', 'username': 'alice', 'display_name': 'Alice', 'role': 'user', 'status': 'ready'}
voices = [
{'id': 'en-US-Ava:DragonHDOmniLatestNeural', 'name': 'Ava', 'locale': 'en-US', 'gender': 'Female', 'tag': 'Omni'},
{'id': 'en-GB-Sonia:DragonHDOmniLatestNeural', 'name': 'Sonia', 'locale': 'en-GB', 'gender': 'Female', 'tag': 'Omni'},
{'id': 'en-AU-WilliamNeural', 'name': 'William', 'locale': 'en-AU', 'gender': 'Male', 'tag': 'Neural'},
]
with sync_playwright() as p:
browser = p.chromium.launch(headless=True)
page = browser.new_page(viewport={'width': 390, 'height': 844})
errors = []
page.on('pageerror', lambda e: errors.append(str(e)))
def route(req):
url = req.request.url
if '/api/auth/me' in url:
req.fulfill(json={'user': account})
elif url.endswith('/voices'):
if available:
req.fulfill(json={'voices': voices, 'default_voice': voices[0]['id'], 'catalog_available': True})
else:
req.fulfill(status=503, json={'error': 'Unavailable'})
elif '/api/settings/model' in url:
req.fulfill(json={'settings': {'model': 'auto', 'thinking_level': 'none'}, 'models': [], 'catalog_available': False})
else:
asset = ROOT / 'web' / (url.split('/', 3)[-1].split('?')[0] or 'index.html')
types = {'.html': 'text/html', '.js': 'application/javascript', '.css': 'text/css', '.svg': 'image/svg+xml'}
if asset.is_file():
req.fulfill(body=asset.read_bytes(), content_type=types.get(asset.suffix, 'application/octet-stream'))
else:
req.fulfill(status=404, body='')
page.route('https://hope.test/**', route)
page.add_init_script("localStorage.setItem('preferred_voice', 'en-US-Ava:DragonHDLatestNeural')")
page.goto('https://hope.test/'); page.wait_for_load_state('networkidle')
page.locator('#settingsBtn').click()
expect(page.locator('#voiceList [aria-checked=true]')).to_contain_text('Ava')
expect(page.locator('#voiceCatalogStatus')).to_contain_text('3 English voices')
page.locator('#voiceSearch').fill('en-GB')
expect(page.locator('#voiceList [role=radio]')).to_have_count(1)
page.locator('#voiceList [role=radio]').press('Enter')
assert page.evaluate("localStorage.getItem('preferred_voice')") == voices[1]['id']
page.locator('#voiceSearch').fill('no-matching-voice')
expect(page.locator('#voiceList')).to_contain_text('No matching voices')
page.locator('#voiceSearch').fill('')
assert page.evaluate('document.documentElement.scrollWidth <= innerWidth')
page.screenshot(path='/tmp/hope-english-voices-mobile.png', full_page=True)
page.locator('#closeSheetBtn').click()
available = False
page.locator('#settingsBtn').click()
expect(page.locator('#retryVoices')).to_be_visible()
expect(page.locator('#voiceList [role=radio]')).to_have_count(3)
available = True
page.locator('#retryVoices').click()
expect(page.locator('#retryVoices')).to_be_hidden()
assert errors == []
browser.close()