59 lines
6.6 KiB
JavaScript
59 lines
6.6 KiB
JavaScript
const fs=require('node:fs'),path=require('node:path'),assert=require('node:assert/strict'),{spawn,spawnSync}=require('node:child_process');
|
|
const {chromium}=require('C:/Users/macbook/.cache/codex-runtimes/codex-primary-runtime/dependencies/node/node_modules/playwright');
|
|
const R=path.resolve(__dirname,'..'),P=path.join(R,'storage/app/private/investmoz-v2/portal-audit');
|
|
const plan=JSON.parse(fs.readFileSync(path.join(P,'onboarding-governance-plan.json'),'utf8')),S=plan.source;
|
|
const PHP='C:/laragon/bin/php/php-8.5.11-Win32-vs17-x64/php.exe';
|
|
assert(S.startsWith(P+path.sep+'onboarding-qa-')&&plan.target.port===55441&&plan.target.database.endsWith('_test'));
|
|
const roles=['investment_project','real_estate','land_rights','business_sale','business_partnership','franchise'];
|
|
const localFixture=path.join(S,'tools/onboarding-fixture.php');
|
|
fs.mkdirSync(path.join(S,'tools'),{recursive:true});fs.copyFileSync(path.join(R,'tools/portal-onboarding-governance-fixture.php'),localFixture);
|
|
fs.writeFileSync(path.join(S,'tools/onboarding-router.php'),`<?php
|
|
$root=dirname(__DIR__); $uri=parse_url($_SERVER['REQUEST_URI'],PHP_URL_PATH);
|
|
$file=realpath($root.'/public'.rawurldecode($uri)); $public=realpath($root.'/public');
|
|
if ($file && str_starts_with($file,$public.DIRECTORY_SEPARATOR) && is_file($file)) { return false; }
|
|
require $root.'/public/index.php';
|
|
`);
|
|
if(!fs.existsSync(path.join(S,'storage/app/private/onboarding-actors-local.json'))){const seeded=spawnSync(PHP,[localFixture,'seed'],{cwd:S,windowsHide:true,encoding:'utf8'});assert.equal(seeded.status,0,'QA fixture initialization failed: '+seeded.stderr.trim());}
|
|
const actors=JSON.parse(fs.readFileSync(path.join(S,'storage/app/private/onboarding-actors-local.json'),'utf8'));
|
|
const evidence={at:new Date().toISOString(),target:'http://127.0.0.1:18117',database:plan.target.database,port:55441,QA_only:true,active_writes:0,secrets_recorded:false,criteria:[],page_errors:[]};
|
|
const log=fs.openSync(path.join(S,'storage/logs/onboarding-http.log'),'a');
|
|
const server=spawn(PHP,['-S','127.0.0.1:18117','-t',path.join(S,'public'),path.join(S,'tools/onboarding-router.php')],{cwd:S,windowsHide:true,stdio:['ignore',log,log]});
|
|
let browser;
|
|
const pause=ms=>new Promise(resolve=>setTimeout(resolve,ms));
|
|
async function login(page,actor){
|
|
await page.goto(evidence.target+'/login');await page.locator('input[name="email"]').fill(actor.email);await page.locator('input[name="password"]').fill(actor.password);
|
|
await page.getByRole('button',{name:'Log in',exact:true}).click();await page.waitForURL('**/two-factor-challenge');
|
|
const otp=spawnSync(PHP,[localFixture,'otp','holder'],{cwd:S,windowsHide:true,encoding:'utf8'});assert.equal(otp.status,0);assert(/^\d{6}$/.test(otp.stdout));
|
|
await page.locator('input[autocomplete="one-time-code"]').fill(otp.stdout);await page.getByRole('button',{name:'Continue',exact:true}).click();await page.waitForURL('**/dashboard');
|
|
}
|
|
(async()=>{
|
|
try{
|
|
for(let attempt=0;attempt<30;attempt++){try{const response=await fetch(evidence.target+'/up');if(response.ok)break;}catch{}await pause(300);}
|
|
// Enrollment and login consume distinct normal TOTP intervals, without bypassing verification.
|
|
await pause(31000-Date.now()%30000);
|
|
browser=await chromium.launch({headless:true,executablePath:'C:/Users/macbook/AppData/Local/ms-playwright/chromium-1243/chrome-win64/chrome.exe'});
|
|
let context=await browser.newContext(),page=await context.newPage();page.on('pageerror',()=>evidence.page_errors.push('pageerror'));
|
|
await login(page,actors.holder);evidence.criteria.push('normal_login_MFA');
|
|
const nav=page.getByRole('link',{name:'Gestão de perfis',exact:true});assert(await nav.first().isVisible());await nav.first().click();await page.waitForURL('**/perfis/gestao');
|
|
await page.getByRole('heading',{name:'Gestão de perfis',exact:true}).waitFor();evidence.criteria.push('dashboard_to_profile_administration');
|
|
const form=page.locator('form').filter({has:page.getByRole('button',{name:'Atribuir com auditoria',exact:true})});
|
|
evidence.stage='assignment_subject';await form.getByLabel('ID da conta existente',{exact:true}).fill(String(actors.validator.id));await form.getByLabel('Papel',{exact:true}).selectOption('validator');
|
|
for(const category of roles){evidence.stage='category_'+category;await form.getByLabel(category,{exact:true}).check();}
|
|
await form.getByLabel('Fundamento',{exact:true}).fill('Synthetic QA preparation approved for all six base categories; operations remain disabled.');
|
|
evidence.stage='assignment_save';await form.getByRole('button',{name:'Atribuir com auditoria',exact:true}).click();await page.getByText('Conta '+actors.validator.id+': validator — atribuído',{exact:false}).waitFor();
|
|
evidence.criteria.push('visible_assignment_created');await page.reload();await page.getByText('Conta '+actors.validator.id+': validator — atribuído',{exact:false}).waitFor();evidence.criteria.push('assignment_recovered_after_reload');
|
|
const denied=await page.goto(evidence.target+'/minhas-oportunidades');assert.equal(denied.status(),404);evidence.criteria.push('operational_routes_remain_closed');
|
|
await context.close();await pause(31000-Date.now()%30000);context=await browser.newContext();page=await context.newPage();
|
|
await login(page,actors.holder);await page.goto(evidence.target+'/perfis/gestao');await page.getByText('Conta '+actors.validator.id+': validator — atribuído',{exact:false}).waitFor();evidence.criteria.push('assignment_recovered_in_new_normal_MFA_session');
|
|
await page.screenshot({path:path.join(P,'onboarding-governance-administration-qa.png'),fullPage:true});
|
|
const verified=spawnSync(PHP,[localFixture,'verify'],{cwd:S,windowsHide:true,encoding:'utf8'});assert.equal(verified.status,0);evidence.persistence=JSON.parse(verified.stdout);
|
|
assert.equal(evidence.persistence.assignments.length,1);assert.equal(evidence.persistence.audit_role_granted,1);assert.equal(evidence.persistence.opportunities,0);assert.equal(evidence.persistence.operational_enabled,false);evidence.result='passed';
|
|
}catch(error){evidence.result='stopped';evidence.error_type=error.name;process.exitCode=1;
|
|
if(evidence.stage && browser){const pages=browser.contexts().flatMap(c=>c.pages());const last=pages.at(-1);if(last&&new URL(last.url()).pathname==='/perfis/gestao'){
|
|
evidence.visible_feedback=await last.locator('main [role="status"]').allTextContents();
|
|
await last.screenshot({path:path.join(P,'onboarding-governance-stopped-qa.png'),fullPage:true});
|
|
}}
|
|
}
|
|
finally{if(browser)await browser.close();server.kill();fs.closeSync(log);fs.writeFileSync(path.join(P,'onboarding-governance-browser.json'),JSON.stringify(evidence,null,2));console.log(JSON.stringify(evidence));}
|
|
})();
|