This commit is contained in:
Mateusz Gruszczyński committed 2026-10-14 16:07:58 +02:00
1 parent 4f36de240c
commit c41d1e00a2
18 files changed
+228 -336

No files matched your search

+24
View File
@@ -0,0 +1,24 @@
#!/usr/bin/env python3
"""Static regression for 0.32.7 follow-up; not a browser or Rust runtime test."""
from pathlib import Path
ROOT = Path(__file__).resolve().parents[2]
css = (ROOT / 'src/admin/web/style.css').read_text()
html = (ROOT / 'src/admin/web/index.html').read_text()
response = (ROOT / 'src/proxy/forward/response.rs').read_text()
helper = (ROOT / 'src/proxy/h2_graceful.rs').read_text()
for button_id in ['overview-refresh', 'overview-layout-open', 'overview-layout-unlock',
'overview-layout-open-settings', 'dashboard-widget-expand']:
assert f'id="{button_id}"' in html
assert '.page-intro-title-row>:is(.quiet, .outline) {\n min-height:' not in css
assert 'dashboard-widget-settings-controls>button {\n min-height:' not in css
assert 'html[data-button-style=compact] body' in css
for mode in ['normal', 'compact', 'ultra']:
assert f'html[data-dashboard-density={mode}] #panel-overview .dashboard-overview-grid>.card:not(.pool-card)' in css
assert 'upstream_health_error_class(&cause, connect_failure, &active_backend)' in response
assert 'let graceful_h2_close = matches!(' in response
assert 'tracing::trace!(' in response
assert 'StatusCode::BAD_GATEWAY' in response
assert 'Some(detail.clone())' in response
assert 'recently_saw_graceful_goaway()' in helper
print('PASS: shared button CSS, density variants, guarded graceful-H2 logging (source only)')
+83
View File
@@ -0,0 +1,83 @@
#!/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'<button\b(?=[^>]*\bid="' + re.escape(button_id) + r'")[\s\S]*?</button>', index)
assert match, button_id
return match.group(0).replace(' hidden', '')
html = f'''<!doctype html><html data-theme="dark"><head><meta name="viewport" content="width=device-width, initial-scale=1"><style>{css}</style></head>
<body><main style="max-width:100%;padding:10px;box-sizing:border-box">
<div class="page-intro-title-row"><h1>Overview</h1>
{button('overview-refresh')}{button('overview-layout-open')}{button('overview-layout-unlock')}</div>
<div class="appearance-settings-grid dashboard-appearance-grid"><div class="dashboard-widget-settings"><div class="dashboard-widget-settings-controls">
{button('overview-layout-open-settings')}{button('dashboard-widget-expand')}
</div></div></div>
<div>{'<button class="quiet" id="reference-quiet">Reference</button><button class="outline" id="reference-outline">Reference</button>'}</div>
<section id="panel-overview"><div class="stats-grid dashboard-overview-grid is-aligned">
<article class="stat stat-chart" data-dashboard-widget="http_protocol"><span>Requests</span><strong>100</strong><small>Rate</small><svg viewBox="0 0 100 25"></svg></article>
<article class="card" data-dashboard-widget="diagnostics"><div class="card-heading"><h2>Diagnostics</h2></div><p>Metrics</p></article>
</div></section></main></body></html>'''
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()
+2 -2
View File
@@ -150,7 +150,7 @@ for marker in [
assert "data" in (root / ".dockerignore").read_text().splitlines()
css = (root / "src/admin/web/style.css").read_text()
assert ".logging-grid fieldset" not in css, "logging sinks must reuse shared card styling"
assert re.search(r"dialog\.config-history-dialog,\s*dialog\.config-history-json-dialog\s*\{", css), "Revision History and JSON comparison must use shared dialog styling"
assert re.search(r"dialog\.config-history-dialog,\s*dialog\.config-history-json-dialog,\s*dialog\.logs-dialog,", css), "Revision History and JSON comparison must use shared dialog styling"
assert ".config-history-dialog::backdrop" not in css, "Revision History must not duplicate the shared dialog backdrop"
history_dialog_css = re.search(r"^\.config-history-dialog\s*\{([^}]*)\}", css, re.M).group(1)
assert "border-radius:" not in history_dialog_css, "Revision History dialog must stay square-cornered"
@@ -229,7 +229,7 @@ for marker in ['toggleVhostEnabled', 'vhQuickEnable', 'vhQuickDisable', 'backend
assert 'rustproxy-backend-table-v1' not in vhosts_js and 'poolTablePreferenceKey' not in vhosts_js
assert 'window.rustProxyPreferences.update({' in vhosts_js and 'backend_table_sort' in vhosts_js and 'backend_table_descending' in vhosts_js
style_ui = (root / 'src/admin/web/style.css').read_text()
for marker in ['--scrollbar-thumb', '*::-webkit-scrollbar-thumb', '.backend-table-tools', '.vh-enable-control', '.vhost-quick-toggle', '.dashboard-widget-toggle', '--toolbar-control-height: min(var(--button-min-height), var(--ui-field-min-height))', 'height: var(--toolbar-control-height)']:
for marker in ['--scrollbar-thumb', '::-webkit-scrollbar-thumb', '.backend-table-tools', '.vh-enable-control', '.vhost-quick-toggle', '.dashboard-widget-toggle', '--toolbar-control-height: min(var(--button-min-height), var(--ui-field-min-height))', 'height: var(--toolbar-control-height)']:
assert marker in style_ui, marker
preferences_js = (root / "src/admin/web/app/preferences.js").read_text()
assert 'dashboard-widget-toggle' in preferences_js and 'visible.type = "checkbox"' not in preferences_js
@@ -18,7 +18,7 @@ assert.match(css, /\.appearance-settings-grid\.dashboard-appearance-grid\s*\{[^}
assert.match(css, /\.dashboard-appearance-grid \.dashboard-widget-list\s*\{[^}]*flex-wrap:\s*nowrap;[^}]*overflow-x:\s*auto;/s,
'the default card selector must be a horizontal ribbon, not a tall two-column list');
assert.match(css, /\.dashboard-appearance-grid \.dashboard-widget-list\.is-expanded\s*\{[^}]*display:\s*grid;/s);
assert.match(css, /\.dashboard-widget-settings-controls > \.dashboard-widget-scroll-button/);
assert.match(css, /\.dashboard-widget-settings-controls\s*>\s*\.dashboard-widget-scroll-button/);
assert(js.includes('list.scrollLeft = previousScroll'), 'rebuilding settings must preserve horizontal scroll position');
assert(js.includes('focusedId') && js.includes('preventScroll: true'), 'keyboard focus must survive updates');
assert(js.includes('saveAppearancePreference({ dashboard_hidden_widgets:') &&
+4 -4
View File
@@ -15,8 +15,8 @@ assert 'grid-template-columns: repeat(2, minmax(0, 1fr))' in css
assert '@container overview-canvas (max-width: 700px)' in css
assert 'overview-canvas (max-width: 440px)' not in css
assert '.vhost-backend-protocol-badge' in css
assert '.vhost-card' in css[css.index('/* Global shape preference.'):]
assert '.draft-dock,' not in css[css.index('/* Global shape preference.'):]
assert '.vhost-card' in css[css.index('html:is([data-corner-style=square]'):]
assert '.draft-dock,' not in css[css.index('html:is([data-corner-style=square]'):]
assert 'grid.append(...orderedNodes)' in preferences
assert 'orderedNodes.some((node, index) => node !== currentNodes[index])' in preferences
assert 'if (ordered.some((node, i) => node !== previous[i])) grid.append(...ordered);' in masonry
@@ -31,8 +31,8 @@ policy_block=render[policy_start:policy_end]
assert 'policy.append(badge);' in policy_block
assert 'vhost-backend-protocol-badge' in policy_block
assert 'box.append(badges)' not in render
assert '.vhost-backend-protocol-badge[data-observed="true"]' in css
assert 'color: var(--green)' in css[css.index('.vhost-backend-protocol-badge[data-observed="true"]'):]
assert '.vhost-backend-protocol-badge[data-observed=true]' in css
assert 'color: var(--green)' in css[css.index('.vhost-backend-protocol-badge[data-observed=true]'):]
assert 'self.inner.observe_protocol(value.version())' in client
assert '"upstream_protocol_observed"' in pool
print('PASS: mobile grid, shape, stable reorder and observed backend protocol source contracts')
@@ -56,7 +56,7 @@ with sync_playwright() as playwright:
for card_density in ("normal", "compact", "ultra"):
page.evaluate("d => document.documentElement.dataset.dashboardDensity = d", card_density)
data = page.evaluate(snapshot)
expected = max(3, old_gap - 1)
expected = old_gap
assert abs(data["parentGap"] - old_gap) < 0.01, data
assert abs(data["rowGap"] - expected) < 0.01, data
assert abs(data["columnGap"] - expected) < 0.01, data
+1 -1
View File
@@ -42,7 +42,7 @@ css=read('src/admin/web/style.css')
match=re.search(r'#panel-overview \.dashboard-overview-grid\.is-aligned\s*\{([^}]*)\}',css)
assert match
rules=match[1]
for marker in ['margin: 0;', '--overview-gap: max(3px, calc(var(--ui-gap) - 1px));',
for marker in ['margin: 0;', '--overview-gap: var(--ui-gap);',
'row-gap: var(--overview-gap);', 'column-gap: var(--overview-gap);',
'gap: var(--overview-gap);']:
assert marker in rules, marker
+1 -1
View File
@@ -448,7 +448,7 @@ def ui_contract_smoke() -> None:
assert './dev.sh tls deploy' not in document_text
assert '/opt/rustproxy/current/rust-proxy --data-dir /var/lib/rustproxy tls deploy' in document_text
style = (ROOT / "src/admin/web/style.css").read_text(encoding="utf-8")
for marker in ['--scrollbar-thumb', '*::-webkit-scrollbar-thumb', '.backend-table-tools', '.vhost-quick-toggle', '.dashboard-widget-toggle', '--toolbar-control-height: min(var(--button-min-height), var(--ui-field-min-height))', 'height: var(--toolbar-control-height)']:
for marker in ['--scrollbar-thumb', '::-webkit-scrollbar-thumb', '.backend-table-tools', '.vhost-quick-toggle', '.dashboard-widget-toggle', '--toolbar-control-height: min(var(--button-min-height), var(--ui-field-min-height))', 'height: var(--toolbar-control-height)']:
assert marker in style, marker
assert "pool-vhost-disabled" in vhosts
for marker in ["locationMatchRegex", "headersVisualBuilder", "headersAdvancedJson", "openLocationHelp", "cloudflare-client-ip", "timing-headers"]: