v0.32.2
This commit is contained in:
1 parent
bb025dcf44
commit
b0f211555a
74 files changed
+6089
-556
No files matched your search
Executable
+75
@@ -0,0 +1,75 @@
|
||||
#!/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'<!doctype html><html data-theme="ultra_dark" data-corner-style="default"><head><style>{css}</style></head><body>'
|
||||
'<div id="settings-page-appearance" class="settings-page" style="max-width:100%;padding:12px">'
|
||||
'<div class="appearance-section"><div class="dashboard-widget-list" id="dashboard-widget-list"></div></div>'
|
||||
'<div style="display:flex;gap:10px;margin-top:12px">'
|
||||
'<div class="card" id="test-card">Card</div><div class="stat" id="test-stat">Stat</div>'
|
||||
'<button class="outline" id="test-action">Action</button><input id="test-input" value="value"></div>'
|
||||
'<a class="brand" href="#"><span class="brand-mark" id="test-logo">r<span>/</span>p</span>RustProxy</a></div>'
|
||||
'<div class="overview-widget-type" id="editor-type-badge">Chart</div></body></html>')
|
||||
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')
|
||||
Reference in new issue
Block a user