import test from 'node:test'; import assert from 'node:assert/strict'; import fs from 'node:fs'; import { createRequire } from 'node:module'; import { compileFunction } from 'node:vm'; import ts from 'typescript'; import React from 'react'; import { renderToStaticMarkup } from 'react-dom/server'; const require = createRequire(import.meta.url); const sharedText = fs.readFileSync( 'resources/js/pages/partnerships/shared.tsx', 'utf8', ); const labelSource = sharedText.match( /export const labels: Record = (\{[\s\S]*?\n\});/, )[1]; const labels = compileFunction(`return (${labelSource});`, [])(); function load(file) { const source = ts.transpileModule(fs.readFileSync(file, 'utf8'), { compilerOptions: { module: ts.ModuleKind.CommonJS, jsx: ts.JsxEmit.ReactJSX, }, }).outputText; const module = { exports: {} }; compileFunction(source, ['require', 'module', 'exports'])( (id) => { if (id === './shared') return { Frame: ({ title, children }) => React.createElement( 'main', {}, React.createElement('h1', {}, title), children, ), labels, }; if (id === '@inertiajs/react') return { Link: ({ children, ...props }) => React.createElement('a', props, children), router: {}, }; return require(id); }, module, module.exports, ); return module.exports.default; } const Page = load('resources/js/pages/partnerships/interest-history.tsx'); const Dashboard = load('resources/js/pages/partnerships/dashboard.tsx'); const snapshot = () => ({ availability: 'available', version: 1, status: 'submitted', scope_known: true, organization_id: null, fields: { proposal: 'SYNTHETIC proposal', capacity: null }, consent_known: true, consent: false, assessment_recorded: true, assessment: [], references: [], complete: true, }); const entry = () => ({ version: 2, restricted: false, action: 'assess', actor_name: 'SYNTHETIC owner', occurred_at: '2026-11-03', reason: 'SYNTHETIC reason', previous: snapshot(), after: snapshot(), partnership_version: 4, matching: { score_min: 0, score_max: 0, eligibility: 'unknown', algorithm_version: 'synthetic-v1', weights_hash: 'synthetic-hash', unknown_weight: 0, criteria: [ { code: 'capacity', label: 'SYNTHETIC frozen label', weight: 20, mandatory: true, state: 'unknown', evidence: 'SYNTHETIC frozen evidence', explanation: 'SYNTHETIC frozen explanation', }, ], }, }); const props = () => ({ candidacy_id: 10, entries: [entry()], next_url: null, first_url: '/parcerias/candidaturas/10/historico', older_page: false, partnership_href: null, dashboard_href: '/parcerias/painel', }); const render = (p = props()) => renderToStaticMarkup(React.createElement(Page, p)); test('history renders frozen decision parameters, including valid zero scores', () => { const html = render(); for (const value of [ '0–0%', 'Peso: 20', 'Obrigatório', 'SYNTHETIC frozen label', 'SYNTHETIC frozen evidence', 'SYNTHETIC frozen explanation', 'synthetic-v1', 'synthetic-hash', ]) assert.ok(html.includes(value), value); assert.ok(!html.includes('Por determinar')); }); test('missing frozen scores and obligations remain unknown instead of false or zero', () => { const p = props(); p.entries[0].matching.score_min = null; p.entries[0].matching.criteria[0].mandatory = null; p.entries[0].matching.criteria[0].weight = null; const html = render(p); assert.ok(html.includes('Por determinar')); assert.ok(html.includes('Obrigatoriedade não registada')); assert.ok(!html.includes('0–0%')); assert.ok(!html.includes('Não obrigatório')); }); test('old incomplete events are explicit and never supplied from a current proposal', () => { const p = props(); p.entries[0].after = { availability: 'available', complete: false, fields: [], assessment: [], assessment_recorded: false, scope_known: false, }; p.entries[0].matching = null; p.entries[0].action = null; const html = render(p); for (const value of [ 'Registo parcial', 'Não consta do registo', 'Âmbito não registado', 'Não foi recalculado', 'Alteração registada', ]) assert.ok(html.includes(value), value); }); test('missing and intentionally empty fields or consent are distinguished', () => { const html = render(); assert.match(html, /Capacidade disponível<\/dt>]*>Não indicado/); assert.match( html, /Contribuição proposta<\/dt>]*>Não consta do registo/, ); assert.ok(html.includes('Não autorizada')); assert.ok(html.includes('Sem critérios avaliados nesta versão')); }); test('restricted scope and missing legacy scope have different explanations', () => { const p = props(); p.entries = [ { ...entry(), restricted: true, previous: { availability: 'restricted' }, after: { availability: 'scope_unknown' }, matching: null, actor_name: null, reason: null, }, ]; const html = render(p); assert.ok(html.includes('Conteúdo reservado')); assert.ok(html.includes('acesso actual')); assert.ok(html.includes('âmbito desta versão antiga')); assert.ok(!html.includes('SYNTHETIC owner')); assert.ok(!html.includes('SYNTHETIC proposal')); assert.ok(!html.includes('Correspondência guardada')); }); test('read-only page has no write or restore controls and uses only supplied cursor navigation', () => { const p = props(); p.next_url = '/parcerias/candidaturas/10/historico?before=opaque%2Btoken'; p.older_page = true; const html = render(p); assert.ok(html.includes('before=opaque%2Btoken')); assert.ok(html.includes('Versões mais recentes')); assert.ok(!/<(?:form|button|input|select|textarea)\b/.test(html)); assert.ok(!html.includes('Consultar parceria')); p.partnership_href = '/parcerias/1'; assert.ok(render(p).includes('href="/parcerias/1"')); }); test('saved user text is escaped and current catalogue names are identified', () => { const p = props(); p.entries[0].after.fields.proposal = ''; p.entries[0].after.assessment = [ { code: 'capacity', label: 'SYNTHETIC current catalogue', state: 'unknown', evidence: 'SYNTHETIC recorded evidence', }, ]; const html = render(p); assert.ok(!html.includes('