81 lines
8.5 KiB
JavaScript
81 lines
8.5 KiB
JavaScript
import assert from 'node:assert/strict';
|
|
import test from 'node:test';
|
|
import fs from 'node:fs';
|
|
import {createRequire} from 'node:module';
|
|
import React from 'react';
|
|
import {renderToStaticMarkup} from 'react-dom/server';
|
|
import ts from 'typescript';
|
|
import * as flow from '../../resources/js/lib/opportunity-fill-flow.ts';
|
|
import { fiscalPreparationGuide } from '../../resources/js/lib/fiscal-preparation-guide.ts';
|
|
const require=createRequire(import.meta.url);
|
|
function load(path,mocks={},exportName='default',extra=''){
|
|
const source=fs.readFileSync(new URL(path,import.meta.url),'utf8');
|
|
const output=ts.transpileModule(source,{compilerOptions:{module:ts.ModuleKind.CommonJS,target:ts.ScriptTarget.ES2022,jsx:ts.JsxEmit.ReactJSX}}).outputText;
|
|
const module={exports:{}};new Function('require','module','exports',output+extra)(name=>mocks[name]??(name.startsWith('@/')?{default:()=>null}:require(name)),module,module.exports);return module.exports[exportName];
|
|
}
|
|
function stateHooks(){const memory=[];let cursor=0;return{hooks:{...React,useState(initial){const i=cursor++;if(!(i in memory))memory[i]=typeof initial==='function'?initial():initial;return[memory[i],next=>memory[i]=typeof next==='function'?next(memory[i]):next];},useRef:()=>({current:null}),useEffect:()=>{}},reset:()=>cursor=0};}
|
|
const flat=node=>!node||typeof node!=='object'?[]:[node,...React.Children.toArray(node.props?.children).flatMap(flat)];
|
|
test('free navigation keeps every field mounted and reports resource work in the current group',()=>{
|
|
const state=stateHooks();const Component=load('../../resources/js/components/opportunity-fill-flow.tsx',{'react':state.hooks,'@/lib/opportunity-fill-flow':flow});
|
|
const groups=flow.opportunityFillGroups(['official_title','locations','documents']);const saved={official_title:'Deliberate user title',locations:['saved-site']};
|
|
const opened=[];let tree;
|
|
const render=()=>{state.reset();tree=Component({groups,errors:{},renderField:field=>React.createElement('input',{name:field,value:JSON.stringify(saved[field]??''),readOnly:true}),onOpenResources:group=>opened.push(group)});};
|
|
const priorWindow=globalThis.window,priorFrame=globalThis.requestAnimationFrame;
|
|
globalThis.window={history:{state:{existing:'inertia-state'},replaceState(state,_title,url){assert.deepEqual(state,{existing:'inertia-state'});this.url=url;}}};globalThis.requestAnimationFrame=callback=>callback();
|
|
try{
|
|
render();assert.equal(flat(tree).filter(node=>node.type==='input').length,3);
|
|
flat(tree).find(node=>node.type==='a'&&node.props.href==='#fill-territory').props.onClick({preventDefault(){}});render();
|
|
const sections=flat(tree).filter(node=>node.type==='section');
|
|
assert.equal(sections.find(node=>node.props.id==='fill-territory').props.hidden,false);
|
|
assert.equal(sections.find(node=>node.props.id==='fill-idea').props.hidden,true);
|
|
assert.equal(flat(tree).filter(node=>node.type==='input').length,3);
|
|
flat(tree).find(node=>node.type==='button').props.onClick();assert.deepEqual(opened,['territory']);
|
|
assert.equal(saved.official_title,'Deliberate user title');assert.deepEqual(saved.locations,['saved-site']);
|
|
assert.equal(globalThis.window.history.url,'#fill-territory');
|
|
}finally{globalThis.window=priorWindow;globalThis.requestAnimationFrame=priorFrame;}
|
|
});
|
|
test('profile request renders readable labels without dumping every available document into the form',()=>{
|
|
const Picker=load('../../resources/js/components/profile-proof-picker.tsx');
|
|
const Page=load('../../resources/js/pages/profiles/request.tsx',{
|
|
'@/lib/operation-key':{createOperationKey:()=> 'synthetic-key'},
|
|
'@inertiajs/react':{Head:()=>null,Link:({href,children})=>React.createElement('a',{href},children),router:{}},
|
|
'@/components/profile-navigation':{default:()=>null},'@/lib/profile-json':{},
|
|
'@/pages/management/shared':{button:'button',control:'control'},
|
|
'@/components/opportunity-search-filters':{modalityLabels:{investment_project:'Projecto de investimento',land_rights:'Direitos fundiários'}},
|
|
'@/components/profile-proof-picker':{default:Picker},
|
|
});
|
|
const html=renderToStaticMarkup(React.createElement(Page,{requests:[],types:['investment_project','land_rights'],organizations:[],documents:Array.from({length:80},(_,i)=>({id:`doc-${i}`,file_name:`UNSELECTED-DOCUMENT-${i}.txt`}))}));
|
|
assert.match(html,/Em nome próprio/);assert.match(html,/Entidade pública/);assert.match(html,/Projecto de investimento/);assert.match(html,/Direitos fundiários/);
|
|
assert.doesNotMatch(html,/UNSELECTED-DOCUMENT/);assert.match(html,/Pesquisar nos meus ficheiros/);
|
|
const visible=html.replace(/<[^>]+>/g,'');assert.doesNotMatch(visible,/investment_project|land_rights|public_entity/);
|
|
});
|
|
test('proof selection is explicit and retained when the filename search changes',()=>{
|
|
const state=stateHooks();const Component=load('../../resources/js/components/profile-proof-picker.tsx',{'react':state.hooks});
|
|
const documents=[{id:'identity',file_name:'Documento próprio'},{id:'law',file_name:'Lei.pdf'}];const values=[];let tree;
|
|
const render=()=>{state.reset();tree=Component({documents,value:values,onChange:ids=>{values.splice(0,values.length,...ids);}});};
|
|
render();assert.equal(flat(tree).filter(node=>node.type==='input'&&node.props.type==='checkbox').length,0);
|
|
flat(tree).find(node=>node.type==='input').props.onChange({target:{value:'próprio'}});render();
|
|
flat(tree).find(node=>node.type==='input'&&node.props.type==='checkbox').props.onChange();render();assert.deepEqual(values,['identity']);
|
|
flat(tree).find(node=>node.type==='input'&&node.props.type==='search').props.onChange({target:{value:'Lei'}});render();
|
|
assert.deepEqual(values,['identity']);assert.equal(flat(tree).filter(node=>node.type==='input'&&node.props.type==='checkbox')[0].props.checked,false);
|
|
});
|
|
test('document entry leads to existing fillable preparation and keeps sources optional',()=>{
|
|
const context='10000000-0000-4000-8000-000000000001';
|
|
const inertia={Link:({href,children})=>React.createElement('a',{href},children),usePage:()=>({url:`/documentos?context=${context}`})};
|
|
const Hub=load('../../resources/js/components/journey-document-resources.tsx',{'@inertiajs/react':inertia,'@/lib/fiscal-preparation-guide':{fiscalPreparationGuide}},'JourneyDocumentResources');
|
|
const hub=renderToStaticMarkup(React.createElement(Hub,{}));
|
|
assert.match(hub,new RegExp(`/investimentos/${context}/contexto/editar#preparation-questions`));assert.match(hub,/href="\/terra-duat"/);
|
|
assert.match(hub,/Preparação digital e exemplar oficial/);assert.doesNotMatch(hub,/<details[^>]*\bopen\b/);
|
|
const Editor=load('../../resources/js/components/private-investment-preparation.tsx',{'@inertiajs/react':inertia,'@/pages/investment/shared':{card:'card',input:'input'}},'PreparationEditor');
|
|
const html=renderToStaticMarkup(React.createElement(Editor,{data:{questions:[{key:'investment_preparation',label:'Preparar pedido?',options:{yes:'Sim',no:'Não'},source:'SYNTHETIC QA'},{key:'declared_amount',label:'Valor do investimento',type:'number',source:'SYNTHETIC QA'}],requirements:[],enabled:true,mode:'authorization',missing_fields:['declared_amount']},fields:{investment_preparation:'yes'},changes:{},documents:[],links:{},onChange(){},onLink(){},disabled:false}));
|
|
assert.match(html,/<input/);assert.match(html,/Valor do investimento/);assert.match(html,/id="preparation-questions"/);
|
|
});
|
|
test('investment stages expose readable next actions while internal codes and sources remain consultable',()=>{
|
|
const useForm=data=>({data,errors:{},processing:false,setData(){},transform(){return this;},post(){}});
|
|
const Stage=load('../../resources/js/pages/investor-path/show.tsx',{'@inertiajs/react':{useForm,Link:({href,children})=>React.createElement('a',{href},children)},'@/lib/investor-path':{pathStates:{not_started:'Por iniciar'}}},'Stage','\nmodule.exports.Stage=Stage;');
|
|
const step={code:'S01',title:'Sistematizar a ideia',state:'not_started',detail:{scope:'promoter_preparation'},preparation_allowed:true,action_gaps:{},source_paragraph:22,applicability:'applicable'};
|
|
const html=renderToStaticMarkup(React.createElement(Stage,{step,path:{case:{id:'synthetic',version:1},next:{code:'S01'},canWrite:true,canReview:false,steps:[step],documents:[]}}));
|
|
assert.match(html,/<details[^>]*id="S01"[^>]*open/);assert.match(html,/<summary[^>]*>Sistematizar a ideia/);
|
|
assert.doesNotMatch(html,/<summary[^>]*>S01/);assert.match(html,/Fonte e referência desta etapa/);
|
|
});
|