#!/usr/bin/env python3 """Progressbar Appearance regression using the production CSS in Chromium. Browser-only visual/CSS verification. Does not execute RustProxy or authenticate. """ from __future__ import annotations from io import BytesIO from pathlib import Path import re from PIL import Image from playwright.sync_api import sync_playwright ROOT = Path(__file__).resolve().parents[2] CSS = (ROOT / 'src/admin/web/style.css').read_text(encoding='utf-8') APP_HTML = (ROOT / 'src/admin/web/index.html').read_text(encoding='utf-8') assert re.search(r'
''' def color_at_progress(page, progress_id: str) -> tuple[int, int, int]: rect = page.locator(f'#{progress_id}').bounding_box() assert rect and rect['width'] > 100 screenshot = Image.open(BytesIO(page.screenshot())).convert('RGB') x = round(rect['x'] + rect['width'] * .22) y = round(rect['y'] + rect['height'] / 2) return screenshot.getpixel((x, y)) with sync_playwright() as playwright: browser = playwright.chromium.launch(headless=True, executable_path='/usr/bin/chromium', args=['--no-sandbox']) for width in (375, 1440): page = browser.new_page(viewport={'width': width, 'height': 900}) errors = [] page.on('pageerror', lambda error: errors.append(str(error))) page.set_content(HTML) page.add_style_tag(content=CSS) for corner, radius in CORNERS.items(): page.evaluate('corner => document.documentElement.dataset.cornerStyle = corner', corner) actual = page.evaluate('''() => { const ids = ['cp-hot-entries-meter','cp-memory','cp-cold-entries-meter','cp-cold-disk', 'overview-progress','overview-fill','memory-meter','memory-meter-fill','www-segmented','www-top','www-top-fill', 'traffic-track','traffic-fill']; return Object.fromEntries(ids.map(id => [id, getComputedStyle(document.getElementById(id)).borderRadius])); }''') assert all(value == radius for value in actual.values()), (corner, radius, actual) actual_pseudo = page.evaluate('''() => { const p = document.getElementById('cp-memory'); return ['::-webkit-progress-bar', '::-webkit-progress-value'].map(pseudo => getComputedStyle(p, pseudo).borderRadius); }''') assert actual_pseudo == [radius, radius], (corner, actual_pseudo) for theme in ('dark', 'light'): page.evaluate('theme => document.documentElement.dataset.theme = theme', theme) for chart_style in STYLES: page.evaluate('style => document.documentElement.dataset.chartStyle = style', chart_style) observed = page.evaluate('''() => { const color = id => getComputedStyle(document.getElementById(id)).backgroundColor; const progress = document.getElementById('cp-memory'); return { chart:color('chart-swatch'), native:getComputedStyle(progress).accentColor, overview:color('overview-fill'), systemRam:color('memory-meter-fill'), www:color('www-top-fill'), traffic:color('traffic-fill'), track:getComputedStyle(progress).backgroundColor, overviewTrack:color('overview-progress'), systemTrack:color('memory-meter'), wwwTrack:color('www-top'), }; }''') assert len({observed[key] for key in ('chart', 'native', 'overview', 'systemRam', 'www', 'traffic')}) == 1, (theme, chart_style, observed) assert len({observed[key] for key in ('track', 'overviewTrack', 'systemTrack', 'wwwTrack')}) == 1, (theme, chart_style, observed) # Native progress on Chromium is painted by the WebKit pseudo-element; # a pixel check confirms the color, not just the accent-color property. if chart_style in ('default', 'neon', 'monochrome'): color = color_at_progress(page, 'cp-memory') chart_rgb = tuple(page.evaluate("""() => { const canvas = document.createElement('canvas'); canvas.width = canvas.height = 1; const ctx = canvas.getContext('2d'); ctx.fillStyle = getComputedStyle(document.getElementById('chart-swatch')).backgroundColor; ctx.fillRect(0, 0, 1, 1); return [...ctx.getImageData(0, 0, 1, 1).data].slice(0, 3); }""")) assert color == chart_rgb, (theme, chart_style, color, chart_rgb) assert not errors, errors page.close() browser.close() print('PASS: native Cache, System RAM, Overview, WWW and Traffic bars respond to 5 corners and 8 palettes (dark/light, 375/1440px).')