Files
Investidor-V2/tests/frontend/context-inheritance.test.mjs
T

423 lines
14 KiB
JavaScript

import { createProjectDossierReport } from '../../resources/js/lib/project-dossier-report.ts';
import assert from 'node:assert/strict';
void test('legacy draft without a compatible source keeps its shape and identity', () => {
const legacy = {
activity_id: 'legacy-activity',
infrastructure_needs: ['energia'],
};
assert.equal(inheritSimulatorFields(legacy), legacy);
assert.equal(
Object.hasOwn(
inheritSimulatorFields(legacy),
'compatible_fields_snapshot',
),
false,
);
});
import test from 'node:test';
import {
inheritCompatibleFields,
inheritSimulatorFields,
reusedInvestmentValue,
} from '../../resources/js/lib/context-inheritance.ts';
import { serializeBusinessPlanSnapshot } from '../../resources/js/lib/business-financial-plan.ts';
import { monthlySalesFromDraft } from '../../resources/js/lib/monthly-iva.ts';
import {
restoreSimulationDraft,
partitionSimulationDraft,
} from '../../resources/js/lib/simulation-form.ts';
void test('known investment questions become editable summaries after save/recovery, while missing and deliberate edits remain questions', () => {
const scope = 'dossier:A:simulator';
const source = {
project_title: 'Florestas — Beira',
project_summary: 'Preparar investimento florestal',
province_id: 'p1',
province_id_label: 'Sofala',
sector_id: '3',
sector_id_label: 'Agronegócio',
};
const reused = inheritCompatibleFields(scope, {}, source, null);
const draft = {
...reused.patch,
context_reuse: reused.metadata,
purpose: 'simulate_only',
journey_type: 'investor',
};
const saved = partitionSimulationDraft(draft);
const recovered = restoreSimulationDraft(
saved.personal_snapshot,
saved.economic_snapshot,
);
assert.equal(
reusedInvestmentValue(scope, 'project_title', recovered),
source.project_title,
);
assert.equal(
reusedInvestmentValue(scope, 'province_id', recovered),
'Sofala',
);
assert.equal(
reusedInvestmentValue(scope, 'sector_id', recovered),
'Agronegócio',
);
assert.equal(reusedInvestmentValue(scope, 'district_id', recovered), null);
assert.equal(
reusedInvestmentValue(
'dossier:B:simulator',
'project_title',
recovered,
),
null,
);
assert.equal(
reusedInvestmentValue(scope, 'project_title', {
...recovered,
project_title: 'Edição deliberada',
}),
null,
);
assert.equal(
reusedInvestmentValue(scope, 'project_title', {
...recovered,
project_title: '',
}),
null,
);
assert.equal(
reusedInvestmentValue(scope, 'province_id', {
...recovered,
province_id_label: '',
}),
null,
);
assert.equal(
reusedInvestmentValue(scope, 'currency', {
...recovered,
currency: 'MZN',
}),
null,
);
assert.equal(
reusedInvestmentValue(scope, 'project_title', {
...recovered,
context_reuse: 'invalid',
}),
null,
);
});
void test('local geography and sector keep their labels when the dossier proposes different identifiers', () => {
const scope = 'dossier:A:simulator';
const source = {
province_id: 'p1',
province_id_label: 'Sofala',
district_id: 'd1',
district_id_label: 'Dondo',
sector_id: '3',
sector_id_label: 'Agronegócio',
};
const local = {
province_id: 'p2',
province_id_label: 'Gaza',
district_id: 'd2',
district_id_label: 'Outro distrito',
sector_id: '4',
sector_id_label: 'Turismo',
};
const reconciliation = inheritCompatibleFields(scope, local, source, null);
assert.deepEqual(reconciliation.patch, {});
assert.ok(reconciliation.conflicts.includes('province_id'));
const first = inheritCompatibleFields(scope, {}, source, null);
const changed = inheritCompatibleFields(
scope,
{ ...first.patch, context_reuse: first.metadata },
{
...source,
province_id: 'p3',
province_id_label: 'Manica',
district_id: '',
district_id_label: '',
},
first.metadata,
);
assert.equal(changed.patch.province_id, 'p3');
assert.equal(changed.patch.province_id_label, 'Manica');
assert.equal(changed.patch.district_id, '');
assert.equal(changed.patch.district_id_label, '');
const stale = inheritCompatibleFields(
scope,
{ province_id_label: 'Nome antigo' },
source,
null,
);
assert.equal(stale.patch.province_id, 'p1');
assert.equal(stale.patch.province_id_label, 'Sofala');
});
void test('investment entry selects the existing simulation route without replacing an earlier deliberate purpose', () => {
const scope = 'dossier:A:simulator';
const source = {
journey_type: 'investor',
journey_type_label: 'Avaliar o meu investimento',
purpose: 'simulate_only',
purpose_label: 'Apenas simular',
};
const first = inheritCompatibleFields(scope, {}, source, null);
const values = { ...first.patch, context_reuse: first.metadata };
assert.equal(
reusedInvestmentValue(scope, 'journey_type', values),
'Avaliar o meu investimento',
);
assert.equal(
reusedInvestmentValue(scope, 'purpose', values),
'Apenas simular',
);
const old = inheritCompatibleFields(
scope,
{ journey_type: 'small_business', purpose: 'seek_partner' },
source,
null,
);
assert.deepEqual(old.patch, {});
assert.equal(
reusedInvestmentValue(scope, 'purpose', {
purpose: 'seek_partner',
context_reuse: old.metadata,
}),
null,
);
});
void test('inherited source updates follow through recovery while local edits and deliberate clears survive', () => {
const first = inheritCompatibleFields(
'dossier:A:simulator',
{},
{ currency: 'MZN', project_title: 'A' },
null,
);
const saved = { ...first.patch, context_reuse: first.metadata };
const changed = inheritCompatibleFields(
'dossier:A:simulator',
saved,
{ currency: 'USD', project_title: 'A2' },
saved.context_reuse,
);
assert.deepEqual(changed.patch, { currency: 'USD', project_title: 'A2' });
const edited = inheritCompatibleFields(
'dossier:A:simulator',
{ ...saved, currency: 'EUR', project_title: '' },
{ currency: 'USD', project_title: 'A2' },
saved.context_reuse,
);
assert.deepEqual(edited.patch, {});
assert.deepEqual(edited.conflicts, ['currency', 'project_title']);
const recovered = JSON.parse(
JSON.stringify({ ...saved, currency: 'EUR', project_title: '' }),
);
assert.deepEqual(
inheritCompatibleFields(
'dossier:A:simulator',
recovered,
{ currency: 'USD', project_title: 'A2' },
recovered.context_reuse,
).patch,
{},
);
assert.ok(!first.metadata.includes('MZN'));
assert.ok(!first.metadata.includes('project_title":"A'));
});
void test('a different dossier cannot take ownership of existing values using another dossier metadata', () => {
const first = inheritCompatibleFields(
'dossier:A:simulator',
{},
{ currency: 'MZN' },
null,
);
const second = inheritCompatibleFields(
'dossier:B:simulator',
first.patch,
{ currency: 'USD' },
first.metadata,
);
assert.deepEqual(second.patch, {});
assert.deepEqual(second.conflicts, ['currency']);
});
void test('a local geographic override protects the entire hierarchy', () => {
const first = inheritCompatibleFields(
'A',
{},
{ province_id: 'p1', district_id: 'd1' },
null,
);
const update = inheritCompatibleFields(
'A',
{ ...first.patch, province_id: 'p-local' },
{ province_id: 'p2', district_id: 'd2' },
first.metadata,
);
assert.deepEqual(update.patch, {});
});
void test('compatible currency and date reuse survives backend partition and new session recovery without invented tax scope', () => {
const initial = inheritSimulatorFields({
currency: 'USD',
expected_start_date: '2026-03-01',
purpose: 'simulate_only',
});
assert.equal(initial.fiscal_currency, 'USD');
assert.equal(initial.published_iva_currency, 'USD');
assert.equal(initial.opportunity_currency, 'USD');
assert.equal(JSON.parse(initial.monthly_iva_settings).start, '2026-03');
assert.equal(JSON.parse(initial.monthly_iva_settings).declared, false);
assert.equal(initial.published_iva_date, undefined);
assert.equal(
inheritSimulatorFields({
expected_start_date: '2026-01-01',
monthly_iva_settings: '[invalid stored input',
}).monthly_iva_settings,
'[invalid stored input',
);
const saved = partitionSimulationDraft(initial, true);
const recovered = restoreSimulationDraft(
saved.economic_snapshot,
saved.personal_snapshot,
);
assert.equal(recovered.published_iva_currency, 'USD');
assert.strictEqual(inheritSimulatorFields(recovered), recovered);
const changed = inheritSimulatorFields({ ...recovered, currency: 'EUR' });
assert.equal(changed.fiscal_currency, 'EUR');
const override = inheritSimulatorFields({
...changed,
fiscal_currency: 'MZN',
published_iva_currency: '',
});
assert.equal(override.fiscal_currency, 'MZN');
assert.equal(override.published_iva_currency, '');
});
void test('land consumer reuses geography inside an empty parcel and preserves all other parcel data', () => {
const first = inheritCompatibleFields(
'land',
{
parcels: [
{ area: '12', province_id: '' },
{ area: '20', province_id: 'other' },
],
},
{ parcels: [{ province_id: 'P', district_id: 'D' }] },
null,
);
assert.equal(first.patch.parcels[0].area, '12');
assert.equal(first.patch.parcels[0].district_id, 'D');
assert.equal(first.patch.parcels[1].province_id, 'other');
const changed = inheritCompatibleFields(
'land',
{
parcels: [
{ ...first.patch.parcels[0], area: '13' },
first.patch.parcels[1],
],
},
{ parcels: [{ province_id: 'P2' }] },
first.metadata,
);
assert.equal(changed.patch.parcels[0].area, '13');
assert.equal(changed.patch.parcels[0].district_id, '');
});
void test('clearing an inherited zone reference clears only the inherited value, preserving a deliberate override', () => {
const first = inheritCompatibleFields(
'A',
{},
{ special_zone_id: 'zone' },
null,
);
assert.equal(
inheritCompatibleFields(
'A',
first.patch,
{ special_zone_id: '' },
first.metadata,
).patch.special_zone_id,
'',
);
assert.deepEqual(
inheritCompatibleFields(
'A',
{ special_zone_id: 'local' },
{ special_zone_id: '' },
first.metadata,
).patch,
{},
);
});
void test('conflicting saved sales currency is explained instead of relabelled or converted', () => {
const fields = [
'openingCash',
'monthlyCollections',
'monthlyVariableCostPayments',
'monthlyInventoryPurchases',
'monthlyOperatingExpenses',
'monthlyOperatingPayments',
'monthlyPayrollExpense',
'monthlyPayrollPayments',
'assetInvestment',
'inventory',
'receivables',
'payables',
'equity',
'shareholderLoans',
'bankLoanProceeds',
'grants',
'assetDepreciation',
'monthlyInterestExpense',
'monthlyInterestPayment',
'monthlyPrincipalRepayment',
];
const plan = {
...Object.fromEntries(fields.map((key) => [key, '0'])),
currency: 'MZN',
periods: 4,
depreciationLifeMonths: 60,
products: [
{
label: 'QA',
monthlyUnits: '1',
unitPrice: '100',
unitVariableCost: '0',
},
],
};
assert.throws(
() =>
monthlySalesFromDraft({
currency: 'USD',
business_plan_snapshot: serializeBusinessPlanSnapshot(plan),
}),
/projecção de vendas está em MZN.*projecto está em USD/,
);
});
void test('report preserves consulted zone version and makes unsupported benefit explicit without inventing a fiscal result', () => {
const context = {
version: 1,
context_revision: 3,
zone: { title: 'Referência QA', version: 7, href: '/zonas/qa' },
fields: { currency: 'USD' },
};
const draft = {
project_title: 'QA',
currency: 'USD',
context_applicability_snapshot: JSON.stringify(context),
};
const saved = JSON.stringify(draft);
const report = createProjectDossierReport(draft, {
selectedSections: new Set(['sources']),
});
assert.match(JSON.stringify(report), /Referência QA, versão 7/);
assert.match(
JSON.stringify(report),
/Benefício fiscal da zona indeterminado/,
);
assert.equal(JSON.stringify(draft), saved);
});