Files
Investidor-V2/tools/investmoz-v2-draft-save-browser.cjs

260 lines
9.6 KiB
JavaScript

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';
(async () => {
const b = await chromium.launch({
headless: true,
executablePath:
'C:/Users/macbook/AppData/Local/ms-playwright/chromium-1243/chrome-win64/chrome.exe',
});
try {
const c = await b.newContext();
const p = await c.newPage();
let posts = 0;
let requestPayload;
const responses = [];
await c.route('**/*', (r) =>
r.request().url().startsWith(base) ? r.continue() : r.abort(),
);
p.on('response', async (r) => {
if (
r.url().includes('/simulation-drafts') &&
r.request().method() === 'POST'
) {
const body = await r.json();
responses.push({
status: r.status(),
body,
payload: r.request().postDataJSON(),
});
requestPayload = r.request().postDataJSON();
}
});
p.on('request', (r) => {
if (r.method() === 'POST' && r.url().includes('/balcao-virtual'))
posts++;
});
await p.addInitScript(() => {
if (!sessionStorage.getItem('investmoz-simulation-draft-v1'))
sessionStorage.setItem(
'investmoz-simulation-draft-v1',
JSON.stringify({
journey_type: 'personal',
detail_level: 'simple',
purpose: 'simulate_only',
preferred_language: 'pt',
fiscal_period: '2026',
fiscal_periodicity: 'annual',
fiscal_component: 'customs_ice',
fiscal_customs_code: 'QA-NAO-CLASSIFICADO',
fiscal_operation: 'import',
fiscal_scenario_mode: 'custom_planning',
base: '1000',
rate: '5',
reduction: '0',
}),
);
});
const initial = await p.goto(base + '/simulador-fiscal');
assert.equal(
initial.headers()['x-investmoz-qa-target'],
'investmoz_v2_20261008_test:55441',
);
await p
.getByText('O servidor não confirmou a gravação.', { exact: false })
.waitFor();
await p
.getByRole('button', { name: '1. Finalidade', exact: true })
.click();
const field = p.getByRole('combobox').last();
assert.equal(await field.getAttribute('aria-invalid'), 'true');
await field.fill('');
await field.press('ArrowDown');
console.log(await p.getByRole('option').allTextContents());
await p
.getByRole('option', { name: /Portugu/ })
.first()
.click();
await p
.getByText('Rascunho guardado no servidor às', { exact: false })
.waitFor();
assert.equal(responses[0].status, 422);
assert.equal(
responses[0].body.errors['economic_snapshot.preferred_language'][0],
'The selected economic_snapshot.preferred_language is invalid.',
);
assert.equal(
requestPayload.economic_snapshot.preferred_language,
'pt-MZ',
);
await p
.getByRole('button', { name: '3. Revisão', exact: true })
.click();
await p
.getByRole('button', { name: 'Validar este rascunho', exact: true })
.click();
await p.locator('#draft-validation-summary').waitFor();
const saved = responses.find((x) => x.status === 201);
assert.ok(saved);
await c.close();
async function login(page) {
await page.goto(base + '/login');
await page
.locator('input[type=email]')
.fill('guidance-qa-investor@example.invalid');
await page
.locator('input[type=password]')
.fill('QA-Guidance-2026!');
await page.locator('button[type=submit]').click();
await page.waitForURL((u) => !u.pathname.startsWith('/login'));
}
const c2 = await b.newContext();
const p2 = await c2.newPage();
await login(p2);
const result = await p2.evaluate(async (snapshots) => {
const token = document.cookie
.split('; ')
.find((x) => x.startsWith('XSRF-TOKEN='))
?.slice(11);
const current = await fetch('/api/v1/simulation-drafts/current', {
headers: { Accept: 'application/json' },
});
const existing = await current.json();
const r = await fetch(
existing.data
? '/api/v1/simulation-drafts/' + existing.data.id
: '/api/v1/simulation-drafts',
{
method: existing.data ? 'PUT' : 'POST',
headers: {
Accept: 'application/json',
'Content-Type': 'application/json',
'X-XSRF-TOKEN': decodeURIComponent(token),
'Idempotency-Key': crypto.randomUUID(),
...(existing.data
? { 'If-Match': current.headers.get('ETag') }
: {}),
},
body: JSON.stringify(snapshots),
},
);
return { status: r.status, body: await r.json() };
}, requestPayload);
assert.ok([200, 201].includes(result.status), JSON.stringify(result));
const id = result.body.data.id;
await c2.close();
const c3 = await b.newContext();
const p3 = await c3.newPage();
await login(p3);
assert.equal(await p3.evaluate(() => sessionStorage.length), 0);
await p3.goto(base + '/simulador-fiscal?draft=' + id);
await p3
.getByText('Dossier privado recuperado da sua conta.', {
exact: false,
})
.waitFor();
await p3
.getByRole('button', { name: '2. Operação fiscal', exact: true })
.click();
assert.equal(
await p3
.getByLabel('Base hipotética para planeamento', {
exact: false,
})
.inputValue(),
'1000',
);
const uiSave = p3.waitForResponse(
(r) =>
r.request().method() === 'PUT' &&
r.url().includes('/simulation-drafts/' + id) &&
r.request().postDataJSON()?.economic_snapshot?.base === '1200',
);
await p3
.getByLabel('Base hipotética para planeamento', { exact: false })
.fill('1200');
assert.equal((await uiSave).status(), 200);
await p3.evaluate(() => {
sessionStorage.clear();
localStorage.clear();
});
await p3.reload();
await p3
.getByText('Dossier privado recuperado da sua conta.', {
exact: false,
})
.waitFor();
await p3
.getByRole('button', { name: '2. Operação fiscal', exact: true })
.click();
assert.equal(
await p3
.getByLabel('Base hipotética para planeamento', {
exact: false,
})
.inputValue(),
'1200',
);
await p3
.getByRole('button', { name: '3. Revisão', exact: true })
.click();
let calculations = 0;
p3.on('request', (r) => {
if (
r.method() === 'POST' &&
new URL(r.url()).pathname === '/api/v1/simulations'
)
calculations++;
});
await p3
.getByRole('button', { name: 'Validar este rascunho', exact: true })
.click();
assert.equal(calculations, 0);
await p3
.getByRole('button', { name: '2. Operação fiscal', exact: true })
.click();
await p3
.getByRole('button', {
name: 'Validar e calcular no servidor',
exact: true,
})
.click();
await p3
.getByText('Cálculo concluído no servidor.', { exact: false })
.waitFor();
assert.equal(calculations, 1);
assert.equal(posts, 0);
fs.writeFileSync(
'storage/app/private/investmoz-v2/draft-422-browser.json',
JSON.stringify(
{
qa: 'investmoz_v2_20261008_test:55441',
responses,
ownedDraft: id,
ownedCreation: result.status,
freshAuthenticatedSession: true,
noLocalStorageRecovery: true,
baseRecovered: '1200',
authenticatedUiSave: 200,
separateCalculationPosts: calculations,
deskSubmissions: posts,
},
null,
2,
),
);
await c3.close();
console.log(
'422 correction, field errors, server save and fresh account recovery passed',
);
} finally {
await b.close();
}
})().catch((e) => {
console.error(e);
process.exitCode = 1;
});