mirror of
https://github.com/bilawalsidhu/gods-eye-view.git
synced 2026-11-04 10:24:02 +00:00
test: restore minimized Transit windows before screenshots
This commit is contained in:
1 parent
72f1625257
commit
56be69d065
6 files changed
+101
-15
No files matched your search
@@ -4,3 +4,4 @@
|
|||||||
- Bound the Transit card-anchor probe by observed poll coverage instead of a fixed 20-second window (asturksever, #1282).
|
- Bound the Transit card-anchor probe by observed poll coverage instead of a fixed 20-second window (asturksever, #1282).
|
||||||
- Keep visible-page Transit probes focused through the browser testing API (asturksever, #1282).
|
- Keep visible-page Transit probes focused through the browser testing API (asturksever, #1282).
|
||||||
- Add a real-browser regression gate for hidden-tab periodic work, explicit refresh, resume and teardown (asturksever, #1282).
|
- Add a real-browser regression gate for hidden-tab periodic work, explicit refresh, resume and teardown (asturksever, #1282).
|
||||||
|
- Restore minimized test windows before screenshots so native compositor pauses cannot stall browser acceptance (asturksever, #1282).
|
||||||
@@ -18,3 +18,30 @@ export function chromeExecutablePath({
|
|||||||
if (env.PUPPETEER_EXECUTABLE_PATH) return env.PUPPETEER_EXECUTABLE_PATH;
|
if (env.PUPPETEER_EXECUTABLE_PATH) return env.PUPPETEER_EXECUTABLE_PATH;
|
||||||
return exists(MACOS_CHROME) ? MACOS_CHROME : undefined;
|
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);
|
||||||
|
}
|
||||||
@@ -1,6 +1,6 @@
|
|||||||
/** Camera-jump regression against an existing server; never starts a server. */
|
/** Camera-jump regression against an existing server; never starts a server. */
|
||||||
import puppeteer from 'puppeteer';
|
import puppeteer from 'puppeteer';
|
||||||
import { chromeExecutablePath } from './qa-chrome.mjs';
|
import { chromeExecutablePath, captureQaScreenshot } from './qa-chrome.mjs';
|
||||||
import { mkdir, writeFile } from 'node:fs/promises';
|
import { mkdir, writeFile } from 'node:fs/promises';
|
||||||
import { reduceTrailPixels } from '../src/layers/transit/qaMetrics.js';
|
import { reduceTrailPixels } from '../src/layers/transit/qaMetrics.js';
|
||||||
|
|
||||||
@@ -307,7 +307,7 @@ try {
|
|||||||
result.pixelPass = pixels.pass;
|
result.pixelPass = pixels.pass;
|
||||||
result.pixelDetails = pixels;
|
result.pixelDetails = pixels;
|
||||||
result.errors = errors;
|
result.errors = errors;
|
||||||
await page.screenshot({ path: `${shots}/recovery.png` });
|
await captureQaScreenshot(page, { path: `${shots}/recovery.png` });
|
||||||
await writeFile(`${shots}/recovery.json`, JSON.stringify(result, null, 2));
|
await writeFile(`${shots}/recovery.json`, JSON.stringify(result, null, 2));
|
||||||
for (const key of ['on', 'off', 'onAgain', 'offAgain']) delete result[key];
|
for (const key of ['on', 'off', 'onAgain', 'offAgain']) delete result[key];
|
||||||
const pass =
|
const pass =
|
||||||
|
|||||||
@@ -1,3 +1,4 @@
|
|||||||
|
import { captureQaScreenshot } from './qa-chrome.mjs';
|
||||||
import { getRegisteredTransitFeed } from '../src/data/transitFeeds.js';
|
import { getRegisteredTransitFeed } from '../src/data/transitFeeds.js';
|
||||||
|
|
||||||
// Not registered or active: camera discovery and live polls never own this feed.
|
// Not registered or active: camera discovery and live polls never own this feed.
|
||||||
@@ -219,7 +220,7 @@ export async function runFleetBudgets({
|
|||||||
allocations.layerFrameBytes / allocationTrace.rows.length <= 8192,
|
allocations.layerFrameBytes / allocationTrace.rows.length <= 8192,
|
||||||
`${allocations.layerFrameBytes / allocationTrace.rows.length} transit-authored bytes/frame; whole frame ${allocations.frameBytes / allocationTrace.rows.length}; top three ${JSON.stringify(details.topAllocatorsPerFrame)}; collected objects included. Full profile saved.`,
|
`${allocations.layerFrameBytes / allocationTrace.rows.length} transit-authored bytes/frame; whole frame ${allocations.frameBytes / allocationTrace.rows.length}; top three ${JSON.stringify(details.topAllocatorsPerFrame)}; collected objects included. Full profile saved.`,
|
||||||
);
|
);
|
||||||
await page.screenshot({
|
await captureQaScreenshot(page, {
|
||||||
path: `${shots}/${tag}-fleet-${count}.jpg`,
|
path: `${shots}/${tag}-fleet-${count}.jpg`,
|
||||||
type: 'jpeg',
|
type: 'jpeg',
|
||||||
quality: 85,
|
quality: 85,
|
||||||
@@ -392,7 +393,7 @@ export async function runBostonMatrix({
|
|||||||
JSON.stringify({ pixels, contrast }),
|
JSON.stringify({ pixels, contrast }),
|
||||||
{ unexercised: pixels.length < 6 },
|
{ unexercised: pixels.length < 6 },
|
||||||
);
|
);
|
||||||
await page.screenshot({
|
await captureQaScreenshot(page, {
|
||||||
path: `${shots}/${tag}-matrix-${background.name}-${look.name}-fleet.jpg`,
|
path: `${shots}/${tag}-matrix-${background.name}-${look.name}-fleet.jpg`,
|
||||||
type: 'jpeg',
|
type: 'jpeg',
|
||||||
quality: 90,
|
quality: 90,
|
||||||
@@ -407,7 +408,7 @@ export async function runBostonMatrix({
|
|||||||
target.key,
|
target.key,
|
||||||
);
|
);
|
||||||
await wait(500);
|
await wait(500);
|
||||||
await page.screenshot({
|
await captureQaScreenshot(page, {
|
||||||
path: `${shots}/${tag}-matrix-${background.name}-${look.name}-${target.route}-selected.jpg`,
|
path: `${shots}/${tag}-matrix-${background.name}-${look.name}-${target.route}-selected.jpg`,
|
||||||
type: 'jpeg',
|
type: 'jpeg',
|
||||||
quality: 90,
|
quality: 90,
|
||||||
@@ -431,7 +432,7 @@ export async function runBostonMatrix({
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
await wait(300);
|
await wait(300);
|
||||||
await page.screenshot({
|
await captureQaScreenshot(page, {
|
||||||
path: `${shots}/${tag}-matrix-${background.name}-${look.name}-restored.jpg`,
|
path: `${shots}/${tag}-matrix-${background.name}-${look.name}-restored.jpg`,
|
||||||
type: 'jpeg',
|
type: 'jpeg',
|
||||||
quality: 90,
|
quality: 90,
|
||||||
@@ -579,7 +580,7 @@ export async function runBostonLive({
|
|||||||
JSON.stringify(selection),
|
JSON.stringify(selection),
|
||||||
{ unexercised: !target },
|
{ unexercised: !target },
|
||||||
);
|
);
|
||||||
await page.screenshot({
|
await captureQaScreenshot(page, {
|
||||||
path: `${shots}/${tag}-boston-live-${view.name}.jpg`,
|
path: `${shots}/${tag}-boston-live-${view.name}.jpg`,
|
||||||
type: 'jpeg',
|
type: 'jpeg',
|
||||||
quality: 90,
|
quality: 90,
|
||||||
@@ -1010,7 +1011,7 @@ export async function runTrailVisibility({
|
|||||||
stable: pixels.stable[i],
|
stable: pixels.stable[i],
|
||||||
eligible: pixels.eligible[i],
|
eligible: pixels.eligible[i],
|
||||||
}));
|
}));
|
||||||
await page.screenshot({
|
await captureQaScreenshot(page, {
|
||||||
path: `${shots}/${tag}-${altitude}m-trail-visible.jpg`,
|
path: `${shots}/${tag}-${altitude}m-trail-visible.jpg`,
|
||||||
type: 'jpeg',
|
type: 'jpeg',
|
||||||
quality: 95,
|
quality: 95,
|
||||||
|
|||||||
@@ -36,7 +36,7 @@ import {
|
|||||||
*/
|
*/
|
||||||
import { mkdir, readFile, writeFile } from 'node:fs/promises';
|
import { mkdir, readFile, writeFile } from 'node:fs/promises';
|
||||||
import puppeteer from 'puppeteer';
|
import puppeteer from 'puppeteer';
|
||||||
import { chromeExecutablePath } from './qa-chrome.mjs';
|
import { chromeExecutablePath, captureQaScreenshot } from './qa-chrome.mjs';
|
||||||
import { createTransitHistory } from '../server/providers/transitHistory.js';
|
import { createTransitHistory } from '../server/providers/transitHistory.js';
|
||||||
import { DETECTION_THEME_MAP } from '../src/overlays/worldOverlayTokens.js';
|
import { DETECTION_THEME_MAP } from '../src/overlays/worldOverlayTokens.js';
|
||||||
import { transitModeTier } from '../src/data/transitPresetStyle.js';
|
import { transitModeTier } from '../src/data/transitPresetStyle.js';
|
||||||
@@ -294,11 +294,13 @@ page.on('request', (request) => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
const shot = (name, caption) =>
|
const shot = (name, caption) =>
|
||||||
page
|
captureQaScreenshot(page, {
|
||||||
.screenshot({ path: `${SHOTS}/${name}`, type: 'jpeg', quality: 82 })
|
path: `${SHOTS}/${name}`,
|
||||||
.then(() => {
|
type: 'jpeg',
|
||||||
console.log(` shot ${name} — ${caption}`);
|
quality: 82,
|
||||||
});
|
}).then(() => {
|
||||||
|
console.log(` shot ${name} — ${caption}`);
|
||||||
|
});
|
||||||
|
|
||||||
const view = (city) =>
|
const view = (city) =>
|
||||||
`${BASE}/?welcome=0#lat=${city.lat}&lon=${city.lon}&alt=600&heading=${city.heading}&pitch=-45`;
|
`${BASE}/?welcome=0#lat=${city.lat}&lon=${city.lon}&alt=600&heading=${city.heading}&pitch=-45`;
|
||||||
|
|||||||
+56
-1
@@ -1,6 +1,10 @@
|
|||||||
import assert from 'node:assert/strict';
|
import assert from 'node:assert/strict';
|
||||||
import test from 'node:test';
|
import test from 'node:test';
|
||||||
import { MACOS_CHROME, chromeExecutablePath } from '../scripts/qa-chrome.mjs';
|
import {
|
||||||
|
MACOS_CHROME,
|
||||||
|
chromeExecutablePath,
|
||||||
|
captureQaScreenshot,
|
||||||
|
} from '../scripts/qa-chrome.mjs';
|
||||||
|
|
||||||
test('gates keep macOS Chrome where it is installed', () => {
|
test('gates keep macOS Chrome where it is installed', () => {
|
||||||
assert.equal(
|
assert.equal(
|
||||||
@@ -25,3 +29,54 @@ test('an explicit executable path wins', () => {
|
|||||||
'C:\\Chrome\\chrome.exe',
|
'C:\\Chrome\\chrome.exe',
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
test('screenshots restore minimized test windows before capture and detach their session', async () => {
|
||||||
|
const calls = [];
|
||||||
|
const session = {
|
||||||
|
send: async (method, params) => {
|
||||||
|
calls.push([method, params]);
|
||||||
|
return { windowId: 7, bounds: { windowState: 'minimized' } };
|
||||||
|
},
|
||||||
|
detach: async () => calls.push(['detach']),
|
||||||
|
};
|
||||||
|
const page = {
|
||||||
|
createCDPSession: async () => session,
|
||||||
|
bringToFront: async () => calls.push(['front']),
|
||||||
|
screenshot: async (options) => {
|
||||||
|
calls.push(['capture', options]);
|
||||||
|
return 'pixels';
|
||||||
|
},
|
||||||
|
};
|
||||||
|
assert.equal(
|
||||||
|
await captureQaScreenshot(page, { path: 'proof.png' }),
|
||||||
|
'pixels',
|
||||||
|
);
|
||||||
|
assert.deepEqual(
|
||||||
|
calls.map((c) => c[0]),
|
||||||
|
[
|
||||||
|
'Browser.getWindowForTarget',
|
||||||
|
'Browser.setWindowBounds',
|
||||||
|
'front',
|
||||||
|
'detach',
|
||||||
|
'capture',
|
||||||
|
],
|
||||||
|
);
|
||||||
|
assert.deepEqual(calls[1][1], {
|
||||||
|
windowId: 7,
|
||||||
|
bounds: { windowState: 'normal' },
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
test('headless capture does not manipulate a native window', async () => {
|
||||||
|
const options = { path: 'proof.png' };
|
||||||
|
const page = {
|
||||||
|
screenshot: async (supplied) => {
|
||||||
|
assert.equal(supplied, options);
|
||||||
|
return 'pixels';
|
||||||
|
},
|
||||||
|
};
|
||||||
|
assert.equal(
|
||||||
|
await captureQaScreenshot(page, options, { headful: false }),
|
||||||
|
'pixels',
|
||||||
|
);
|
||||||
|
});
|
||||||
Reference in new issue
Block a user