Files
SGF/scripts/preview-http-proof.mjs
nala f8d57b52aa Preserva classificacao contabilistica aceite e bases locais
Regista aceitacao funcional do primeiro incremento PGC-NIRF e preserva as dependencias documentais e tecnicas existentes. A validacao do calculo fiscal continua separada e pendente. Sem credenciais, bases operacionais ou publicacao.
2026-10-26 13:47:11 +02:00

39 lines
4.9 KiB
JavaScript

import fs from 'node:fs/promises';
import assert from 'node:assert/strict';
import { randomUUID } from 'node:crypto';
const fixture = JSON.parse(await fs.readFile('C:/laragon/data/sgf-tempo/secrets/browser-fixture.json','utf8'));
const base = 'http://127.0.0.1:8001';
function client() {
const cookies = new Map(); let csrf = '', context = '';
return {
async request(path, method = 'GET', body, token = context) {
const response = await fetch(base + path, { method, headers: { Accept:'application/json','Content-Type':'application/json',Cookie:[...cookies].map(([k,v]) => `${k}=${v}`).join('; '),'X-CSRF-TOKEN':csrf,'X-SGF-Context':token,'Idempotency-Key':randomUUID() },...(body === undefined ? {} : {body:JSON.stringify(body)}) });
for (const cookie of response.headers.getSetCookie()) { const pair=cookie.split(';',1)[0], split=pair.indexOf('='); cookies.set(pair.slice(0,split),pair.slice(split+1)); }
const data=await response.json().catch(() => ({})); if(data.csrf)csrf=data.csrf;if(data.context?.token)context=data.context.token;
return {status:response.status,data,cache:response.headers.get('cache-control')};
},
async login(email) {await this.request('/api/session');assert.equal((await this.request('/api/login','POST',{email,password:fixture.password})).status,200);return this.select();},
async select(unit=fixture.unit) {const response=await this.request('/api/context','POST',{tenant_id:fixture.tenant,company_id:fixture.company,unit_id:unit});assert.equal(response.status,200);return response.data.context.token;}
};
}
const manager=client(),reader=client();await manager.login('gestor@example.test');await reader.login('consulta@example.test');
const path=`/api/document-preview/draft/${fixture.document_draft_id}`;
const first=await manager.request(path);assert.equal(first.status,200);assert.ok(first.cache.includes('no-store'));assert.equal(first.data.notice,'RASCUNHO — SEM VALIDADE FISCAL');assert.equal(first.data.base_amount,'0.0000000125');assert.equal(first.data.data.currency,null);assert.ok(first.data.pending.tax_rule_pending);
const model={version:0,show_logo:false,show_contacts:true,show_observations:true,show_payment_instructions:false,contact_text:'Contactos sintéticos da empresa',observations:'Observações iniciais da demonstração'};
assert.equal((await manager.request('/api/document-preview/model','PATCH',model)).status,200);
const revision=await manager.request(path+'/revision');assert.equal(revision.status,200);assert.notEqual(revision.data.revision,first.data.revision);assert.equal(Object.keys(revision.data).join(','),'revision');
const refreshed=await manager.request(path);assert.equal(refreshed.data.observations,model.observations);assert.equal(refreshed.data.payments.length,0);assert.equal(refreshed.data.notice,first.data.notice);assert.ok(refreshed.data.pending.tax_rule_pending);
assert.equal((await reader.request(path)).status,200);assert.equal((await reader.request('/api/document-preview/model','PATCH',{...model,version:1})).status,403);
assert.equal((await manager.request('/api/document-preview/model','PATCH',{...model,version:1,show_notice:false})).status,422);
assert.equal((await manager.request('/api/document-preview/model','PATCH',model)).status,409);
const oldContext=await manager.select();await manager.select(null);assert.equal((await manager.request('/api/document-preview/model','PATCH',{...model,version:1},oldContext)).status,409);await manager.select();
const list=await manager.request('/api/a/billing_drafts');const confirmed=list.data.records.find(record=>record.internal_confirmation);
assert.ok(confirmed);const historyPath=`/api/document-preview/history/${confirmed.id}`;
const history=await manager.request(historyPath);assert.equal(history.status,200);assert.equal(history.data.contacts,null);assert.equal(history.data.issuer.name,null);
assert.equal((await manager.request('/api/document-preview/model','PATCH',{...model,version:1,observations:'Observações para a prova no navegador'})).status,200);
const historyAfter=await manager.request(historyPath);assert.equal(historyAfter.data.revision,history.data.revision);assert.equal(historyAfter.data.contacts,null);
await manager.request('/api/logout','POST');await reader.request('/api/logout','POST');
await fs.writeFile('docs/proofs/preview-http-results.json',JSON.stringify({database:'sgf_tempo_test',real_synthetic_login:true,results:['Read-only composition reuses exact values and unknown currency; no-store headers.', 'Revision changes after configuration; explicit new read loads new values.', 'Reader consults but cannot configure (403); hidden mandatory content rejected (422).', 'Old configuration version and context rejected (409).', 'Historical consultation is independent of current configuration and does not reconstruct missing issuer name.'],instruction_values:'omitted'},null,2));
console.log('Isolated preview HTTP proof passed; instruction values omitted.');