test: keep Traffic interception off workers and restore screenshot windows

This commit is contained in:
Said committed 2026-10-20 15:12:32 +01:00
1 parent 116f28a525
commit 168d491038
6 files changed
+230 -27

No files matched your search

+27
View File
@@ -18,3 +18,30 @@ export function chromeExecutablePath({
if (env.PUPPETEER_EXECUTABLE_PATH) return env.PUPPETEER_EXECUTABLE_PATH;
return exists(MACOS_CHROME) ? MACOS_CHROME : undefined;
}
/** Restore an owned test window before capture: focus emulation alone does not
* unminimize the native compositor, so CDP screenshots can otherwise stall. */
export async function captureQaScreenshot(
page,
options,
{ headful = true } = {},
) {
if (headful) {
const session = await page.createCDPSession();
try {
const { windowId, bounds } = await session.send(
'Browser.getWindowForTarget',
);
if (bounds.windowState === 'minimized') {
await session.send('Browser.setWindowBounds', {
windowId,
bounds: { windowState: 'normal' },
});
}
await page.bringToFront();
} finally {
await session.detach();
}
}
return page.screenshot(options);
}
+11 -26
View File
@@ -31,6 +31,7 @@
*/
import puppeteer from 'puppeteer';
import { captureQaScreenshot } from './qa-chrome.mjs';
import fs from 'node:fs';
import path from 'node:path';
import { fileURLToPath } from 'node:url';
@@ -49,7 +50,7 @@ appUrl.searchParams.set('welcome', '0');
const APP_URL = appUrl.href;
const HEADFUL = argv.includes('--headful');
const FIXTURES = argv.includes('--fixtures');
const fixtureResponse = FIXTURES ? (await import('./traffic-fixtures.mjs')).trafficFixtureResponse : () => null;
const { installTrafficRoutes } = await import('./traffic-fixtures.mjs');
const CHROME_EXECUTABLE_CANDIDATES = [
process.env.PUPPETEER_EXECUTABLE_PATH,
@@ -158,11 +159,6 @@ async function main() {
// Chrome minimized. Use browser focus emulation, not patched DOM getters.
const focusSession = await page.createCDPSession();
await focusSession.send('Emulation.setFocusEmulationEnabled', { enabled: true });
const onFixture = (request) => {
const response = fixtureResponse(request);
if (response) void request.respond(response); else void request.continue();
};
if (FIXTURES) { await page.setCacheEnabled(false); await page.setRequestInterception(true); page.on('request', onFixture); }
await page.setViewport({ width: 1440, height: 900 });
// Track flow-tile requests + traffic console lines for (ii)/(iii)/(v).
@@ -172,6 +168,7 @@ async function main() {
});
const trafficLogs = [];
const pageErrors = [];
if (FIXTURES) await installTrafficRoutes(page, { origin: appUrl.origin, fixtures: true, onError: error => pageErrors.push(error.message) });
page.on('pageerror', error => { pageErrors.push(error.message); console.error('PAGE ERROR:', error.message); });
page.on('console', message => { if (message.type() === 'error') console.error('BROWSER ERROR:', message.text()); });
page.on('console', (msg) => {
@@ -210,7 +207,7 @@ async function main() {
`coverage=${mumbai.flowCoveragePct}% tiles=${mumbai.tilesFetched}`);
if (mumbai.mode !== 'live' || !(mumbai.count > 0) || !(colored > 0)) exitCode = 1;
await sleep(1200);
await page.screenshot({ path: path.join(SHOTS_DIR, 'traffic-live-flow.png') });
await captureQaScreenshot(page, { path: path.join(SHOTS_DIR, 'traffic-live-flow.png') }, { headful: HEADFUL });
}
// ── (iv) uncovered-roads param — hide vs sim ─────────────────────────────
@@ -243,7 +240,7 @@ async function main() {
(hid.flowBuckets?.sim || 0) === 0 && hid.count > 0,
`count=${hid.count} sim=${hid.flowBuckets?.sim}`);
if ((hid.flowBuckets?.sim || 0) !== 0) exitCode = 1;
await page.screenshot({ path: path.join(SHOTS_DIR, 'traffic-live-hide-mode.png') });
await captureQaScreenshot(page, { path: path.join(SHOTS_DIR, 'traffic-live-hide-mode.png') }, { headful: HEADFUL });
} else {
record('PARAM: hide mode renders zero sim (white) dots', null,
'view had 100% coverage (no sim dots to hide) — inconclusive here, covered by unit tests');
@@ -265,7 +262,7 @@ async function main() {
}
record('C4: oblique fetch box centers on the look-at point', ok, detail);
if (!ok) exitCode = 1;
await page.screenshot({ path: path.join(SHOTS_DIR, 'traffic-c4-oblique.png') });
await captureQaScreenshot(page, { path: path.join(SHOTS_DIR, 'traffic-c4-oblique.png') }, { headful: HEADFUL });
}
// ── (iii) budget honesty ─────────────────────────────────────────────────
@@ -290,23 +287,11 @@ async function main() {
await keylessFocus.send('Emulation.setFocusEmulationEnabled', { enabled: true });
page.on('pageerror', error => { pageErrors.push(error.message); console.error('PAGE ERROR:', error.message); });
page.on('console', message => { if (message.type() === 'error') console.error('BROWSER ERROR:', message.text()); });
await page.setCacheEnabled(false);
await page.setRequestInterception(true);
const keylessFlowReqs = [];
page.on('request', (req) => {
const url = req.url();
if (url.includes('/api/tomtom/status')) {
req.respond({ status: 200, contentType: 'application/json', body: JSON.stringify({ hasKey: false }) });
return;
}
if (url.includes('/api/tomtom/flow/')) {
keylessFlowReqs.push(url);
req.respond({ status: 503, contentType: 'application/json', body: JSON.stringify({ error: 'no_key' }) });
return;
}
const response = fixtureResponse(req);
if (response) { void req.respond(response); return; }
try { req.continue(); } catch { /* already handled */ }
await installTrafficRoutes(page, {
origin: appUrl.origin, fixtures: FIXTURES, keyless: true,
onFlow: url => keylessFlowReqs.push(url),
onError: error => pageErrors.push(error.message),
});
await page.goto(APP_URL, { waitUntil: 'domcontentloaded', timeout: 60000 });
await page.waitForFunction(
@@ -338,7 +323,7 @@ async function main() {
exitCode = 1;
}
await sleep(1000);
await page.screenshot({ path: path.join(SHOTS_DIR, 'traffic-sim-keyless.png') });
await captureQaScreenshot(page, { path: path.join(SHOTS_DIR, 'traffic-sim-keyless.png') }, { headful: HEADFUL });
}
record('BROWSER: no uncaught page exceptions', pageErrors.length === 0, pageErrors.join('; '));
} catch (e) {
+56
View File
@@ -117,3 +117,59 @@ export function trafficFixtureResponse(request) {
body: trafficFixtureTile(Number(road[1])),
};
}
/** Intercept provider URLs only; Cesium worker/module loading stays untouched. */
export async function installTrafficRoutes(
page,
{
origin,
fixtures = false,
keyless = false,
onFlow = () => {},
onError = () => {},
},
) {
const session = await page.createCDPSession();
const patterns = [
`${origin}/api/tomtom/status*`,
`${origin}/api/tomtom/flow/*`,
...(fixtures
? ['https://tiles.openfreemap.org/*', 'https://terrain.reearth.land/*']
: []),
].map((urlPattern) => ({ urlPattern, requestStage: 'Request' }));
session.on('Fetch.requestPaused', async ({ requestId, request }) => {
try {
const url = new URL(request.url);
let response;
if (keyless && url.pathname === '/api/tomtom/status') {
response = json({ hasKey: false });
} else if (keyless && url.pathname.startsWith('/api/tomtom/flow/')) {
onFlow(request.url);
response = { ...json({ error: 'no_key' }), status: 503 };
} else if (fixtures) {
response = trafficFixtureResponse({ url: () => request.url });
}
if (!response) {
await session.send('Fetch.continueRequest', { requestId });
return;
}
await session.send('Fetch.fulfillRequest', {
requestId,
responseCode: response.status,
responseHeaders: Object.entries({
'content-type': response.contentType,
...response.headers,
}).map(([name, value]) => ({ name, value })),
body: Buffer.from(response.body).toString('base64'),
});
} catch (error) {
if (page.isClosed()) return;
onError(error);
await session
.send('Fetch.failRequest', { requestId, errorReason: 'Failed' })
.catch(() => {});
}
});
await session.send('Fetch.enable', { patterns });
return session;
}