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); function load(file, mocks = {}, suffix = '') { const code = ts.transpileModule( fs.readFileSync(new URL(file, import.meta.url), 'utf8') + suffix, { compilerOptions: { module: ts.ModuleKind.CommonJS, jsx: ts.JsxEmit.ReactJSX, target: ts.ScriptTarget.ES2022, }, }, ).outputText; const module = { exports: {} }; compileFunction(code, ['require', 'module', 'exports'])( (name) => mocks[name] ?? require(name), module, module.exports, ); return module.exports; } const Link = ({ children, href, className }) => React.createElement('a', { href, className }, children); const Empty = () => null; const mocks = { '@inertiajs/react': { Link, Head: Empty }, '@/pages/management/shared': { states: { received: 'Recebido existente' } }, '@/pages/crm/types': { taskStates: { open: 'Aberta existente' } }, }; const Queue = load( '../../resources/js/components/dashboard-work-queue.tsx', mocks, ).default; const Dashboard = load('../../resources/js/pages/dashboard.tsx', { ...mocks, '@/components/dashboard-work-queue': { default: Queue }, '@/components/profile-navigation': { default: Empty }, '@/components/content-management-entry': { default: Empty }, '@/routes': { dashboard: () => '/dashboard' }, }).default; const item = (patch = {}) => ({ id: 'synthetic-one', title: 'SYNTHETIC next action', reference: 'SYNTHETIC-REF', status: 'received', due_at: '2026-11-03T10:00:00.000000Z', overdue: true, href: '/management/interests/1', ...patch, }); const group = (patch = {}) => ({ total: 1, overdue: 1, items: [item()], page: 1, last_page: 1, previous: null, next: null, ...patch, }); const queue = (groups) => ({ as_of: '2026-11-03T11:00:00.000000Z', desk_states: { accepted: 'Aceite internamente — edição configurada' }, groups, }); const render = (Component, props) => renderToStaticMarkup(React.createElement(Component, props)); function nodes(tree) { return Array.isArray(tree) ? tree.flatMap(nodes) : tree && typeof tree === 'object' ? [tree, ...nodes(tree.props?.children)] : []; } test('investor dashboard retains its investment context without an irrelevant operational panel', () => { const html = render(Dashboard, { summary: null, workQueue: null, investorPath: { contexts: [{ id: 'own-case', title: 'SYNTHETIC own investment' }], current: { id: 'own-case', next: { code: 'S01', title: 'SYNTHETIC next investment step' }, pending: 2, documents: 3, results: 1, tasks: 4, }, }, }); assert.match(html, /SYNTHETIC own investment/); assert.match(html, /href="\/investimentos\/own-case#S01"/); assert.doesNotMatch( html, /O meu acompanhamento|Manifestações atribuídas a mim|Gestão de Oportunidades/, ); }); test('the three collections keep separate totals and labels from their existing domains', () => { const html = render(Queue, { queue: queue({ interests: group({ total: 7, overdue: 2 }), desk: group({ total: 8, overdue: 3, items: [ item({ status: 'accepted', href: '/balcao-virtual/pedidos/one', }), ], }), crm_tasks: group({ total: 9, overdue: 4, items: [ item({ status: 'open', href: '/management/crm/leads/one#crm-task-one', }), ], }), }), }); for (const label of [ 'Manifestações atribuídas a mim', 'Pedidos do Balcão atribuídos a mim', 'Tarefas do CRM atribuídas a mim', 'Recebido existente', 'Aceite internamente — edição configurada', 'Aberta existente', ]) assert.ok(html.includes(label)); for (const n of [7, 8, 9]) assert.ok(html.includes(`${n} por acompanhar`)); assert.doesNotMatch(html, /24 por acompanhar|Aprovado|Licença concedida/); assert.ok(html.includes('href="/management/crm/leads/one#crm-task-one"')); }); test('missing groups stay absent and an accessible empty collection shows its real zero', () => { const html = render(Queue, { queue: queue({ desk: group({ total: 0, overdue: 0, items: [] }) }), }); assert.match(html, /0 por acompanhar/); assert.match(html, /Não tem registos activos atribuídos/); assert.doesNotMatch( html, /Manifestações atribuídas|Tarefas do CRM atribuídas|Página/, ); assert.equal(render(Queue, { queue: undefined }), ''); }); test('deadlines use Maputo time with explicit overdue and unknown-deadline information', () => { const html = render(Queue, { queue: queue({ interests: group({ items: [ item(), item({ id: 'no-date', due_at: null, overdue: false }), ], }), }), }); assert.ok(html.includes('dateTime="2026-11-03T10:00:00.000000Z"')); assert.match(html, /12:00.*?Maputo/); assert.match(html, /Prazo ultrapassado/); assert.match(html, /Sem prazo definido/); }); test('each collection paginates through supplied destinations without losing scroll position', () => { const tree = Queue({ queue: queue({ interests: group({ total: 13, page: 2, last_page: 3, previous: '/dashboard?interests_page=1&desk_page=2', next: '/dashboard?interests_page=3&desk_page=2', }), }), }); const pagination = nodes(tree).find((node) => node.type === 'nav'); assert.equal( pagination.props['aria-label'], 'Páginas: Manifestações atribuídas a mim', ); const links = nodes(pagination).filter((node) => node.type === Link); assert.deepEqual( links.map((link) => link.props.href), [ '/dashboard?interests_page=1&desk_page=2', '/dashboard?interests_page=3&desk_page=2', ], ); assert.ok(links.every((link) => link.props.preserveScroll === true)); assert.match( render(Queue, { queue: queue({ interests: group({ total: 13, page: 2, last_page: 3 }), }), }), /Página 2 de 3/, ); }); test('work queue and existing management indicators coexist, escaping record text', () => { const html = render(Dashboard, { summary: { requestsByStatus: { received: 4 }, publishedOpportunities: 3, draftOpportunities: 2, activeSectors: 1, recentRequests: [], canCreateOpportunity: false, }, workQueue: queue({ interests: group({ items: [item({ title: '' })], }), }), }); assert.match(html, /O meu acompanhamento/); assert.match(html, /Indicadores de utilização e cobertura/); assert.match(html, /Oportunidades publicadas/); assert.ok(html.includes('<img src=x onerror=alert(1)>')); assert.doesNotMatch(html, / { const TaskRow = load( '../../resources/js/pages/crm/lead.tsx', { '@inertiajs/react': { Link, useForm() {} }, '@/lib/crm-record-edit': { useCrmRecordEdit: () => ({ form: { processing: false }, values: { status: 'open' }, error: () => undefined, blocked: false, }), }, '@/components/crm-edit-comparison': { default: Empty }, '@/components/crm-task-creation': { default: Empty }, '../management/shared': { Management: Empty, Field: Empty, button: '', control: '', }, './types': { leadStates: {}, taskStates: { open: 'Aberta' } }, }, '\nexport { TaskRow };', ).TaskRow; const form = TaskRow({ task: { id: 'one', title: 'SYNTHETIC task', status: 'open', due_at: null, assignee_user_id: 1, version_no: 1, }, leadId: 'lead-one', }); const href = '/management/crm/leads/lead-one#crm-task-one'; assert.equal(form.props.id, href.split('#')[1]); });