170 lines
6.2 KiB
JavaScript
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;
|
|
}
|
|
});
|