120 lines
4.7 KiB
JavaScript
120 lines
4.7 KiB
JavaScript
// Read-only browser smoke test; reuse the dedicated QA Edge debugger on 9224.
|
|
import fs from 'node:fs';
|
|
const base = process.argv[2] ?? 'http://127.0.0.1:8000';
|
|
if (!/^http:\/\/127\.0\.0\.1:\d+$/.test(base))
|
|
throw Error('Local QA server required');
|
|
const target = await (
|
|
await fetch('http://127.0.0.1:9224/json/new?about:blank', { method: 'PUT' })
|
|
).json();
|
|
const ws = new WebSocket(target.webSocketDebuggerUrl);
|
|
await new Promise((resolve) =>
|
|
ws.addEventListener('open', resolve, { once: true }),
|
|
);
|
|
let sequence = 0;
|
|
const pending = new Map();
|
|
const errors = [];
|
|
ws.onmessage = (event) => {
|
|
const message = JSON.parse(event.data);
|
|
if (message.method === 'Runtime.exceptionThrown')
|
|
errors.push(message.params.exceptionDetails.text);
|
|
if (message.id) {
|
|
const callback = pending.get(message.id);
|
|
pending.delete(message.id);
|
|
callback(message.error ? { error: message.error } : message.result);
|
|
}
|
|
};
|
|
const send = (method, params = {}) =>
|
|
new Promise((resolve) => {
|
|
const id = ++sequence;
|
|
pending.set(id, resolve);
|
|
ws.send(JSON.stringify({ id, method, params }));
|
|
});
|
|
const evaluate = async (expression) => {
|
|
const result = await send('Runtime.evaluate', {
|
|
expression,
|
|
returnByValue: true,
|
|
});
|
|
if (result.exceptionDetails || result.error)
|
|
throw Error(JSON.stringify(result));
|
|
return result.result?.value;
|
|
};
|
|
await send('Page.enable');
|
|
await send('Runtime.enable');
|
|
const observations = [];
|
|
try {
|
|
for (const width of [390, 1440]) {
|
|
await send('Emulation.setDeviceMetricsOverride', {
|
|
width,
|
|
height: 900,
|
|
deviceScaleFactor: 1,
|
|
mobile: width < 600,
|
|
});
|
|
for (const path of [
|
|
'/zonas?category=zee',
|
|
'/zonas?category=zfi',
|
|
'/zonas?category=industrial_park',
|
|
'/oportunidades',
|
|
'/oportunidades?view=combined',
|
|
]) {
|
|
await send('Page.navigate', { url: base + path });
|
|
let ready = false;
|
|
for (let attempt = 0; attempt < 100; attempt++) {
|
|
await new Promise((resolve) => setTimeout(resolve, 100));
|
|
ready = await evaluate(
|
|
`document.readyState==='complete' && location.href===${JSON.stringify(base + path)} && !!document.querySelector('h1')`,
|
|
);
|
|
if (ready) break;
|
|
}
|
|
if (!ready) throw Error('Page not ready: ' + path);
|
|
const result = await evaluate(
|
|
`({title:document.querySelector('h1').textContent,overflow:document.documentElement.scrollWidth>innerWidth+1,breadcrumb:!!document.querySelector('nav[aria-label="Caminho de navegação"]'),support:[...document.querySelectorAll('a')].some(a=>a.textContent.includes('Contactar Apoio')),dimensions:['Por Cluster','Por Corredor','Por ZEE','Por ZFI'].every(text=>[...document.querySelectorAll('a')].some(a=>a.textContent===text))})`,
|
|
);
|
|
if (
|
|
result.overflow ||
|
|
!result.breadcrumb ||
|
|
!result.support ||
|
|
!result.dimensions
|
|
)
|
|
throw Error(JSON.stringify({ path, width, ...result }));
|
|
observations.push({ path, width, ...result });
|
|
}
|
|
}
|
|
await send('Network.enable');
|
|
await send('Network.setBlockedURLs', { urls: ['*api/v1/investment/map*'] });
|
|
await send('Page.navigate', { url: base + '/oportunidades?view=map' });
|
|
let fallback = false;
|
|
for (let attempt = 0; attempt < 100; attempt++) {
|
|
await new Promise((resolve) => setTimeout(resolve, 100));
|
|
fallback = await evaluate(
|
|
`document.body.innerText.includes('Mapa indisponível') && [...document.querySelectorAll('article a')].some(a=>a.getAttribute('href')?.startsWith('/oportunidades/'))`,
|
|
);
|
|
if (fallback) break;
|
|
}
|
|
if (!fallback) throw Error('Map failure did not preserve investment list');
|
|
observations.push({ scenario: 'map_request_blocked', fallback_list: true });
|
|
await send('Network.setBlockedURLs', { urls: [] });
|
|
if (errors.length) throw Error('JavaScript errors: ' + errors.join('; '));
|
|
fs.writeFileSync(
|
|
'docs/investmoz/zones/browser-validation.json',
|
|
JSON.stringify(
|
|
{
|
|
date: new Date().toISOString(),
|
|
scope: 'Public pages and empty states only; no institutional workflow/UAT claim',
|
|
observations,
|
|
errors,
|
|
},
|
|
null,
|
|
2,
|
|
),
|
|
);
|
|
console.log(
|
|
JSON.stringify({
|
|
passed: observations.length,
|
|
javascript_errors: errors.length,
|
|
}),
|
|
);
|
|
} finally {
|
|
await send('Page.close');
|
|
ws.close();
|
|
}
|