import fs from 'node:fs';import path from 'node:path';import assert from 'node:assert/strict';import {Element,walk} from './purchasing-workspace-dom.mjs';import {evidence} from '../public/purchasing-presenter.mjs';import {installPurchasingExit} from '../public/purchasing-exit.mjs'; const run=JSON.parse(fs.readFileSync('C:/laragon/data/sgf-tempo/run/modular-regression-current.json')),root=path.join(run.root,'private/receipt-composition-cc50a276c10c'),out=path.join(root,'completion-client-result.json');assert(!fs.existsSync(out));const checks=[],ok=(v,name)=>{assert(v,name);checks.push(name);}; globalThis.document={createElement:tag=>new Element(tag)};const rendered=evidence({total_minor:10000,accepted_milli:1000,status:'active',due_on:null,name:''});ok(rendered.textContent.includes('100,00 MZN')&&rendered.textContent.includes('1,000')&&rendered.textContent.includes('Activo')&&rendered.textContent.includes('Por indicar'),'C09 prévia legível conserva montantes quantidades estado e pendências');ok(walk(rendered).every(e=>e.tag!=='script')&&rendered.textContent.includes(''),'C09 dados recebidos são texto e não instruções HTML');ok(evidence('constructor').textContent==='constructor','C09 designações não são confundidas com propriedades de objectos'); const listeners={},windowListeners={},main=new Element('main'),form=new Element('form'),input=new Element('input'),confirm=new Element('button','Confirmar'),link=new Element('a','Trocar função'),message=new Element('p');link.href='/compras';form.append(input,confirm);main.append(form,link);let allow=false,resolver,mode='success'; const doc={addEventListener:(name,fn)=>listeners[name]=fn,querySelector:()=>message},win={addEventListener:(name,fn)=>windowListeners[name]=fn,confirm:()=>allow,fetch:async()=>{if(mode==='wait')return new Promise(resolve=>resolver=resolve);return {ok:true,clone:()=>({json:async()=>{if(mode==='uncertain')throw Error('body lost');return {};}})};}}; const guard=installPurchasingExit(doc,win),event=(target,trusted=true)=>({target,isTrusted:trusted,prevented:false,preventDefault(){this.prevented=true;}}); listeners.input(event(input,false));ok(guard.dirty.size===0,'C09 carregamento automático de selectores não marca formulários vazios como alterados');listeners.input(event(input));let click=event(link);listeners.click(click);ok(click.prevented&&guard.dirty.size===1,'C09 cancelar a saída conserva campos por confirmar');allow=true;click=event(link);listeners.click(click);ok(!click.prevented&&guard.dirty.size===0,'C09 descarte só ocorre após escolha explícita'); listeners.input(event(input));listeners.click(event(confirm));mode='wait';const pending=win.fetch('/api/purchasing-requests/1/confirm',{method:'POST'});click=event(link);listeners.click(click);ok(click.prevented&&guard.pending()===1&&input.disabled,'C09 operação em curso impede mudar função e editar a confirmação');resolver({ok:true,clone:()=>({json:async()=>({})})});await pending;ok(!input.disabled&&guard.pending()===0&&guard.dirty.size===0,'C09 confirmação íntegra liberta navegação e restaura controlos'); listeners.input(event(input));listeners.click(event(confirm));mode='uncertain';await win.fetch('/api/purchasing-requests/1/confirm',{method:'POST'});ok(guard.dirty.size===1&&!input.disabled,'C09 resposta incerta mantém campos para recuperação manual');const unload=event(input);windowListeners.beforeunload(unload);ok(unload.prevented,'C09 fechar a página avisa de campos ainda por confirmar'); fs.writeFileSync(out,JSON.stringify({passed:true,checks,dom_simulation:true,business_commands:0,visual_review:false},null,2));console.log(JSON.stringify({passed:true,checks:checks.length}));