import assert from 'node:assert/strict'; import test from 'node:test'; import { readSimulationApiJson, simulationApiErrorMessage, simulationPollingFailureMessage, simulationCatalogChoices, } from '../../resources/js/lib/simulation-api.ts'; test('malformed and non-JSON API bodies do not leak parser exceptions', async () => { assert.equal( await readSimulationApiJson( new Response('gateway error', { headers: { 'Content-Type': 'text/html' }, status: 502, }), ), null, ); assert.equal( await readSimulationApiJson( new Response('{"truncated":', { headers: { 'Content-Type': 'application/json' }, status: 500, }), ), null, ); }); test('API error messages prefer validated field details and reject malformed shapes', () => { assert.equal( simulationApiErrorMessage({ message: 'Validation failed', errors: { base: ['Base is required'], rate: ['Rate is invalid'] }, }), 'Base is required Rate is invalid', ); assert.equal( simulationApiErrorMessage({ message: 'Try again' }), 'Try again', ); assert.equal( simulationApiErrorMessage({ errors: { base: 'invalid' } }), undefined, ); assert.equal(simulationApiErrorMessage('error'), undefined); }); test('polling failures explain that an accepted calculation may still be pending', () => { assert.equal( simulationPollingFailureMessage(null), 'O cenário foi recebido, mas não foi possível confirmar o estado do cálculo. Consulte o histórico antes de tentar novamente.', ); assert.equal( simulationPollingFailureMessage({ message: 'Acesso expirado' }), 'Acesso expirado', ); }); test('catalog parser distinguishes a valid empty list and filters malformed options', () => { assert.deepEqual(simulationCatalogChoices({ data: [] }), []); assert.deepEqual( simulationCatalogChoices({ data: [ { id: 'country-1', label: 'Moçambique' }, { value: 2, name: 'Província de Maputo' }, { id: 'incomplete', label: '' }, null, ], }), [ { id: 'country-1', label: 'Moçambique' }, { id: '2', label: 'Província de Maputo' }, ], ); assert.throws(() => simulationCatalogChoices('gateway error')); });