#!/usr/bin/env node // 0.31.7 DOM/source + executable revision-diff tests (no Rust runtime). import assert from 'node:assert/strict'; import fs from 'node:fs'; import vm from 'node:vm'; const read = path => fs.readFileSync(path, 'utf8'); const html = read('src/admin/web/index.html'); const css = read('src/admin/web/style.css'); const settings = read('src/admin/web/settings.js'); const hist = read('src/admin/web/app/config-history.js'); const management = read('src/admin/web/management.js'); const listener = read('src/admin/web/integrations.js'); const router = read('src/admin/router.rs'); const core = read('src/admin/web/vhosts/core.js'); const editor = read('src/admin/web/vhosts/editor.js'); const rates = read('src/admin/web/vhosts/rates.js'); const model = read('src/rate_limit.rs'); const api = JSON.parse(read('src/admin/openapi.json')); assert.match(html, /data-settings-tab="policies"/); for (const name of ['user-agent', 'headers', 'response']) { assert.match(html, new RegExp(`data-policy-settings-tab="${name}"`)); assert.match(html, new RegExp(`data-policy-settings-page="${name}"`)); } for (const form of ['global-ua-block-form', 'headers-form', 'response-form']) { assert.equal(html.split(`id="${form}"`).length, 2, `${form} must be unique`); } assert.match(settings, /selectPolicyTab\("user-agent"\)/); assert.match(html, /id="config-history-json-dialog"/); assert.match(html, /id="config-history-compare-open"/); const actionStart = html.indexOf('
'); const actionEnd = html.indexOf('
', actionStart); const restorePos = html.indexOf('id="config-history-restore"', actionStart); const comparePos = html.indexOf('id="config-history-compare-open"', actionStart); assert.ok(actionStart > -1 && restorePos > actionStart && comparePos > restorePos && comparePos < actionEnd, 'JSON compare button must appear directly under restore inside the same action group'); assert.equal(html.split('id="config-history-compare-open"').length, 2); assert.match(html, /id="config-json-compare-title"[\s\S]*?
[\s\S]*?id="config-history-json-close"/); assert.match(css, /dialog\.config-history-dialog,\s*dialog\.config-history-json-dialog\s*\{/); assert.match(css, /\.config-history-dialog\[open\]\s*\{[^}]*grid-template-rows:\s*auto minmax\(0, 1fr\)/); assert.match(css, /\.config-history-diff\s*\{[^}]*overflow-y:\s*auto/); assert.match(css, /\.config-history-layout\s*\{[^}]*overflow:\s*hidden/); assert.match(css, /@media \(max-width:\s*860px\)\s*\{[\s\S]*?\.config-history-layout\s*\{[^}]*overflow-y:\s*auto/); assert.match(css, /\.config-history-json-columns pre\s*\{[^}]*border:\s*0/); assert.match(hist, /"config-history-json-before"\)\.textContent/); assert.match(hist, /"config-history-json-after"\)\.textContent/); assert.match(css, /\.listener-protocol-settings-actions\s*\{[^}]*gap:\s*14px/); assert.match(listener, /listener-protocol-settings-actions/); assert.match(management, /el\("details", undefined, "acl-profile-attached"\)/); assert.doesNotMatch(management, /attached\.open\s*=\s*true/); assert.match(router, /include_str!\("web\/vhosts\/rates\.js"\)/); assert.match(editor, /user_agent_limits: uaRatesReader\(\)/); assert.match(editor, /userAgentRateEditor\(g, rate\.user_agent_limits \|\| \[\]\)/); assert.match(core, /uaRatesReader/); assert.match(rates, /function userAgentRateEditor/); assert.match(model, /pub user_agent_limits: Vec/); assert.ok(api.components.schemas.VhostRateLimit.properties.user_agent_limits); const start = hist.indexOf('function configDiff('), end = hist.indexOf('function renderConfigRevisionDetail(', start); assert.ok(start > 0 && end > start, 'executable diff function must exist'); const context = { before: null, after: null }; vm.createContext(context); vm.runInContext(`${hist.slice(start, end)}\nglobalThis.diffResult = () => configDiff(before, after);`, context); const diff = (before, after) => { context.before=before; context.after=after; return JSON.parse(JSON.stringify(context.diffResult())); }; let result = diff({port:80, x:{a:true, b:2}, vhosts:[{id:'v1', host:'a'},{id:'v2', host:'b'}]}, {port:443, x:{a:true, b:3}, vhosts:[{id:'v2', host:'b'},{id:'v1', host:'a'}]}); assert.deepEqual(result.map(x => x.path), ['$["port"]','$["x"]["b"]']); result = diff({a:1, headers:[]}, {a:1, headers:[{id:'one',value:'ok'}], policy:true}); assert.deepEqual(result.map(x => x.path), ['$["headers"]["one"]["id"]','$["headers"]["one"]["value"]','$["policy"]']); result = diff({items: [{id:'one', active: true}]}, {items: [{id:'one',active:false}]}); assert.equal(result.length,1); assert.equal(result[0].path,'$["items"]["one"]["active"]'); assert.ok(diff({}, Object.fromEntries(Array.from({length:350},(_,i) => [i, i]))).length <= 200); console.log('PASS: 0.31.7 Settings sections, vhost UA rate editor/API, ACL/listener layout, changed-field revision diff, bounded scrolling, conventional full JSON modal.');