Asset / _validate_router_dom.js
Your Name
Fix router FOUC rule permanently hiding all pages; add DOM/computed-style route validators
4fc5db8
Raw
History Blame Contribute Delete
3.83 kB
const fs = require('fs');
const { JSDOM } = require('jsdom');
const html = fs.readFileSync('hermes_overlay/tools/templates/hermes_futures_desk_luxury.html', 'utf8');
async function run() {
const dom = new JSDOM(html, { url: 'https://example.test/futures', runScripts: 'dangerously', resources: 'usable', pretendToBeVisual: true });
// Stub fetch so the app's background refresh calls don't explode / hang.
dom.window.fetch = () => Promise.reject(new Error('network disabled in test'));
await new Promise(r => setTimeout(r, 300)); // let inline <script> run
const { document, window } = dom.window;
const PAGES = ['market','trade-plan','signals','advisory','account','diagnostics','activity','data-sources'];
function visiblePages() {
return [...document.querySelectorAll('.grid>[data-page]')]
.filter(el => el.style.display !== 'none')
.map(el => el.dataset.page);
}
function uniqueVisiblePageNames() {
return [...new Set(visiblePages())];
}
let allOk = true;
function check(label, cond) {
console.log((cond ? 'OK ' : 'FAIL'), label);
if (!cond) allOk = false;
}
// 1. Initial load with no hash -> defaults to market, exactly one page visible.
check('initial load defaults to #market', window.location.hash === '#market');
check('initial load: exactly one page visible', uniqueVisiblePageNames().length === 1 && uniqueVisiblePageNames()[0] === 'market');
// 2. Every route via navigateToPage (simulates clicking nav).
for (const p of PAGES) {
window.navigateToPage(p);
const vis = uniqueVisiblePageNames();
check(`navigate -> #${p}: hash set`, window.location.hash === '#' + p);
check(`navigate -> #${p}: exactly one page visible (${vis.join(',')})`, vis.length === 1 && vis[0] === p);
const activeLink = document.querySelector('.quicknav a.active');
check(`navigate -> #${p}: nav active state matches`, activeLink && activeLink.dataset.page === p);
}
// 3. Legacy hash redirect.
window.location.hash = '#activityCard';
window.dispatchEvent(new window.Event('hashchange'));
check('legacy #activityCard redirects hash to #activity', window.location.hash === '#activity');
check('legacy #activityCard shows activity page', uniqueVisiblePageNames()[0] === 'activity');
// 4. Back/Forward via popstate: go to signals, then advisory, then back.
window.navigateToPage('signals');
window.navigateToPage('advisory');
const histLenBefore = window.history.length;
// Simulate browser back: pop the hash back to '#signals' and fire popstate.
window.location.hash = '#signals';
window.dispatchEvent(new window.PopStateEvent('popstate', { state: { page: 'signals' } }));
check('back navigation shows signals page', uniqueVisiblePageNames()[0] === 'signals');
window.location.hash = '#advisory';
window.dispatchEvent(new window.PopStateEvent('popstate', { state: { page: 'advisory' } }));
check('forward navigation shows advisory page', uniqueVisiblePageNames()[0] === 'advisory');
// 5. Refresh persistence: reload a fresh DOM with hash already set to #account.
const dom2 = new JSDOM(html, { url: 'https://example.test/futures#account', runScripts: 'dangerously', resources: 'usable', pretendToBeVisual: true });
dom2.window.fetch = () => Promise.reject(new Error('network disabled in test'));
await new Promise(r => setTimeout(r, 300));
const doc2 = dom2.window.document;
const vis2 = [...new Set([...doc2.querySelectorAll('.grid>[data-page]')].filter(el => el.style.display !== 'none').map(el => el.dataset.page))];
check('reload with #account in URL shows account page', vis2.length === 1 && vis2[0] === 'account');
console.log(allOk ? 'ALL_DOM_ROUTER_CHECKS_OK' : 'DOM_ROUTER_FAILURES');
process.exit(allOk ? 0 : 1);
}
run().catch(e => { console.error('ERROR', e); process.exit(1); });