v0.33.7
This commit is contained in:
1 parent
162e986d37
commit
f462ca7194
26 files changed
+980
-710
No files matched your search
+189
@@ -0,0 +1,189 @@
|
||||
#!/usr/bin/env python3
|
||||
"""0.33.7 Dashboard preset manager and chart-title font regression.
|
||||
|
||||
Runs the bundled administration DOM/CSS/JavaScript with mocked account preferences.
|
||||
This is simulated-browser UI coverage, not a live RustProxy server test.
|
||||
"""
|
||||
import json
|
||||
import re
|
||||
from pathlib import Path
|
||||
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")
|
||||
PACKS = {
|
||||
name: {"id": name, **json.loads((ROOT / "langs" / f"{name}.json").read_text(encoding="utf-8"))}
|
||||
for name in ("en_US", "pl_pl")
|
||||
}
|
||||
|
||||
|
||||
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" / f"{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)
|
||||
|
||||
|
||||
BUNDLE = app_bundle()
|
||||
|
||||
|
||||
def load(page):
|
||||
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.wait_for_function("window.rustProxyPreferences && window.rustProxyDashboardLayout")
|
||||
page.evaluate("""packs => {
|
||||
languagePacks = new Map(Object.entries(packs));
|
||||
defaultLanguage = 'en_US';
|
||||
language = 'pl_pl';
|
||||
document.documentElement.lang = 'pl-PL';
|
||||
document.documentElement.classList.remove('app-loading', 'app-startup-failed');
|
||||
document.getElementById('workspace').hidden = false;
|
||||
document.getElementById('panel-overview').hidden = false;
|
||||
document.getElementById('overview-layout-open').hidden = false;
|
||||
currentPanel = 'overview';
|
||||
const visible = ['connection_chart', 'traffic_chart'];
|
||||
const hidden = ADMIN_DASHBOARD_WIDGETS.filter(id => !visible.includes(id));
|
||||
window.__savedDashboard = {
|
||||
...structuredClone(ADMIN_APPEARANCE_DEFAULTS),
|
||||
language: 'pl_pl',
|
||||
dashboard_density: 'ultra',
|
||||
dashboard_widgets: [...visible, ...hidden],
|
||||
dashboard_hidden_widgets: hidden,
|
||||
dashboard_widget_sizes: {connection_chart: 6, traffic_chart: 3},
|
||||
dashboard_presets: [],
|
||||
};
|
||||
window.rustProxyPreferences.load = async () => window.__savedDashboard;
|
||||
window.rustProxyPreferences.current = () => window.__savedDashboard;
|
||||
window.rustProxyPreferences.update = async patch => {
|
||||
window.__savedDashboard = {...window.__savedDashboard, ...structuredClone(patch)};
|
||||
applyAdminPreferences(window.__savedDashboard);
|
||||
return window.__savedDashboard;
|
||||
};
|
||||
applyAdminPreferences(window.__savedDashboard);
|
||||
language = 'pl_pl'; languagePreference = 'pl_pl';
|
||||
for (const node of document.querySelectorAll('#overview-layout-dialog [data-i18n]'))
|
||||
node.textContent = t(node.dataset.i18n);
|
||||
for (const node of document.querySelectorAll('#overview-layout-dialog [data-i18n-placeholder]'))
|
||||
node.placeholder = t(node.dataset.i18nPlaceholder);
|
||||
}""", PACKS)
|
||||
|
||||
|
||||
with sync_playwright() as p:
|
||||
browser = p.chromium.launch(headless=True, executable_path="/usr/bin/chromium", args=["--no-sandbox"])
|
||||
for width in (320, 375, 768, 1440):
|
||||
page = browser.new_page(viewport={"width": width, "height": 900})
|
||||
errors = []
|
||||
page.on("pageerror", lambda error: errors.append(str(error)))
|
||||
load(page)
|
||||
|
||||
page.locator("#overview-layout-open").click()
|
||||
page.wait_for_function("document.getElementById('overview-layout-dialog').open")
|
||||
assert page.locator("#overview-layout-dialog-title").inner_text() == "Presety Dashboardu"
|
||||
assert page.locator("#overview-layout-visible").count() == 0
|
||||
assert page.locator("#overview-layout-hidden").count() == 0
|
||||
geom = page.locator("#overview-layout-dialog").evaluate("""node => ({
|
||||
left: node.getBoundingClientRect().left,
|
||||
right: node.getBoundingClientRect().right,
|
||||
client: node.clientWidth,
|
||||
scroll: node.scrollWidth,
|
||||
})""")
|
||||
assert geom["left"] >= -1 and geom["right"] <= width + 1, (width, geom)
|
||||
assert geom["scroll"] <= geom["client"] + 2, (width, geom)
|
||||
|
||||
page.locator("#overview-preset-name").fill("NOC")
|
||||
page.locator("#overview-preset-save").click()
|
||||
page.wait_for_function("window.__savedDashboard.dashboard_presets.length === 1")
|
||||
saved = page.evaluate("window.__savedDashboard.dashboard_presets[0]")
|
||||
assert saved["name"] == "NOC"
|
||||
assert saved["dashboard_density"] == "ultra"
|
||||
assert saved["dashboard_widgets"][:2] == ["connection_chart", "traffic_chart"]
|
||||
assert len(saved["dashboard_hidden_widgets"]) == len(saved["dashboard_widgets"]) - 2
|
||||
assert saved["dashboard_widget_sizes"] == {"connection_chart": 6, "traffic_chart": 3}
|
||||
assert page.locator("#overview-preset-list .dashboard-preset-row").count() == 1
|
||||
assert "2 widocznych kart" in page.locator(".dashboard-preset-info small").inner_text()
|
||||
page.locator("#overview-preset-name").fill("NOC")
|
||||
page.locator("#overview-preset-save").click()
|
||||
page.wait_for_function("document.getElementById('overview-layout-message').textContent.includes('Zaktualizowano')")
|
||||
assert page.evaluate("window.__savedDashboard.dashboard_presets.length") == 1
|
||||
|
||||
page.locator("#overview-layout-cancel").click()
|
||||
page.evaluate("""async () => {
|
||||
await window.rustProxyPreferences.update({
|
||||
dashboard_density: 'normal',
|
||||
dashboard_widgets: [...ADMIN_DASHBOARD_WIDGETS],
|
||||
dashboard_hidden_widgets: [],
|
||||
dashboard_widget_sizes: null,
|
||||
});
|
||||
}""")
|
||||
page.locator("#overview-layout-open").click()
|
||||
page.locator("#overview-preset-list .outline").click()
|
||||
page.wait_for_function("!document.getElementById('overview-layout-dialog').open")
|
||||
restored = page.evaluate("""() => ({
|
||||
density: window.__savedDashboard.dashboard_density,
|
||||
hidden: window.__savedDashboard.dashboard_hidden_widgets.length,
|
||||
sizes: window.__savedDashboard.dashboard_widget_sizes,
|
||||
})""")
|
||||
assert restored == {
|
||||
"density": "ultra",
|
||||
"hidden": len(saved["dashboard_hidden_widgets"]),
|
||||
"sizes": {"connection_chart": 6, "traffic_chart": 3},
|
||||
}, (width, restored)
|
||||
|
||||
fonts = page.evaluate("""() => {
|
||||
const family = selector => getComputedStyle(document.querySelector(selector)).fontFamily;
|
||||
return {
|
||||
connection: family('[data-dashboard-widget="connection_chart"] .small-label'),
|
||||
traffic: family('[data-dashboard-widget="traffic_chart"] .card-heading h2'),
|
||||
wide: family('[data-dashboard-widget="wide_cpu"] .card-heading h2'),
|
||||
compact: family('[data-dashboard-widget="http_protocol"] > span:first-child'),
|
||||
};
|
||||
}""")
|
||||
assert len(set(fonts.values())) == 1, (width, fonts)
|
||||
|
||||
page.locator("#overview-layout-open").click()
|
||||
page.once("dialog", lambda prompt: prompt.accept())
|
||||
page.locator("#overview-preset-list .quiet").click()
|
||||
page.wait_for_function("window.__savedDashboard.dashboard_presets.length === 0")
|
||||
assert page.locator("#overview-preset-list .dashboard-preset-row").count() == 0
|
||||
assert page.locator("#overview-preset-empty").is_visible()
|
||||
|
||||
# The browser enforces the same 20-preset limit as the preferences API.
|
||||
page.evaluate("""() => {
|
||||
const prefs = window.__savedDashboard;
|
||||
prefs.dashboard_presets = Array.from({length: 20}, (_, index) => ({
|
||||
name: `Preset ${index + 1}`,
|
||||
dashboard_density: prefs.dashboard_density,
|
||||
dashboard_widgets: [...prefs.dashboard_widgets],
|
||||
dashboard_hidden_widgets: [...prefs.dashboard_hidden_widgets],
|
||||
dashboard_widget_sizes: prefs.dashboard_widget_sizes === null ? null : {...prefs.dashboard_widget_sizes},
|
||||
}));
|
||||
applyAdminPreferences(prefs);
|
||||
window.rustProxyDashboardLayout.refresh();
|
||||
}""")
|
||||
assert page.locator("#overview-preset-list .dashboard-preset-row").count() == 20
|
||||
page.locator("#overview-preset-name").fill("Preset 21")
|
||||
page.locator("#overview-preset-save").click()
|
||||
assert page.evaluate("window.__savedDashboard.dashboard_presets.length") == 20
|
||||
assert "Osiągnięto limit presetów" in page.locator("#overview-layout-message").inner_text()
|
||||
assert not errors, (width, errors)
|
||||
page.close()
|
||||
print(f"PASS Dashboard presets + chart title font at {width}px")
|
||||
browser.close()
|
||||
print("PASS 0.33.7 Dashboard preset manager regression (simulated API)")
|
||||
Reference in new issue
Block a user