Files
RustProxy/tools/checks/overview_registry_0323_ui_test.mjs
T
2026-10-13 21:29:57 +02:00

73 lines
5.6 KiB
JavaScript

// Regression for shared server/browser Overview Cards metadata and future opt-in widgets.
import fs from 'node:fs';
import vm from 'node:vm';
import assert from 'node:assert/strict';
const registry = JSON.parse(fs.readFileSync('src/admin/web/dashboard-widgets.json','utf8'));
const prefs = fs.readFileSync('src/admin/web/app/preferences.js','utf8');
const constants = prefs.slice(prefs.indexOf('const ADMIN_DASHBOARD_WIDGETS'), prefs.indexOf('const CHART_STYLE_KEYS'));
const normalize = prefs.slice(prefs.indexOf('function normalizeDashboardWidgets'),prefs.indexOf('function browserLanguage'));
const label = prefs.slice(prefs.indexOf('function dashboardWidgetLabel'),prefs.indexOf('function renderDashboardWidgetSettings'));
assert(constants.startsWith('const ADMIN_DASHBOARD_WIDGETS'));
assert(normalize.startsWith('function normalizeDashboardWidgets'));
assert(label.startsWith('function dashboardWidgetLabel'));
function client(definitions) {
const context = {t: key => `loc:${key}`};
vm.createContext(context);
vm.runInContext(`const ADMIN_DASHBOARD_WIDGET_REGISTRY = Object.freeze(${JSON.stringify(definitions)});\n${constants}\n${normalize}\n${label}\n`,context);
return {
order: value => [...vm.runInContext(`normalizeDashboardWidgets(${JSON.stringify(value)})`,context)],
hidden: (value,saved) => [...vm.runInContext(`normalizeHiddenDashboardWidgets(${JSON.stringify(value)},${JSON.stringify(saved)})`,context)],
label: id => vm.runInContext(`dashboardWidgetLabel(${JSON.stringify(id)})`,context),
};
}
const original = client(registry);
const previous = registry.filter(widget => widget.category === 'overview').map(widget => widget.id);
assert.deepEqual(original.order(previous),registry.map(widget => widget.id));
assert.deepEqual(original.hidden([],previous),registry.filter(widget=>widget.default_hidden).map(widget=>widget.id));
assert.equal(original.label('stream_overview'),'loc:streamWidgetOverview');
assert.equal(original.label('backend_health'),'loc:backendWidgetHealth');
assert.equal(original.label('backend_table'),'loc:vhHealthTitle');
assert.equal(registry.length, 62);
const types = new Set(['value', 'value_chart', 'chart', 'panel', 'table']);
assert(registry.every(widget => types.has(widget.display_type)), 'Every Overview block needs explicit type metadata');
assert.equal(registry.find(w => w.id === 'requests').display_type, 'value');
assert.equal(registry.find(w => w.id === 'backend_requests').display_type, 'value_chart');
assert.equal(registry.find(w => w.id === 'traffic_chart').display_type, 'chart');
assert.equal(registry.find(w => w.id === 'cache_diagnostics').display_type, 'panel');
assert.equal(registry.find(w => w.id === 'backend_table').display_type, 'table');
// Upgrading from the previous 30-widget 0.32.3 archive keeps its exact
// visible/order preferences: only twelve new metrics are opt-in, while
// seven existing large panels remain visible in the factory layout.
const previouslySaved = registry.slice(0, 30).map(widget => widget.id);
const migratedOrder = original.order(previouslySaved);
const migratedHidden = original.hidden(registry.slice(0, 30).filter(w => w.default_hidden).map(w => w.id), previouslySaved);
assert.deepEqual(migratedOrder.slice(0, 30), previouslySaved);
assert.deepEqual(migratedOrder.slice(30), registry.slice(30).map(widget => widget.id));
for (const widget of registry.filter(widget => widget.category === 'performance'))
assert(migratedHidden.includes(widget.id), `${widget.id} must be opt-in after upgrade`);
for (const widget of registry.filter(widget => widget.category === 'panels' && !widget.default_hidden))
assert(!migratedHidden.includes(widget.id), `${widget.id} must retain default visibility`);
for (const widget of registry.filter(widget => widget.id.startsWith('wide_')))
assert(migratedHidden.includes(widget.id), `${widget.id} is a new opt-in chart`);
assert.equal(registry.filter(widget => widget.category === 'panels').length, 14);
for (const widget of registry.filter(widget => widget.category === 'performance')) assert(widget.default_hidden);
for (const id of ['backend_health','backend_activity','backend_errors','backend_latency','backend_traffic','backend_protocols','backend_requests','backend_capacity','backend_http5xx','backend_timeouts','backend_network','backend_retries','backend_queue','backend_rotations'])
assert(original.hidden([],previous).includes(id), `${id} must remain opt-in for older preferences`);
assert.deepEqual(original.order(['errors','unknown-0.33.0','requests','errors']).slice(0,2),['errors','requests']);
assert(original.hidden(['unknown-0.33.0','http3'],registry.map(widget=>widget.id)).includes('http3'));
assert(!original.hidden(['unknown-0.33.0','http3'],registry.map(widget=>widget.id)).includes('unknown-0.33.0'));
// Adding a new registry card, with an existing UI element and translation key,
// automatically offers it in the ordered preference list and hides it by default.
const extra={...registry[0], id:'future_upstream', label_key:'futureUpstreamProtocol',
description_key:null, element_selector:'[data-dashboard-widget="future_upstream"]', default_hidden:true};
const expanded=client([...registry,extra]);
assert.equal(expanded.order(previous).at(-1),'future_upstream');
assert(expanded.hidden([],previous).includes('future_upstream'));
assert.equal(expanded.label('future_upstream'),'loc:futureUpstreamProtocol');
assert(!expanded.hidden([],registry.map(widget=>widget.id).concat('future_upstream')).includes('future_upstream'),
'explicitly opted-in widget must not become hidden after a later release');
console.log(`PASS: shared widget registry UI preserves order, visibility and ${registry.length} existing cards`);