#!/usr/bin/env python3 """Optional Chromium checks for Appearance controls and global corner geometry. Uses shipped CSS and the real Appearance list-rendering function with mocked preferences/translation state. Not a test of the authenticated Rust service. """ from pathlib import Path import json import shutil from playwright.sync_api import sync_playwright ROOT = Path(__file__).resolve().parents[2] WEB = ROOT / 'src/admin/web' css = (WEB / 'style.css').read_text() prefs = (WEB / 'app/preferences.js').read_text() widgets = json.loads((WEB / 'dashboard-widgets.json').read_text()) translations = json.loads((ROOT / 'langs/en_US.json').read_text())['translations'] functions = prefs[:prefs.index('function browserLanguage()')] + '\n' + prefs[prefs.index('function dashboardWidgetLabel'):prefs.index('function refreshChartStylePalette')] html = (f'' '
' '
' '
' '
Card
Stat
' '
' 'RustProxy
' '
Chart
') js = f'''const ADMIN_DASHBOARD_WIDGET_REGISTRY = Object.freeze({json.dumps(widgets)}); const translations = {json.dumps(translations)}; function t(key) {{ return translations[key] || key; }} function $(id) {{ return document.getElementById(id); }} function el(tag, text, klass) {{ const node = document.createElement(tag); if (text != null) node.textContent = text; if (klass) node.className = klass; return node; }} {functions} renderDashboardWidgetSettings();''' with sync_playwright() as playwright: binary = shutil.which('chromium') or shutil.which('chromium-browser') browser = playwright.chromium.launch(headless=True, executable_path=binary, args=['--no-sandbox']) page = browser.new_page(viewport={'width': 1320, 'height': 950}) page.set_content(html, wait_until='domcontentloaded') page.add_script_tag(content=js) assert page.locator('#dashboard-widget-list .dashboard-widget-setting').count() == 62 assert page.locator('#settings-page-appearance .overview-widget-type').count() == 0 assert page.locator('#editor-type-badge').is_visible() for width in (1320, 790, 450, 345): page.set_viewport_size({'width': width, 'height': 950}) results = page.locator('.dashboard-widget-setting').evaluate_all('''rows => rows.map(row => { const label = row.querySelector('.dashboard-widget-toggle').getBoundingClientRect(); const actions = row.querySelector('.dashboard-widget-setting-actions').getBoundingClientRect(); const box = row.getBoundingClientRect(); return { labelRight: label.right, actionsLeft: actions.left, actionsRight: actions.right, right: box.right }; })''') for i, result in enumerate(results): assert result['actionsLeft'] >= result['labelRight'] - 1, (width, i, result) assert result['actionsRight'] <= result['right'] + 1, (width, i, result) assert page.evaluate('document.documentElement.scrollWidth <= innerWidth + 2'), width for theme in ('dark', 'light', 'ultra_dark', 'cream'): page.evaluate('theme => { document.documentElement.dataset.theme = theme; document.documentElement.dataset.cornerStyle = "default"; }', theme) stat = page.locator('#test-stat').evaluate('(n) => getComputedStyle(n).borderTopLeftRadius') card = page.locator('#test-card').evaluate('(n) => getComputedStyle(n).borderTopLeftRadius') assert stat == card == '0px', (theme, stat, card) for style, expected_surface, expected_control in (('square', '0px', '0px'), ('subtle','5px','4px'), ('rounded','12px','8px'),('extra','18px','12px')): page.evaluate('style => document.documentElement.dataset.cornerStyle = style', style) assert page.locator('#test-stat').evaluate('(n) => getComputedStyle(n).borderTopLeftRadius') == expected_surface, (theme, style, 'stat') assert page.locator('#test-card').evaluate('(n) => getComputedStyle(n).borderTopLeftRadius') == expected_surface, (theme, style, 'card') assert page.locator('#test-action').evaluate('(n) => getComputedStyle(n).borderTopLeftRadius') == expected_control, (theme, style, 'button') assert page.locator('#test-input').evaluate('(n) => getComputedStyle(n).borderTopLeftRadius') == expected_control, (theme, style, 'input') page.evaluate('document.documentElement.dataset.theme = "dark"; document.documentElement.dataset.cornerStyle = "default"') original_logo = page.locator('#test-logo').evaluate('(n) => getComputedStyle(n).borderTopColor') page.evaluate('document.documentElement.dataset.theme = "ultra_dark"') black_logo = page.locator('#test-logo').evaluate('(n) => getComputedStyle(n).borderTopColor') assert black_logo == original_logo == 'rgb(246, 155, 116)', (black_logo, original_logo) out = ROOT.parent / 'appearance_ux_0323_preview.png' page.screenshot(path=str(out)) browser.close() print('PASS: 62 badge-free Appearance rows, right-pinned buttons at 4 widths, theme-independent corner geometry, original black-theme logo accent')