Files
Investidor-V2/tests/frontend/navigation-context-integration.test.mjs
T
2026-11-15 18:56:39 +02:00

170 lines
6.2 KiB
JavaScript

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;
}
});