Files
RustProxy/scripts/tests/dashboard_chart_headers_0335_browser_test.py
T
2026-10-15 15:36:35 +02:00

97 lines
5.4 KiB
Python
Executable File

#!/usr/bin/env python3
"""Overview traffic/connection heading cleanup against Chromium and the bundled JS.
Runs a simulated authenticated DOM rather than a live RustProxy service.
"""
from pathlib import Path
import json
import re
from playwright.sync_api import sync_playwright
ROOT = Path(__file__).resolve().parents[2]
HTML = (ROOT / 'src/admin/web/index.html').read_text(encoding='utf-8')
CSS = (ROOT / 'src/admin/web/style.css').read_text(encoding='utf-8')
ROUTER = (ROOT / 'src/admin/router.rs').read_text(encoding='utf-8')
def app_bundle():
match = re.search(r'fn admin_app_javascript\([^)]*\)[^{]*\{', ROUTER)
assert match
body = ROUTER[match.end():]
body = body[:re.search(r'\]\s*\.join\("\\n"\)', body).start()]
result = []
for line in body.splitlines():
line = line.strip()
include = re.search(r'include_str!\("([^"]+)"\)', line)
if include:
result.append((ROOT / 'src/admin' / include.group(1)).read_text(encoding='utf-8'))
elif line == 'admin_vhosts_javascript(),':
result.append('(() => {\n' + '\n'.join(
(ROOT / 'src/admin/web/vhosts' / (name + '.js')).read_text(encoding='utf-8')
for name in ('core', 'protocol', 'health', 'rates', 'editor', 'render')) + '\n})();')
elif line.startswith('"') and line.endswith('",'):
result.append(json.loads(line[:-1]))
return '\n'.join(result)
with sync_playwright() as p:
browser = p.chromium.launch(headless=True, executable_path='/usr/bin/chromium', args=['--no-sandbox'])
bundle = app_bundle()
for width in (320, 375, 768, 1440, 1920):
page = browser.new_page(viewport={'width': width, 'height': 920})
errors = []
page.on('pageerror', lambda error: errors.append(str(error)))
page.set_content(HTML.replace('/assets/app___RUSTPROXY_ASSET_ID__.js', '')
.replace('/assets/style___RUSTPROXY_ASSET_ID__.css', ''))
page.add_style_tag(content=CSS)
page.add_script_tag(content=bundle)
page.evaluate('''() => {
document.documentElement.classList.remove('app-loading', 'app-startup-failed');
document.getElementById('workspace').hidden = false;
document.getElementById('panel-overview').hidden = false;
currentPanel = 'overview';
samples.splice(0); samples.push(1.5, 85.5, 12.3);
redrawOverviewHistoryCharts();
}''')
for density in ('normal', 'compact', 'ultra'):
for span in (3, 6):
data = page.evaluate('''({density,span}) => {
document.documentElement.dataset.dashboardDensity = density;
const visible = ['traffic_chart', 'connection_chart'];
const hidden = ADMIN_DASHBOARD_WIDGETS.filter(id => !visible.includes(id));
applyDashboardLayout([...visible,...hidden], hidden,
{traffic_chart:span,connection_chart:span});
const traffic = document.querySelector('[data-dashboard-widget="traffic_chart"]');
const connection = document.querySelector('[data-dashboard-widget="connection_chart"]');
const heading = traffic.querySelector('.card-heading');
const peak = traffic.querySelector('#chart-peak');
const peakRect = peak.getBoundingClientRect();
const cardRect = traffic.getBoundingClientRect();
const headingRect = heading.getBoundingClientRect();
return {
title: heading.querySelector('h2')?.textContent.trim(),
peak: peak.textContent,
peakInHeading: peak.parentElement === heading,
peakNotInFooter: !traffic.querySelector('.chart-footer #chart-peak'),
noTrafficEyebrow: !traffic.querySelector('.small-label'),
noTrafficLiveBadge: !traffic.querySelector('.pill.live'),
noConnectionLiveBadge: !connection.querySelector('.pill.live'),
connectionTitleIntact: !!connection.querySelector('.card-heading .small-label[data-i18n="connectionActivity"]'),
peakInsideCard: peakRect.left >= cardRect.left - 1 && peakRect.right <= cardRect.right + 1,
peakInsideHeading: peakRect.top >= headingRect.top - 1 && peakRect.bottom <= headingRect.bottom + 1,
browserOverflow: document.documentElement.scrollWidth - innerWidth,
};
}''', {'density':density,'span':span})
assert data['title'] == 'Requests per second', (width, density, span, data)
assert data['peak'] == 'max 85.5 req/s', (width, density, span, data)
for key in ('peakInHeading', 'peakNotInFooter', 'noTrafficEyebrow',
'noTrafficLiveBadge', 'noConnectionLiveBadge',
'connectionTitleIntact', 'peakInsideCard', 'peakInsideHeading'):
assert data[key], (width, density, span, key, data)
assert data['browserOverflow'] <= 2, (width, density, span, data)
assert not errors, (width, errors)
print(f'PASS traffic/connection chart headers at {width}px (all densities, spans 3 and 6)')
page.close()
browser.close()
print('PASS Overview chart heading cleanup')