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 { renderToStaticMarkup } from 'react-dom/server'; import ts from 'typescript'; const require = createRequire(import.meta.url); function load(file, mocks = {}) { const code = ts.transpileModule( fs.readFileSync(new URL(file, import.meta.url), 'utf8'), { compilerOptions: { module: ts.ModuleKind.CommonJS, target: ts.ScriptTarget.ES2022, jsx: ts.JsxEmit.ReactJSX, }, }, ).outputText; const module = { exports: {} }; compileFunction(code, ['require', 'module', 'exports'])( (key) => mocks[key] ?? require(key), module, module.exports, ); return module.exports; } const urls = load('../../resources/js/lib/company-comparison.ts'); function nodes(tree) { if (!tree || typeof tree !== 'object') return []; if (Array.isArray(tree)) return tree.flatMap(nodes); return [tree, ...nodes(tree.props?.children)]; } const questions = { purpose: { label: 'Finalidade', options: { new: 'Nova', representation: 'Representação', unknown: 'Por definir', }, }, participants: { label: 'Participantes', options: { one: 'Um', several: 'Vários', unknown: 'Por definir' }, }, regulated: { label: 'Regras específicas', options: { unknown: 'Por conferir' }, }, preferred: { label: 'Preferência', options: { quotas: 'Quotas', unknown: 'Por definir' }, }, }; const props = { definition: { version: 'v1', questions }, answers: { purpose: 'new', participants: 'one', regulated: 'unknown', preferred: 'quotas', }, result: { engine_version: 'v1', questions, active: Object.keys(questions), pending: ['regulated'], route: 'Compare alternativas.', preparation: ['Preparar contrato.'], scope: 'Edição indicada.', source: { title: 'Código Comercial', edition: 'Edição consultada', issued_on: '2022-05-25', consulted_on: '2026-11-02', url: 'https://tsrm.gov.mz/source.pdf', }, forms: [ { code: 'quotas', title: 'Sociedade ', description: 'Capital em quotas', articles: 'Artigo 281', source_href: 'https://tsrm.gov.mz/source.pdf#page=42', selected: true, constraints: ['SYNTHETIC incompatibility'], notes: ['Conferir modalidade.'], }, ], }, case: null, saved: null, history: [], historyNext: null, historical: false, workingCopy: false, canWrite: false, }; function harness() { let cursor = 0; const values = [], refs = [], visits = [], requests = []; let rejectSave = false; const hooks = { useState(initial) { const i = cursor++; if (!(i in values)) values[i] = typeof initial === 'function' ? initial() : initial; return [ values[i], (v) => { values[i] = v; }, ]; }, useRef(initial) { const i = cursor++; if (!(i in values)) { values[i] = { current: initial }; refs.push(values[i]); } return values[i]; }, }; const module = load( '../../resources/js/pages/investment/company-comparison.tsx', { react: hooks, '@inertiajs/react': { Link: 'a', router: { visit: (...args) => visits.push(args) }, }, './shared': { Frame: 'main', card: '', input: '', button: '' }, '@/lib/company-comparison': urls, '@/lib/operation-key': { createOperationKey: () => 'SYNTHETIC-operation', }, '@/lib/profile-json': { profileJson: async (...args) => { requests.push(args); if (rejectSave) throw new Error('SYNTHETIC conflict; keep edits'); return { saved: true }; }, }, }, ); return { render(extra = {}) { cursor = 0; const outer = module.default({ ...props, ...extra }); return outer.type(outer.props); }, refs, visits, requests, fail() { rejectSave = true; }, }; } const find = (tree, name) => nodes(tree).find((node) => node.props?.name === `answers[${name}]`); const button = (tree, text) => nodes(tree).find( (node) => node.type === 'button' && node.props.children === text, ); await test('public comparison is a real GET form, safely renders sources and constraints, and asks no identity data', () => { const h = harness(), tree = h.render(), html = renderToStaticMarkup(tree); const form = nodes(tree).find((node) => node.type === 'form'); assert.equal(form.props.method, 'get'); assert.equal(form.props.action, '/formas-juridicas'); assert.match(html, /Sociedade <SYNTHETIC>/); assert.match(html, /Incompatibilidade a resolver/); assert.match(html, /Preferência para aprofundar/); assert.match(html, /2022-05-25/); assert.doesNotMatch(html, /name="(email|nuit|name|registration)"/); }); await test('changing to representation hides inapplicable questions while keeping their answers for later recovery', () => { const h = harness(); find(h.render(), 'purpose').props.onChange({ target: { value: 'representation' }, }); const tree = h.render(); assert.equal(find(tree, 'participants').type, 'input'); assert.equal(find(tree, 'participants').props.type, 'hidden'); assert.equal(find(tree, 'participants').props.value, 'one'); assert.equal(find(tree, 'preferred').props.value, 'quotas'); find(tree, 'purpose').props.onChange({ target: { value: 'new' } }); assert.equal(find(h.render(), 'participants').props.value, 'one'); }); await test('dossier choice uses current browser values and transports only answer codes through normal authentication', () => { const h = harness(), tree = h.render(); h.refs[0].current = {}; const old = globalThis.FormData; globalThis.FormData = class { get(key) { return key === 'answers[participants]' ? 'several' : null; } }; try { button(tree, 'Escolher dossier para guardar').props.onClick(); } finally { globalThis.FormData = old; } const target = new URL(h.visits[0][0], 'https://portal.test'); assert.equal(target.pathname, '/investimentos'); assert.equal( target.searchParams.get('company_comparison[participants]'), 'several', ); assert.equal( target.searchParams.get('company_comparison[preferred]'), 'quotas', ); }); await test('a failed save keeps actual field values and context, and never navigates as though the comparison was saved', async () => { const h = harness(); h.fail(); const extra = { case: { id: 'dossier-a', title: 'SYNTHETIC dossier', version: 7 }, canWrite: true, }; let tree = h.render(extra); h.refs[0].current = {}; find(tree, 'participants').props.onChange({ target: { value: 'several' } }); tree = h.render(extra); const old = globalThis.FormData; globalThis.FormData = class { get(key) { return key === 'answers[participants]' ? 'several' : null; } }; try { await button(tree, 'Guardar no dossier').props.onClick(); } finally { globalThis.FormData = old; } assert.equal(h.requests[0][0], '/investimentos/dossier-a/forma-juridica'); assert.equal(h.requests[0][1].version, 7); assert.equal(h.requests[0][1].answers.participants, 'several'); assert.equal(h.visits.length, 0); const after = h.render(extra); assert.equal(find(after, 'participants').props.value, 'several'); assert.match(renderToStaticMarkup(after), /SYNTHETIC conflict; keep edits/); assert.equal( button(after, 'Reabrir com estas respostas').props.type, 'submit', ); assert.equal( nodes(after).find((node) => node.type === 'form').props.method, 'get', ); }); await test('historical and superseded results retain their own question labels and source and require explicit current preparation', () => { const h = harness(); const historicalResult = { ...props.result, engine_version: 'older', questions: { ...questions, participants: { ...questions.participants, label: 'SYNTHETIC historical wording', }, }, }; const tree = h.render({ case: { id: 'dossier-a', title: 'Dossier', version: 3 }, canWrite: true, historical: true, saved: { revision: 1, at: '2026-11-01', result: historicalResult }, result: historicalResult, }); const html = renderToStaticMarkup(tree); assert.match(html, /SYNTHETIC historical wording/); assert.equal(nodes(tree).filter((node) => node.type === 'form').length, 0); const link = nodes(tree).find( (node) => node.props?.children === 'Preparar nova comparação com estas respostas', ); assert.equal( new URL(link.props.href, 'https://portal.test').searchParams.get( 'answers[participants]', ), 'one', ); assert.equal( new URL(link.props.href, 'https://portal.test').searchParams.has( 'revision', ), false, ); }); await test('successful save recovers the saved dossier edition and history links retain the exact dossier scope', async () => { const h = harness(), extra = { case: { id: 'dossier-a', title: 'Dossier', version: 5 }, canWrite: true, history: [ { id: 'event-a', revision: 2, at: '2026-11-02', engine_version: 'v1', }, ], historyNext: 100, }; const tree = h.render(extra); h.refs[0].current = {}; const old = globalThis.FormData; globalThis.FormData = class { get() { return null; } }; try { await button(tree, 'Guardar no dossier').props.onClick(); } finally { globalThis.FormData = old; } assert.equal(h.visits[0][0], '/investimentos/dossier-a/forma-juridica'); assert.equal(h.visits[0][1].preserveState, false); const html = renderToStaticMarkup(tree); assert.match(html, /dossier-a\/forma-juridica\?revision=event-a/); assert.match(html, /dossier-a\/forma-juridica\?history_before=100/); });