Files
RustProxy/tools/checks/admin_panel_config_0314_ui_test.mjs
T
2026-10-11 13:56:30 +02:00

53 lines
3.6 KiB
JavaScript

// Test the real admin settings normalization helpers and visible form wiring;
// source-level UI test only, not a Rust or browser integration test.
import assert from 'node:assert/strict';
import fs from 'node:fs';
import vm from 'node:vm';
const js = fs.readFileSync('src/admin/web/settings.js','utf8');
const html = fs.readFileSync('src/admin/web/index.html','utf8');
const en = JSON.parse(fs.readFileSync('langs/en_US.json','utf8'));
const pl = JSON.parse(fs.readFileSync('langs/pl_pl.json','utf8'));
const api = JSON.parse(fs.readFileSync('src/admin/openapi.json','utf8'));
const begin = js.indexOf(' function pinnedAdminHostname(value) {');
const end = js.indexOf(' const normalizedRequestedTab', begin);
assert(begin >= 0 && end > begin, 'real admin form normalization helpers must exist');
const sandbox = vm.createContext({URL});
vm.runInContext(js.slice(begin,end),sandbox);
const normalize = (hosts, pin) => Array.from(vm.runInContext(
`additionalAdminHosts(${JSON.stringify(hosts)},${JSON.stringify(pin)})`,sandbox));
const cases = [
{name:'empty form',hosts:[],pin:null,expected:[]},
{name:'simple single origin',hosts:[],pin:'https://panel.example.test',expected:[]},
{name:'0.31.4 repeated host',hosts:['panel.example.test'],pin:'https://panel.example.test',expected:[]},
{name:'case and trailing dot',hosts:['PANEL.Example.Test.',' other.example.test '],pin:'https://panel.example.test:8443',expected:['other.example.test']},
{name:'multiple additional names',hosts:['foo.example.test','panel.example.test','bar.example.test'],pin:'https://panel.example.test',expected:['foo.example.test','bar.example.test']},
{name:'pin changed',hosts:['other.example.test'],pin:'https://new.example.test',expected:['other.example.test']},
{name:'no pin means independent allowlist',hosts:['panel.example.test'],pin:'',expected:['panel.example.test']},
{name:'invalid URL delegates to server validation',hosts:['other.example.test'],pin:'not a url',expected:['other.example.test']},
{name:'blank host lines removed',hosts:['',' panel.example.test ',' '],pin:null,expected:['panel.example.test']},
];
for (const item of cases) {
assert.deepEqual(normalize(item.hosts,item.pin),item.expected,item.name);
}
const admin = html.split('id="settings-page-administration"')[1].split('id="settings-page-system-info"')[0];
for (const id of ['admin-public-origin','admin-extra-hosts-details','admin-hosts'])
assert(admin.includes(`id="${id}"`),`missing ${id}`);
assert(admin.indexOf('id="admin-public-origin"') < admin.indexOf('id="admin-extra-hosts-details"'));
assert(admin.includes('<details id="admin-extra-hosts-details">'));
assert(js.includes('$("admin-extra-hosts-details").open = extraHosts.length > 0'));
assert(js.includes('additionalAdminHosts(admin.allowed_hosts || [], admin.public_origin)'));
assert(js.includes('allowed_hosts: additionalAdminHosts($("admin-hosts").value.split('));
assert(!js.includes('allowed_hosts: $("admin-hosts").value.split('));
for (const key of ['administrationHosts','administrationHostsAdvanced','administrationHostsHelp','administrationPublicOriginHelp']) {
assert.equal(typeof en.translations[key],'string'); assert.equal(typeof pl.translations[key],'string');
assert(en.translations[key].length > 15 && pl.translations[key].length > 15,key);
}
// Config contract remains compatible; the pin allows a host implicitly.
const spec = api.components?.schemas || api.definitions;
const specText=JSON.stringify(spec);
assert(specText.includes('implicitly allowed'));
assert(specText.includes('automatically allowed'));
console.log(`PASS: ${cases.length} real settings-helper scenarios, HTML/wiring, locale parity and OpenAPI descriptions`);