const { chromium, } = require('C:/Users/macbook/.cache/codex-runtimes/codex-primary-runtime/dependencies/node/node_modules/playwright'); const assert = require('node:assert/strict'); const fs = require('node:fs'); const base = 'http://127.0.0.1:18092'; const dir = 'storage/app/private/investmoz-v2'; void (async () => { const browser = await chromium.launch({ headless: true, executablePath: 'C:/Users/macbook/AppData/Local/ms-playwright/chromium-1243/chrome-win64/chrome.exe', }); const errors = []; async function login(role) { const context = await browser.newContext({ viewport: { width: 1440, height: 1000 }, }); await context.route('**/*', (r) => r.request().url().startsWith(base) ? r.continue() : r.abort(), ); const page = await context.newPage(); page.on('pageerror', (e) => errors.push(e.message)); const response = await page.goto(base + '/login'); assert.equal( response.headers()['x-investmoz-qa-target'], 'investmoz_v2_20261008_test:55441', ); await page .locator('input[type=email]') .fill(`guidance-qa-${role}@example.invalid`); await page.locator('input[type=password]').fill('QA-Guidance-2026!'); await page.locator('button[type=submit]').click(); await page.waitForURL((url) => !url.pathname.startsWith('/login')); return page; } try { const owner = await login('investor'); const manager = await login('manager'); const id = await owner.evaluate(async () => { const token = decodeURIComponent( document.cookie .split('; ') .find((c) => c.startsWith('XSRF-TOKEN=')) .slice(11), ); const response = await fetch('/balcao-virtual/dossiers', { method: 'POST', headers: { Accept: 'application/json', 'Content-Type': 'application/json', 'X-XSRF-TOKEN': token, }, body: JSON.stringify({ title: 'Segunda entrega sintética QA', reuse_consent: true, client_key: crypto.randomUUID(), }), }); if (response.status !== 201) throw new Error('QA creation failed'); return (await response.json()).id; }); await owner.goto(`${base}/balcao-virtual/dossiers/${id}`); await owner .getByText('Corrigir pressupostos ou registar uma alternativa', { exact: true, }) .click(); for (const [label, value] of Object.entries({ 'Procura declarada (quantidade, não previsão)': '100', 'Capacidade declarada na mesma unidade e período': '50', 'Unidade comum da procura e capacidade': 'toneladas', 'Período comum da procura e capacidade': 'ano', 'Financiamento necessário declarado': '100.50', 'Financiamento comprometido declarado': '100.49', 'Moeda comum do financiamento': 'MZN', })) { await owner.getByLabel(label, { exact: true }).fill(value); } const [saved] = await Promise.all([ owner.waitForResponse( (response) => response.url().endsWith('/pressupostos') && response.request().method() === 'POST', ), owner .getByRole('button', { name: 'Guardar pressupostos corrigidos', exact: true, }) .click(), ]); assert.ok(saved.status() < 400); await owner.waitForLoadState('networkidle'); await owner.goto(`${base}/balcao-virtual/dossiers/${id}?phase=market`); await owner .getByText('A procura declarada excede a capacidade declarada', { exact: false, }) .waitFor(); await owner.goto(`${base}/balcao-virtual/dossiers/${id}?phase=finance`); await owner .getByText('O financiamento comprometido declarado é inferior', { exact: false, }) .waitFor(); await manager.goto(`${base}/balcao-virtual/dossiers/${id}`); const review = manager.locator('form').filter({ has: manager.getByRole('button', { name: 'Registar a minha conferência da ligação', exact: true, }), }); await review .getByLabel('Evidência e data da consulta') .fill( 'Consulta sintética QA: endereço indisponível; nenhum pedido externo efetuado.', ); await review .getByLabel('Contacto alternativo com fonte') .fill('Pedido de apoio interno; fonte fixture QA'); await review .getByRole('button', { name: 'Registar a minha conferência da ligação', }) .click(); await manager.waitForLoadState('networkidle'); await owner.goto(`${base}/balcao-virtual/dossiers/${id}`); await owner .getByText('Pedido de apoio interno; fonte fixture QA', { exact: false, }) .waitFor(); await owner .getByRole('link', { name: 'Ligação indisponível: continuar internamente', exact: true, }) .click(); await owner.waitForLoadState('networkidle'); assert.ok(owner.url().includes('/dossiers/' + id)); await manager.goto(base + '/management/balcao-install'); await manager .getByRole('heading', { name: 'Instalação autenticada do Balcão e acompanhamento', }) .waitFor(); await manager .getByText('Destino: investmoz_v2_20261008_test', { exact: false }) .waitFor(); await manager .getByText('Indisponível (scanner_unavailable)', { exact: false }) .waitFor(); await manager.screenshot({ path: dir + '/second-install-qa.png', fullPage: true, }); assert.deepEqual(errors, []); const proof = { passed: true, database: 'investmoz_v2_20261008_test', port: 55441, errors, checks: [ 'Assumptions saved through UI; comparable declared gaps explained.', 'Human link review, fallback contact and internal continuation through UI.', 'Authenticated installation page shows actual QA target and unavailable ClamD; no active installation.', ], }; fs.writeFileSync( dir + '/second-browser-evidence.json', JSON.stringify(proof, null, 2), ); console.log(JSON.stringify(proof)); } finally { await browser.close(); } })().catch((error) => { console.error(error); process.exitCode = 1; });