Files
Investidor-V2/tools/portal-promoter-visual-qa.cjs
T
nala 287e991486
tests / ci (push) Waiting to run
oportunidades 7
2026-10-13 11:40:29 +02:00

208 lines
7.9 KiB
JavaScript

const {
start,
BASE,
assert,
sanitized,
} = require('./portal-visual-qa-lib.cjs');
void (async () => {
const q = await start('promoter-dashboard-chromium-20261010');
q.proof.opportunity = q.prior.opportunity || {
title: 'QA dashboard Promotor — ' + q.stamp,
};
let page, ctx;
try {
q.phase('Dashboard QA21 → Minhas oportunidades → Nova oportunidade');
({ page, ctx } = await q.context('promoter'));
await q.login(page, 'promoter');
await q.open(page, '/dashboard');
const root = page.locator('main').last();
await root
.getByRole('link', { name: 'Minhas oportunidades', exact: true })
.first()
.waitFor();
await root
.getByRole('link', { name: 'Nova oportunidade', exact: true })
.first()
.waitFor();
await q.shot(page, 'dashboard-promoter');
await root
.getByRole('link', { name: 'Minhas oportunidades', exact: true })
.first()
.click();
await page.waitForURL(BASE + '/minhas-oportunidades');
await page
.getByRole('link', { name: 'Nova oportunidade', exact: true })
.first()
.click();
await page.waitForURL(BASE + '/minhas-oportunidades/create');
const e = q.proof.opportunity;
if (!e.id) {
await page
.getByLabel('Título oficial', { exact: true })
.fill(e.title);
await page
.getByLabel('Motivo da alteração', { exact: true })
.fill('Criação sintética QA pelo dashboard, sem divulgação.');
await page
.getByRole('button', { name: 'Guardar rascunho', exact: true })
.click();
await page.waitForURL(/\/minhas-oportunidades\/\d+\/edit$/);
e.id = Number(new URL(page.url()).pathname.split('/')[2]);
e.created_via_dashboard = true;
q.save();
}
q.proof.checks.dashboard_links_create_save = true;
await q.logout(page);
await ctx.close();
q.phase('Fresh MFA session, recovery and editing');
({ page, ctx } = await q.context('promoter-new-session'));
await q.login(page, 'promoter');
await q.open(page, '/dashboard');
await page
.getByRole('link', { name: 'Minhas oportunidades', exact: true })
.first()
.click();
await page.waitForURL(BASE + '/minhas-oportunidades');
const card = page.locator('article').filter({
has: page.getByRole('heading', { name: e.title, exact: true }),
});
await card
.getByRole('link', { name: 'Continuar preenchimento', exact: true })
.click();
await page.waitForURL((u) =>
u.pathname.includes('/minhas-oportunidades/' + e.id),
);
if (!new URL(page.url()).pathname.endsWith('/edit')) {
await page
.getByRole('link', {
name: 'Editar proposta privada',
exact: true,
})
.click();
await page.waitForURL(
BASE + '/minhas-oportunidades/' + e.id + '/edit',
);
}
assert.equal(
await page
.getByLabel('Título oficial', { exact: true })
.inputValue(),
e.title,
);
e.recovered_new_session = true;
await page
.getByLabel('Resumo executivo', { exact: true })
.fill(
'Resumo sintético recuperável; dossier privado separado da oportunidade.',
);
await page
.getByLabel('Motivo da alteração', { exact: true })
.fill('Edição sintética QA pelo Promotor autorizado.');
await page
.getByRole('button', { name: 'Guardar rascunho', exact: true })
.click();
await page
.getByText(
'Rascunho guardado no servidor. Não foi submetido, aprovado ou publicado.',
{ exact: true },
)
.waitFor();
await page.reload({ waitUntil: 'domcontentloaded' });
assert.equal(
await page
.getByLabel('Resumo executivo', { exact: true })
.inputValue(),
'Resumo sintético recuperável; dossier privado separado da oportunidade.',
);
e.edited_recovered = true;
assert.equal(
await page
.getByRole('button', { name: 'Arquivar', exact: true })
.count(),
0,
);
assert.equal(
await page
.getByRole('button', { name: 'Restaurar', exact: true })
.count(),
0,
);
await page
.getByLabel('Fundamentação', { exact: true })
.fill('Pedido de arquivo sintético QA após teste do dashboard.');
await page
.getByRole('button', { name: 'Solicitar arquivo', exact: true })
.click();
await page
.getByText(
'Pedido de arquivo registado; aguarda decisão independente.',
{ exact: false },
)
.waitFor();
await page.reload({ waitUntil: 'domcontentloaded' });
await page
.getByText(
'Pedido de arquivo registado; aguarda decisão independente.',
{ exact: false },
)
.waitFor();
e.archive_request_persisted = true;
await q.shot(page, 'promoter-recovered-archive-request');
q.proof.checks.recover_edit_request_archive_no_self_archive = true;
await q.logout(page);
await ctx.close();
q.phase('Independent authorized publisher archive');
({ page, ctx } = await q.context('publisher'));
await q.login(page, 'publisher');
await q.open(page, '/minhas-oportunidades/' + e.id + '/view');
await page
.getByLabel('Fundamentação', { exact: true })
.fill('Decisão independente de arquivo sintético QA para ensaio.');
await page
.getByRole('button', { name: 'Arquivar', exact: true })
.click();
await page.reload({ waitUntil: 'domcontentloaded' });
await page.getByText(/Estado da preparação: Arquivado/).waitFor();
e.archived_by_authorized_publisher = true;
await q.shot(page, 'publisher-archived');
q.proof.checks.independent_archive_persisted = true;
q.proof.restore = {
state: 'not_available_for_profile_owned_opportunities',
reason: 'The reconciled v1 disallows promoter restore and legacy lifecycle denies profile-owned records. No new restore policy is invented.',
};
q.proof.result = 'passed_scoped_restore_pending';
await q.logout(page);
await ctx.close();
} catch (e) {
q.proof.result = 'failed';
q.proof.error = sanitized(e);
if (
page &&
!['/login', '/two-factor-challenge'].includes(
new URL(page.url()).pathname,
)
) {
q.proof.failure_state = {
path: new URL(page.url()).pathname,
headings: await page.locator('h1').allTextContents(),
labels: await page.locator('label').allTextContents(),
alerts: await page.getByRole('alert').allTextContents(),
};
await q.shot(page, 'failure').catch(() => {});
}
} finally {
q.proof.finished_at = new Date().toISOString();
q.save();
await q.browser.close();
console.log(
JSON.stringify({
result: q.proof.result,
phase: q.proof.phase,
checks: q.proof.checks,
receipt: q.receipt,
}),
);
if (q.proof.result === 'failed') process.exitCode = 1;
}
})();