Files
SGF/scripts/sgf-assets-ui.mjs
T
2026-11-11 15:04:01 +02:00

12 lines
7.0 KiB
JavaScript

import fs from'node:fs';import assert from'node:assert/strict';import{pathToFileURL}from'node:url';import{transformWithOxc}from'vite';const root=JSON.parse(fs.readFileSync('C:/laragon/data/sgf-tempo/run/modular-regression-current.json')).root+'/private/receipt-composition-cc50a276c10c',checks=[],ok=(v,n)=>{assert(v,n);checks.push(n);};let slots=[],cursor=0,effects=[],tree,calls=[],rootComponent,props;const same=(a,b)=>a&&b&&a.length===b.length&&a.every((v,i)=>v===b[i]);const R={createElement:(type,props,...children)=>({type,props:props??{},children}),Fragment:Symbol('fragment'),Suspense:Symbol('suspense'),lazy:()=>Symbol('lazy'),useRef(initial){const i=cursor++;slots[i]??={value:{current:initial}};return slots[i].value;},useState(initial){const i=cursor++;slots[i]??={value:initial};return[slots[i].value,v=>{slots[i].value=typeof v==='function'?v(slots[i].value):v;}];},useMemo(fn,deps){const i=cursor++;if(!same(slots[i]?.deps,deps))slots[i]={value:fn(),deps};return slots[i].value;},useEffect(fn,deps){const i=cursor++;if(!same(slots[i]?.deps,deps)){slots[i]?.cleanup?.();slots[i]={deps};effects.push(()=>slots[i].cleanup=fn());}}};globalThis.__hrHooks=R;const stub='const r=globalThis.__hrHooks;export default r;export const useState=r.useState,useMemo=r.useMemo,useEffect=r.useEffect,useRef=r.useRef;',reactUrl='data:text/javascript;base64,'+Buffer.from(stub).toString('base64'),compile=async(file,imports)=>{let s=fs.readFileSync('resources/js/'+file,'utf8').replace(/from\s*['"]react['"]/, 'from '+JSON.stringify(reactUrl));for(const f of imports)s=s.replace(new RegExp('from\\s*[\'"]\\./'+f.replaceAll('.','\\.')+'[\'"]'),'from '+JSON.stringify(pathToFileURL(process.cwd()+'/resources/js/'+f).href));const c=await transformWithOxc(s,file,{jsx:{runtime:'classic'}});return import('data:text/javascript;base64,'+Buffer.from(c.code).toString('base64'));};
const{default:Workspace}=await compile('FixedAssetsWorkspace.jsx',[]);const{navigationGroups}=await compile('WorkspaceNavigation.jsx',['billing-menu.js','workshop-menu.js','stock-menu.js','accounting-menu.js']);const{moduleGroups}=await compile('ModuleNavigation.jsx',[]);
const row={id:7,kind:'asset',record_key:'00000000-0000-4000-8000-000000000007',version:2,state:'approved',actor_id:16,created_at:'QA',reason:'Revisão artificial',data:{status:'active',input:{code:'QA-UI-ASSET',description:'Fixture UI',origin_reference:'QA-UI-OPEN',cost:'1200.00',residual:'0.00',available_on:'2026-10-01',location:'QA-A',custodian:'QA-A',evidence:'Evidência artificial de UI'}},effective:null};row.effective={...row};let fail=true,posted=[],previewCalls=[];
const api=async(path,method,body,unused,key)=>{calls.push({path,method,body,key});if(method==='POST'&&path.endsWith('/preview')){previewCalls.push({body,key});return{preview:'opaque',impact:{before:{version:0},after:{version:1,state:'prepared',proposal:{input:body.data}}}};}if(method==='POST'){posted.push({path,body,key});if(fail){const e=Error('Resultado incerto503');e.status=503;throw e;}return{state:'prepared',version:1};}if(path.includes('/receipts/'))return{result:{state:'prepared',version:1}};if(path.includes('/ledger?'))return{balance:{cost_minor:120000,accumulated_minor:10000,carrying_minor:110000,disposed:false},records:{data:[],last_page:1},corrections:[]};const q=new URL('http://qa'+path).searchParams;return{kind:q.get('kind'),records:{data:q.get('kind')==='asset'?[row]:[],per_page:Number(q.get('per_page')),total:26,last_page:2}};};
const render=()=>{cursor=0;tree=rootComponent(props);const jobs=effects;effects=[];jobs.forEach(f=>f());return tree;},tick=async()=>{await new Promise(r=>setTimeout(r,0));render();},descend=n=>Array.isArray(n)?n.flatMap(descend):n&&typeof n==='object'?[n,...descend(n.children)]:[],nodes=(n=tree)=>descend(n),text=n=>Array.isArray(n)?n.map(text).join(''):n&&typeof n==='object'?text(n.children):String(n??''),find=(tag,label)=>nodes().find(n=>n.type===tag&&text(n).includes(label));
rootComponent=Workspace;props={api,context:{token:'qa',unit:{id:2}},can:()=>true,busy:false,perform:async(fn)=>{try{await fn();}catch{}}};render();await tick();ok(calls.length===1&&calls[0].path.includes('kind=asset'),'bounded initial asset list only');ok(!calls.some(c=>c.path.includes('/ledger')),'no implicit first asset selection');find('button','Seguinte').props.onClick();render();await tick();ok(calls.at(-1).path.includes('page=2'),'page changes server query');find('button','QA-UI-ASSET').props.onClick();render();await tick();ok(calls.at(-1).path.includes('asset_key='+row.record_key),'ledger only for explicit asset');ok(text(tree).includes('Diário do activo seleccionado'),'asset and GL integrated detail');find('button','Novo registo').props.onClick();render();ok(!find('h2','Versão seleccionada'),'new record clears old selection');const field=(label,value)=>{find('label',label).children.find(n=>['input','textarea'].includes(n?.type)).props.onChange({target:{value}});render();};field('Código QA','QA-NEW-UI');field('Descrição','Equipamento artificial UI');field('Referência da abertura','QA-NEW-OPEN');field('Custo MZN','1200.00');field('Residual MZN','0.00');field('Entrada em uso','2026-10-01');field('Localização interna','QA-SALA-A');field('Custódia interna','QA-CUSTODIA-A');field('Evidência','Evidência artificial UI');field('Fundamento da decisão','Fundamento artificial UI');render();await nodes().find(n=>n.type==='form').props.onSubmit({preventDefault(){}});render();ok(previewCalls.length===1&&previewCalls[0].body.data.cost==='1200.00'&&previewCalls[0].body.version===0,'exact documentary amount and explicit first version');ok(Boolean(find('h2','Impacto antes da confirmação')),'impact before commit');ok(find('button','Planos mensais').props.disabled,'preview blocks navigation');await find('button','Confirmar só este impacto').props.onClick();render();ok(find('button','Planos mensais').props.disabled&&Boolean(find('button','Recuperar comprovativo')),'uncertain failure retains same conference');await find('button','Recuperar comprovativo').props.onClick();render();await tick();ok(posted.length===1&&calls.some(c=>c.path.endsWith('/receipts/'+previewCalls[0].key)),'receipt recovery does not duplicate POST');find('button','Planos mensais').props.onClick();render();await tick();const picker=nodes().find(n=>typeof n.type==='function'&&n.type.name==='ReferencePicker');ok(picker&&picker.props.value==='','dependent asset explicitly unselected');const groups=navigationGroups(r=>r.startsWith('fixed_assets.'),2,{fixedAssets:true});ok(moduleGroups(groups,'accounting').some(g=>g.items.some(i=>i.id==='fixed_assets')),'accounting dropdown with exact asset right');ok(moduleGroups(groups,'finance').length===0&&moduleGroups(groups,'human_resources').length===0,'asset right adds no other module');const hidden=navigationGroups(()=>false,2,{fixedAssets:true});ok(!hidden.flatMap(g=>g.items).some(i=>i.id==='fixed_assets'),'no asset menu without permission');
const file=root+'/assets-ui-20261111.json';fs.writeFileSync(file,JSON.stringify({passed:true,checks,api_mocked:true,browser_visual_review:false},null,2));console.log(JSON.stringify({passed:true,checks:checks.length,proof:file}));