#!/usr/bin/env python3 """Optional Chromium regression: shared button sizing and Dashboard density. Uses the production HTML button markup and stylesheet without a running API. Run: python3 tools/checks/appearance_density_buttons_0327_browser.py """ from pathlib import Path import re import shutil from playwright.sync_api import sync_playwright ROOT = Path(__file__).resolve().parents[2] index = (ROOT / 'src/admin/web/index.html').read_text() css = (ROOT / 'src/admin/web/style.css').read_text() def button(button_id): match = re.search(r']*\bid="' + re.escape(button_id) + r'")[\s\S]*?', index) assert match, button_id return match.group(0).replace(' hidden', '') html = f'''

Overview

{button('overview-refresh')}{button('overview-layout-open')}{button('overview-layout-unlock')}
{button('overview-layout-open-settings')}{button('dashboard-widget-expand')}
{''}
Requests100Rate

Diagnostics

Metrics

''' with sync_playwright() as p: browser = p.chromium.launch(executable_path=shutil.which('chromium') or shutil.which('chromium-browser'), args=['--no-sandbox']) for width in [320, 393, 1280]: page = browser.new_page(viewport={'width': width, 'height': 900}) page.set_content(html) for style in ['normal', 'compact']: page.evaluate('(value) => document.documentElement.dataset.buttonStyle = value', style) computed = page.evaluate('''() => { const values = id => { const s = getComputedStyle(document.getElementById(id)); return [s.fontSize, s.minHeight, s.paddingTop, s.paddingRight, s.paddingBottom, s.paddingLeft]; }; return Object.fromEntries(['overview-refresh', 'overview-layout-open', 'overview-layout-unlock', 'overview-layout-open-settings', 'dashboard-widget-expand', 'reference-quiet', 'reference-outline'] .map(id => [id, values(id)])); }''') for target, reference in [ ('overview-refresh', 'reference-quiet'), ('overview-layout-open', 'reference-quiet'), ('overview-layout-unlock', 'reference-outline'), ('overview-layout-open-settings', 'reference-outline'), ('dashboard-widget-expand', 'reference-quiet'), ]: assert computed[target] == computed[reference], (width, style, target, computed[target], computed[reference]) print('PASS buttons', width, style, computed['overview-refresh']) measures = {} for density in ['normal', 'compact', 'ultra']: page.evaluate('(value) => document.documentElement.dataset.dashboardDensity = value', density) measures[density] = page.evaluate('''() => { const stat = document.querySelector('#panel-overview .stat'); const value = stat.querySelector('strong'); const svg = stat.querySelector('svg'); const card = document.querySelector('#panel-overview .card'); const title = card.querySelector('h2'); return {statPadding: parseFloat(getComputedStyle(stat).paddingTop), valueSize: parseFloat(getComputedStyle(value).fontSize), chartHeight: parseFloat(getComputedStyle(svg).height), cardPadding: parseFloat(getComputedStyle(card).paddingTop), titleSize: parseFloat(getComputedStyle(title).fontSize), overflow: document.documentElement.scrollWidth > window.innerWidth}; }''') assert not measures[density]['overflow'], (width, density) for key in ['statPadding', 'valueSize', 'chartHeight', 'cardPadding', 'titleSize']: values = [measures[d][key] for d in ['normal', 'compact', 'ultra']] assert values[0] > values[1] > values[2], (width, key, values) print('PASS densities', width, measures) page.close() browser.close()