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

116 lines
10 KiB
JavaScript

import { createProjectDossierReport } from '../../resources/js/lib/project-dossier-report.ts';
import assert from 'node:assert/strict';
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';
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);
});
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');
});
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);
});
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'));
});
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']);
});
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,{});
});
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,'');
});
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,'');
});
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,{});
});
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/);
});
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);
});