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 { createElement } from 'react'; import { renderToStaticMarkup } from 'react-dom/server'; import ts from 'typescript'; const require = createRequire(import.meta.url); function load(file, mocks = {}) { const output = 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(output, ['require', 'module', 'exports'])( (name) => mocks[name] ?? require(name), module, module.exports, ); return module.exports; } const locations = load('../../resources/js/lib/business-locations.ts'); const summaryModule = load( '../../resources/js/components/business-point-summary.tsx', { '@/lib/business-locations': locations }, ); const Summary = summaryModule.default; const sourceModule = load( '../../resources/js/components/similar-businesses.tsx', { '@inertiajs/react': { Link: 'a' }, '@/lib/portal-api': {} }, ); const paths = [ { province_id: 'qa-province', district_id: 'qa-one', admin_post_id: '', locality_id: '', }, { province_id: 'qa-province', district_id: 'qa-two', admin_post_id: '', locality_id: '', }, ]; const payload = { title: 'QA private preparation', wizard_version: '2', wizard_step: '5', geography_scope: 'multiple', locations_json: JSON.stringify(paths), location_unknown: 'no', disclosure_precision: 'exact', location_point_enabled: 'yes', location_latitude: '-26.0001', location_longitude: '32.0001', location_point_source_mode: 'listing', source_reference: '', source_date: '2026-10-02', location_point_source_reference: 'Other private source', location_point_source_date: '', location_point_share_source: 'no', }; function nodes(tree) { if (!tree || typeof tree !== 'object') return []; if (Array.isArray(tree)) return tree.flatMap(nodes); return [tree, ...nodes(tree.props?.children)]; } function harness(initial = payload) { let cursor = 0; const state = [], requests = []; const hooks = { useState(initial) { const index = cursor++; if (!(index in state)) state[index] = typeof initial === 'function' ? initial() : initial; return [ state[index], (value) => { state[index] = typeof value === 'function' ? value(state[index]) : value; }, ]; }, useRef(initial) { const index = cursor++; if (!(index in state)) state[index] = { current: initial }; return state[index]; }, useEffect() {}, useCallback(fn) { return fn; }, }; const active = { geography_scope: ['specific', 'multiple'], disclosure_precision: ['exact'], location_unknown: ['no'], location_point_enabled: ['yes'], }; const schema = { geography_scope: { step: 5, pt: 'Geographic scope', en: 'Scope', type: 'select', max: 30, options: { multiple: 'Multiple', specific: 'Specific', national: 'National', digital: 'Digital', }, }, location_point_territory: { step: 5, pt: 'Primary site', en: 'Primary site', type: 'point_territory', max: 150, when: { ...active, geography_scope: ['multiple'] }, }, location_latitude: { step: 5, pt: 'Latitude', en: 'Latitude', type: 'decimal', max: 16, when: active, }, location_longitude: { step: 5, pt: 'Longitude', en: 'Longitude', type: 'decimal', max: 16, when: active, }, location_point_source_mode: { step: 5, pt: 'Coordinate source', en: 'Coordinate source', type: 'select', max: 20, options: { listing: 'Existing source', custom: 'Different source' }, when: active, }, location_point_source_reference: { step: 5, pt: 'Point source', en: 'Point source', type: 'textarea', max: 2000, when: { ...active, location_point_source_mode: ['custom'] }, }, }; const record = { id: 'qa-listing', code: 'MNE-QA', modality: 'company_sale', classification: 'restricted', version_no: 1, payload: initial, territory_paths: [ ['QA province', 'QA one'], ['QA province', 'QA two'], ], }; const Wizard = load( '../../resources/js/pages/investment/business-wizard.tsx', { react: hooks, '@inertiajs/react': { router: { visit() {}, reload() {} } }, '@/components/country-select': { default: () => null }, '@/components/business-point-summary': summaryModule, './shared': { Frame: 'div', Field: ({ label, children }) => createElement('label', null, label, children), input: 'input', button: 'button', card: 'card', api: async (url, body) => { requests.push({ url, body }); return { ...record, payload: body.payload, version_no: 2 }; }, }, './business-types': { businessModalities: { company_sale: 'Sale' }, }, './business-objects': { default: () => null }, '../../lib/business-locations': locations, }, ).default; return { render() { cursor = 0; return Wizard({ countries: [], record, formSchema: schema, modalityFormType: 'company_sale', modalities: ['company_sale'], objects: [], objectKinds: [], sectors: [], }); }, requests, }; } await test('the existing wizard requires an explicit primary path and keeps the selected path distinct from the first site', async () => { const h = harness(); let tree = h.render(); const chooser = nodes(tree).find( (node) => node.type === 'select' && nodes(node).some( (child) => child.type === 'option' && child.props.value === locations.businessPointTerritoryKey(paths[1]), ), ); assert.equal(chooser.props.value, ''); chooser.props.onChange({ target: { value: locations.businessPointTerritoryKey(paths[1]) }, }); tree = h.render(); const html = renderToStaticMarkup(tree); assert.match(html, /QA two/); assert.match(html, /Latitude \*/); assert.match(html, /não publica o ponto/); assert.match(html, /mantida no processo reservado/); const save = nodes(tree).find( (node) => node.type === 'button' && node.props.children === 'Guardar e sair', ); await save.props.onClick(); assert.equal( h.requests[0].url, '/api/v1/existing-business/listings/qa-listing', ); assert.equal( h.requests[0].body.payload.location_point_territory, locations.businessPointTerritoryKey(paths[1]), ); assert.equal(h.requests[0].body.version_no, 1); assert.equal(h.requests[0].body.payload.location_latitude, '-26.0001'); }); await test('switching source reuses existing fields and switching to national hides the supplement while preserving the private draft', async () => { const h = harness(); let tree = h.render(); assert.equal( nodes(tree).some((node) => node.type === 'textarea'), false, ); const source = nodes(tree).find( (node) => node.type === 'select' && node.props.value === 'listing', ); source.props.onChange({ target: { value: 'custom' } }); tree = h.render(); assert.equal( nodes(tree).find((node) => node.type === 'textarea').props.value, 'Other private source', ); const scope = nodes(tree).find( (node) => node.type === 'select' && node.props.value === 'multiple', ); scope.props.onChange({ target: { value: 'national' } }); tree = h.render(); assert.doesNotMatch( renderToStaticMarkup(tree), /Ponto em preparação|Other private source|Latitude WGS84/, ); assert.equal( nodes(tree).some((node) => node.type === 'textarea'), false, ); await nodes(tree) .find( (node) => node.type === 'button' && node.props.children === 'Guardar e sair', ) .props.onClick(); assert.equal(h.requests[0].body.payload.location_latitude, '-26.0001'); assert.equal( h.requests[0].body.payload.location_point_source_reference, 'Other private source', ); assert.equal( h.requests[0].body.payload.location_point_source_mode, 'custom', ); assert.equal(h.requests[0].body.payload.geography_scope, 'national'); }); await test('stale point path stays visible for reconciliation instead of selecting another site', () => { const h = harness({ ...payload, location_point_territory: 'qa-removed-site', }); const html = renderToStaticMarkup(h.render()); assert.match(html, /Selecção guardada fora das localizações actuais/); assert.match(html, /value="qa-removed-site" selected/); }); await test('an incomplete earlier location does not change the index or name of a later selectable site', () => { const h = harness({ ...payload, locations_json: JSON.stringify([ locations.emptyBusinessLocation(), paths[1], ]), }); const option = nodes(h.render()).find( (node) => node.type === 'option' && node.props.value === locations.businessPointTerritoryKey(paths[1]), ); const html = renderToStaticMarkup(option); assert.match(html, /Localização 2/); assert.match(html, /QA two/); assert.doesNotMatch(html, /QA one/); assert.equal( locations.businessPointTerritoryLabel( { ...payload, location_point_territory: locations.businessPointTerritoryKey( paths[1], ), }, [['QA one'], ['QA two']], ), 'QA two', ); }); await test('summary distinguishes registered, prepared and published data, escapes the reused source and reports an unavailable supplement', () => { const registered = { id: 'qa-existing', is_public: false, precision_level: 'exact', has_geometry: true, latitude: -27, longitude: 33, }; let html = renderToStaticMarkup( Summary({ payload, registered, available: false }), ); assert.match(html, /Latitude -27; longitude/); assert.match(html, /Ponto em preparação/); assert.match(html, /<QA source>/); assert.match(html, /ainda não está instalado/); assert.match(html, /substitui o primário cadastrado/); html = renderToStaticMarkup( Summary({ payload, registered, published: true }), ); assert.match(html, /Ponto declarado na publicação/); assert.match(html, /não reescreve o histórico/); assert.equal( Summary({ payload: { ...payload, location_unknown: 'yes' } }), null, ); html = renderToStaticMarkup( Summary({ payload: { ...payload, location_point_enabled: 'no' }, registered, }), ); assert.match( html, /cadastro existente é conservado|cadastro\s+existente é conservado/, ); assert.doesNotMatch(html, /-26.0001|<QA source>/); }); await test('public source dates remain calendar dates in a western timezone and unknown dates are not replaced by the registration time', () => { const previous = process.env.TZ; try { process.env.TZ = 'Pacific/Honolulu'; const html = renderToStaticMarkup( sourceModule.BusinessLocationSource({ record: { location_source_reference: '', location_source_date: '2026-10-02', location_recorded_at: '2026-11-02T10:00:00Z', }, showRecorded: true, }), ); assert.match(html, /<Public source>/); assert.ok( html.includes( new Date('2026-10-02T00:00:00Z').toLocaleDateString('pt-MZ', { timeZone: 'UTC', }), ), ); const unknown = renderToStaticMarkup( sourceModule.BusinessLocationSource({ record: { location_recorded_at: '2026-11-02T10:00:00Z' }, }), ); assert.match(unknown, /Data da fonte: desconhecida/); assert.doesNotMatch(unknown, /2026/); } finally { if (previous === undefined) delete process.env.TZ; else process.env.TZ = previous; } });