Files
Investidor-V2/tests/frontend/fiscal-qa-preview.test.mjs
T

196 lines
7.2 KiB
JavaScript

import assert from 'node:assert/strict';
import test from 'node:test';
import { fiscalQaRows } from '../../resources/js/lib/fiscal-qa-preview.ts';
import {
exportCompletedArithmeticCsv,
readArithmeticSnapshot,
} from '../../resources/js/lib/simulation-form.ts';
import { createProjectDossierReport } from '../../resources/js/lib/project-dossier-report.ts';
function fixture() {
const snapshot = {
contract_version: 1,
scenario_kind: 'fiscal_rule_qa_preview',
base: '0.03',
currency: 'MZN',
indicative_total: '0.0048',
legal_interpretation: false,
formula_version: 'investmoz.tax.v1',
context: {
reference_date: '2026-10-21',
currency: 'MZN',
currency_fraction_digits: 2,
scenario_id: '61000100-0000-4000-8000-000000000099',
scenario_version: 1,
engine_version: 'fiscal-draft-preview-v1',
ruleset_version: 'IVA-GERAL-BASE-LIQUIDA:1',
},
result: {
status: 'calculated',
value: '0.0048',
unit: 'MZN',
explanation:
'Cálculo exacto QA; enquadramento declarado; não é saldo a pagar.',
missing_inputs: [],
source_ids: ['source-fixture'],
},
intermediate: { result: '48/10000' },
fiscal_provenance: {
rule: {
rule_code: 'IVA-GERAL-BASE-LIQUIDA',
rule_version: 1,
valid_from: '2023-01-01',
valid_until: null,
source_sha256: 'a'.repeat(64),
source: { diploma: 'Lei 22/2022', article: 'Artigo 17(1)' },
},
},
};
return {
id: '61000100-0000-4000-8000-000000000088',
status: 'completed',
version_no: 2,
result_snapshot: snapshot,
reports: [
{
id: '61000100-0000-4000-8000-000000000077',
version_no: 1,
status: 'ready',
report_snapshot: structuredClone(snapshot),
report_sha256: 'b'.repeat(64),
},
],
};
}
void test('screen rows preserve sub-cent IVA as a string and distinguish calculation from payment', () => {
const simulation = fixture();
const before = JSON.stringify(simulation);
const rows = fiscalQaRows(simulation.result_snapshot);
assert.equal(
rows.find(([label]) => label.startsWith('IVA calculado'))[1],
'0.0048',
);
assert.match(
rows.find(([label]) => label === 'Arredondamento')[1],
/Não aplicado/,
);
assert.match(
rows.find(([label]) => label === 'Enquadramento')[1],
/não validado juridicamente/,
);
assert.equal(JSON.stringify(simulation), before);
});
void test('CSV preserves the exact amount and refuses a mismatched immutable report', () => {
const simulation = fixture();
const csv = exportCompletedArithmeticCsv(
simulation,
'2026-10-21T09:00:00Z',
);
assert.match(csv, /0\.0048/);
assert.doesNotMatch(csv, /Resultado fiscal final,Indeterminado/);
simulation.reports[0].report_snapshot.result.value = '0.00';
assert.throws(
() => exportCompletedArithmeticCsv(simulation),
/relatório preservado/,
);
});
void test('dossier report uses the same exact snapshot and preserves genuine indetermination', () => {
const simulation = fixture();
function report() {
return createProjectDossierReport(
{ project_title: 'QA fiscal', currency: 'MZN' },
{
selectedSections: new Set(['finance']),
currentCalculation: {
status: 'completed',
version: 2,
snapshot: simulation.result_snapshot,
},
},
);
}
const rows = report().sections.find(
(section) => section.id === 'finance',
).rows;
assert.equal(
rows.find((row) => row.field.startsWith('IVA calculado')).value,
'0.0048',
);
assert.equal(
rows.find((row) => row.field === 'Fonte da taxa').value,
'Lei 22/2022 — Artigo 17(1)',
);
simulation.result_snapshot.result.status = 'indeterminate';
simulation.result_snapshot.result.value = null;
simulation.result_snapshot.indicative_total = null;
simulation.result_snapshot.result.missing_inputs = ['eligible_parameter'];
assert.equal(
report()
.sections.find((section) => section.id === 'finance')
.rows.find((row) => row.field.startsWith('IVA calculado')).value,
'Indeterminado',
);
});
void test('published consumer routes the frozen snapshot through screen CSV and dossier without QA labels', () => {
const simulation = fixture();
const snapshot = simulation.result_snapshot;
snapshot.scenario_kind = 'fiscal_rule_published';
snapshot.context.engine_version = 'fiscal-published-v1';
snapshot.presentation = {
value: snapshot.result.value,
rounding_applied: false,
};
snapshot.result.explanation =
'IVA pela versão publicada; enquadramento declarado.';
snapshot.fiscal_provenance.rule.status = 'published';
snapshot.fiscal_provenance.scope_status = 'user_declared';
snapshot.fiscal_provenance.mode = 'published_version';
simulation.reports[0].report_snapshot = structuredClone(snapshot);
const before = JSON.stringify(simulation);
const rows = fiscalQaRows(snapshot);
assert.equal(readArithmeticSnapshot(snapshot).integrity, 'versioned');
assert.match(rows[0][1], /publicada/);
assert.doesNotMatch(JSON.stringify(rows), /rascunho|não publicada|QA/);
const csv = exportCompletedArithmeticCsv(
simulation,
'2026-10-21T12:00:00Z',
);
for (const [label, value] of rows) {
assert.ok(csv.includes(label));
assert.ok(csv.includes(value.replaceAll('"', '""')));
}
const report = createProjectDossierReport(
{ project_title: 'Published IVA QA', currency: 'MZN' },
{
selectedSections: new Set(['finance']),
currentCalculation: { status: 'completed', version: 2, snapshot },
},
);
const finance = report.sections.find((section) => section.id === 'finance');
for (const [field, value] of rows)
assert.ok(
finance.rows.some(
(row) => row.field === field && row.value === value,
),
);
assert.doesNotMatch(JSON.stringify(finance), /rascunho|proveniência QA/);
assert.equal(JSON.stringify(simulation), before);
});
void test('published consumer indeterminate snapshot is valid and a mismatched presentation is refused', () => {
const snapshot = fixture().result_snapshot;
snapshot.scenario_kind = 'fiscal_rule_published';
snapshot.result.status = 'indeterminate';
snapshot.result.value = null;
snapshot.result.missing_inputs = ['operation_scope'];
snapshot.indicative_total = null;
snapshot.presentation = { value: null, rounding_applied: false };
assert.equal(readArithmeticSnapshot(snapshot).integrity, 'versioned');
snapshot.presentation.value = '0';
assert.equal(readArithmeticSnapshot(snapshot).integrity, 'invalid');
});