"""Offline Chromium checks of actual Hope assets with mocked account APIs.""" import json from pathlib import Path from playwright.sync_api import sync_playwright, expect ROOT = Path(__file__).resolve().parents[2] def test_model_settings_load_save_reload_and_failure(): saved = {'model': 'auto', 'thinking_level': 'none'} account = {'id':'alice','username':'alice','display_name':'Alice','role':'user','status':'ready','error':None} calls = [] available = True models = [{'id':m,'name':m,'thinking_levels':['none','low','high']} for m in ['auto','openai/gpt-6.1-sol-subscription']] 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): nonlocal saved url = req.request.url if '/api/auth/me' in url: req.fulfill(json={'user':account}) elif '/api/capabilities' in url: req.fulfill(json={'version': 1, 'features': {}}) elif '/api/settings/model' in url: calls.append(req.request.method) if req.request.method == 'PUT': saved = req.request.post_data_json req.fulfill(json={'settings':saved,'message':'Saved for your account. Applies to your next request.'}) else: req.fulfill(json={'settings':saved,'models':models if available else [],'catalog_available':available,'message':''}) else: name = url.split('/',3)[-1].split('?')[0] or 'index.html' asset = ROOT/'web'/name if asset.is_file(): types = {'.html':'text/html','.js':'application/javascript','.css':'text/css','.svg':'image/svg+xml'} 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.goto('https://hope.test/') page.wait_for_load_state('networkidle') assert calls == [] page.locator('#drawerOpen').click() page.locator('#accountMenuBtn').click() page.locator('[data-settings-target="preferences"]').click() expect(page.locator('#modelSelect')).to_be_enabled() expect(page.locator('#saveModelSettings')).to_be_disabled() page.locator('#modelSelect').select_option('openai/gpt-6.1-sol-subscription') page.locator('#thinkingLevelSelect').select_option('high') page.locator('#saveModelSettings').click() expect(page.locator('#modelSettingsStatus')).to_contain_text('Saved') assert saved == {'model':'openai/gpt-6.1-sol-subscription','thinking_level':'high'} assert page.evaluate('document.documentElement.scrollWidth <= innerWidth') page.locator('#settingsClose').click() page.reload(); page.wait_for_load_state('networkidle') page.locator('#drawerOpen').click() page.locator('#accountMenuBtn').click() page.locator('[data-settings-target="preferences"]').click() expect(page.locator('#modelSelect')).to_have_value(saved['model']) expect(page.locator('#thinkingLevelSelect')).to_have_value('high') page.screenshot(path='/tmp/hope-model-settings-mobile.png',full_page=True) page.locator('#settingsClose').click() available = False page.locator('#drawerOpen').click() page.locator('#accountMenuBtn').click() page.locator('[data-settings-target="preferences"]').click() expect(page.locator('#modelSelect')).to_be_disabled() expect(page.locator('#saveModelSettings')).to_be_disabled() expect(page.locator('#retryModelSettings')).to_be_visible() available = True page.locator('#retryModelSettings').click() expect(page.locator('#modelSelect')).to_be_enabled() assert errors == [] browser.close()