import assert from 'node:assert/strict'; import fs from 'node:fs'; const read = path => fs.readFileSync(new URL(`../../${path}`, import.meta.url), 'utf8'); const html = read('src/admin/web/index.html'); const js = read('src/admin/web/file-logs.js'); const css = read('src/admin/web/style.css'); const en = JSON.parse(read('langs/en_US.json')).translations; const pl = JSON.parse(read('langs/pl_pl.json')).translations; const header = html.indexOf('class="file-logs-heading-actions"'); const filter = html.indexOf('id="file-logs-filter"'); const toggle = html.indexOf('id="file-log-consolidate-vhosts"'); assert.ok(header >= 0 && header < toggle && toggle < filter, 'compact consolidation switch belongs in header'); assert.equal((html.match(/id="file-log-consolidate-vhosts"/g) || []).length, 1); for (const view of ['entries','counts']) { assert.match(html, new RegExp(`id="file-log-tab-${view}"[^>]+role="tab"`)); assert.match(html, new RegExp(`id="file-log-view-${view}"[^>]+role="tabpanel"`)); } assert.match(html, /id="file-log-view-counts"[^>]+hidden/); assert.ok(html.indexOf('id="file-log-aggregate-form"') > html.indexOf('id="file-log-view-counts"')); assert.ok(html.indexOf('id="file-log-aggregate-form"') < html.indexOf('id="file-log-view-entries"')); assert.match(js, /function setView\(view\)/); assert.match(js, /aria-selected/); assert.match(js, /\$\("file-log-view-" \+ name\)\.hidden = !selected/); assert.match(js, /activeView === "counts" && aggregateField/); assert.match(js, /localStorage\.setItem\(CONSOLIDATION_STORAGE_KEY/); assert.match(css, /#file-log-view-counts\[hidden\], #file-log-view-entries\[hidden\]/); for (const strings of [en, pl]) for (const key of ['fileLogsConsolidateShort', 'fileLogsEntriesTab','fileLogsCountsTab']) assert.ok(strings[key], key); console.log('PASS: Stored Logs separate tabs, shared filter, compact persisted consolidation toggle, localized UI.');