Files
SGF/scripts/stock-period-ui.mjs
2026-11-04 09:37:20 +02:00

27 lines
4.8 KiB
JavaScript

import fs from 'node:fs';import path from 'node:path';import assert from 'node:assert/strict';import React from 'react';import {renderToStaticMarkup} from 'react-dom/server';import {createServer} from 'vite';
import {requestStockPeriod} from '../resources/js/stock-period-request.js';
const tag=process.argv[2];assert(/^[a-f0-9]{12}$/.test(tag??''));const run=JSON.parse(fs.readFileSync('C:/laragon/data/sgf-tempo/run/modular-regression-current.json')),root=path.join(run.root,'private/receipt-composition-'+tag),out=path.join(root,'stock-period-ui.json');assert(!fs.existsSync(out));const checks=[],ok=(v,name)=>{assert(v,name);checks.push(name);};
const settle=()=>new Promise(resolve=>setTimeout(resolve,0));let value='old',message='old',busy=false,uri;
const setters={data:v=>value=v,error:v=>message=v,loading:v=>busy=v};const query={view:'period',from:'2026-11-01',to:'2026-11-03',search:'%_',warehouse_id:9,per_page:25,page:2,snapshot:'opaque+token'};
requestStockPeriod({...setters,query,api:async url=>{uri=url;return {id:'current'};}});ok(value===null&&message===''&&busy,'starting another period immediately clears stale rows errors and enters loading');await settle();await settle();
const params=new URL('http://qa.local'+uri).searchParams;ok(uri.startsWith('/api/stock-read?')&&params.get('view')==='period'&&params.get('from')===query.from&&params.get('to')===query.to&&params.get('search')==='%_'&&params.get('snapshot')==='opaque+token'&&params.get('warehouse_id')==='9','report request preserves dates literal search warehouse page and reference');
ok(value.id==='current'&&!busy&&!message,'successful active read supplies the current result without a business command');
let first,second;const cancel=requestStockPeriod({...setters,query,api:()=>new Promise(resolve=>first=resolve)});await settle();cancel();
requestStockPeriod({...setters,query:{...query,to:'2026-11-04',snapshot:undefined},api:()=>new Promise(resolve=>second=resolve)});await settle();first({id:'obsolete'});await settle();await settle();
ok(value===null&&busy,'older period response cannot replace rows or release a newer loading state');second({id:'new-period'});await settle();await settle();ok(value.id==='new-period'&&!busy,'newest period response owns the visible result');
requestStockPeriod({...setters,query,api:async()=>{throw Error('Referência antiga');}});await settle();await settle();ok(value===null&&message==='Referência antiga'&&!busy,'rejected reference shows an error without retaining previous report rows');
let reject;const stop=requestStockPeriod({...setters,query,api:()=>new Promise((resolve,r)=>reject=r)});await settle();stop();message='new context';reject(Error('late old failure'));await settle();await settle();ok(message==='new context','late failure after cancellation cannot overwrite another context message');
const server=await createServer({configFile:false,server:{middlewareMode:true,watch:null},appType:'custom',optimizeDeps:{noDiscovery:true}});
try{
const {default:Workspace,StockPeriodTable}=await server.ssrLoadModule('/resources/js/StockPeriodReportWorkspace.jsx');
const html=renderToStaticMarkup(React.createElement(Workspace,{api:()=>{throw Error('No automatic read');},context:{token:'qa'}}));
ok(html.includes('name="from"')&&html.includes('name="to"')&&html.includes('required=""')&&!html.includes('value="2026-'),'actual report form requires an explicit period without choosing dates or fetching on mount');
ok(html.includes('UTC')&&html.includes('designações')&&html.includes('Sem valorização'),'actual report explains registration time current metadata and physical-only scope');
const row={stock_item_id:1,warehouse_id:2,code:'QA',name:'Exact quantity',unit:'UN',warehouse_code:'WH',warehouse_name:'Warehouse',opening_milli:'9007199254740994',incoming_milli:'0',outgoing_milli:'1',closing_milli:'9007199254740993',period_movements:'1'};
const table=renderToStaticMarkup(React.createElement(StockPeriodTable,{rows:[row,{...row,stock_item_id:3,unit:'KG',opening_milli:'6000',closing_milli:'6000',outgoing_milli:'0',period_movements:'0'}]}));
ok(table.includes('9007199254740,994')&&table.includes('9007199254740,993')&&table.includes('0,001'),'actual report table renders exact three-decimal quantities beyond JS safe integer limits');
ok(table.includes('KG')&&table.includes('UN')&&!table.includes('<tfoot>'),'actual report preserves each unit and does not invent a grand quantity total');
ok(table.includes('Abertura')&&table.includes('Entradas')&&table.includes('Saídas')&&table.includes('Fecho'),'actual report labels all four reconciliation quantities');
}finally{await server.close();}
fs.writeFileSync(out,JSON.stringify({passed:true,checks,react_render:true,async_race_simulation:true,business_commands:0,visual_review:false},null,2));console.log(JSON.stringify({passed:true,checks:checks.length}));