import test from 'node:test'; import assert from 'node:assert/strict'; import fs from 'node:fs'; import { compileFunction } from 'node:vm'; import { createRequire } from 'node:module'; import ts from 'typescript'; import { readNavigationFocus, rememberNavigationFocus, } from '../../resources/js/lib/navigation-focus.ts'; const require = createRequire(import.meta.url); const A = '15111500-0000-4000-8000-000000000001'; const B = '15111500-0000-4000-8000-000000000002'; test('dossier provider retains tab focus across navigation/reload, honours explicit URLs and uses the current server version on deliberate change', async () => { const oldStorage = globalThis.sessionStorage, oldWindow = globalThis.window; const storage = new Map(), calls = [], visits = []; globalThis.sessionStorage = { getItem: (k) => storage.get(k), setItem: (k, v) => storage.set(k, v), removeItem: (k) => storage.delete(k), }; globalThis.window = { location: { hash: '' }, addEventListener() {}, removeEventListener() {}, }; let pageUrl = '/simulador', serverFocus = { case_id: B, step_code: null, version: 8 }; rememberNavigationFocus(7, { case_id: A, step_code: 'S08', version: 1 }); const code = ts.transpileModule( fs.readFileSync( 'resources/js/components/dossier-navigation-context.tsx', 'utf8', ), { compilerOptions: { module: ts.ModuleKind.CommonJS, target: ts.ScriptTarget.ES2022, jsx: ts.JsxEmit.ReactJSX, }, }, ).outputText; function mount() { const state = [], dependencies = [], pending = []; let cursor = 0, effectCursor = 0; const hooks = { createContext: () => ({ Provider: 'provider' }), useContext: () => ({}), useState(initial) { const i = cursor++; if (!(i in state)) state[i] = typeof initial === 'function' ? initial() : initial; return [ state[i], (n) => (state[i] = typeof n === 'function' ? n(state[i]) : n), ]; }, useEffect(callback, deps) { const i = effectCursor++; if ( !dependencies[i] || deps.some((v, n) => v !== dependencies[i][n]) ) { dependencies[i] = deps; pending.push(callback); } }, }; const module = { exports: {} }; compileFunction(code, ['require', 'module', 'exports'])( (id) => { if (id === 'react') return hooks; if (id === '@inertiajs/react') return { usePage: () => ({ url: pageUrl, props: { auth: { user: { id: 7 } }, investorPathEnabled: true, }, }), router: { visit: (url) => visits.push(url) }, Link: 'a', }; if (id === '@/lib/navigation-focus') return { readNavigationFocus, rememberNavigationFocus }; if (id === '@/lib/investor-context') return { contextApi: async (url, data, method) => { calls.push({ url, data, method }); if (url === '/investimentos') return { contexts: [{ id: A }, { id: B }] }; if (url === '/investimentos/contexto-atual') { if (method === 'PUT') { assert.equal( data.version, serverFocus.version, ); serverFocus = { ...data, version: serverFocus.version + 1, }; } return { installed: true, focus: serverFocus }; } return { case: { id: url.split('/').pop() } }; }, }; return require(id); }, module, module.exports, ); const render = () => { cursor = effectCursor = 0; const tree = module.exports.NavigationContextProvider({ children: null, }); while (pending.length) pending.shift()(); return tree.props.value; }; return async () => { render(); await new Promise(setImmediate); return render(); }; } try { let render = mount(), view = await render(); assert.equal(view.active, A); assert.equal(view.view.case.id, A); assert.equal( calls.some((c) => c.method === 'PUT'), false, ); render = mount(); view = await render(); assert.equal( view.active, A, 'reload must not adopt the other tab server preference', ); pageUrl = '/simulador?context=' + B; view = await render(); assert.equal(view.active, B, 'explicit authorised dossier wins'); assert.equal(readNavigationFocus(7, [A, B]).case_id, B); serverFocus = { case_id: A, step_code: null, version: 15 }; view.choose(A, 'S02'); await new Promise(setImmediate); assert.equal( calls.filter((c) => c.method === 'PUT').at(-1).data.version, 15, ); assert.equal(visits.at(-1), '/investimentos/' + A + '#S02'); } finally { globalThis.sessionStorage = oldStorage; globalThis.window = oldWindow; } });