test(browser): isolate and await the real zoom extension

This commit is contained in:
cesnimda
2026-10-29 07:35:56 +01:00
parent 3255da9fc6
commit 5add159156
4 changed files with 27 additions and 5 deletions
+12 -5
View File
@@ -1,5 +1,7 @@
import { expect, test, type APIRequestContext, type Page } from '@playwright/test';
import fs from 'node:fs/promises';
import os from 'node:os';
import path from 'node:path';
import { translations } from '../src/i18n/translations';
const apiUrl = 'http://localhost:5302/api';
@@ -48,7 +50,9 @@ async function geometry(page: Page) {
for (const [language, mode] of [['en', 'light'], ['nb', 'dark']] as const) {
test(`[P5-15-02 E08 C06] actual browser zoom ${language}/${mode}: collect 100/200/400 percent reflow without changing document geometry`, async ({ playwright }, info) => {
test.setTimeout(240_000);
const extension = info.outputPath('local-zoom-extension');
// Keep Chromium's runtime paths short in deep worktrees and repeat-run output folders.
const runtime = await fs.mkdtemp(path.join(os.tmpdir(), 'jt-zoom-'));
const extension = path.join(runtime, 'extension');
await fs.mkdir(extension, { recursive: true });
await fs.writeFile(`${extension}/manifest.json`, JSON.stringify({
manifest_version: 3, name: 'Local audit browser zoom', version: '1.0',
@@ -56,21 +60,23 @@ for (const [language, mode] of [['en', 'light'], ['nb', 'dark']] as const) {
background: { service_worker: 'background.js' },
}));
await fs.writeFile(`${extension}/background.js`, 'globalThis.auditZoomReady = true;');
const context = await playwright.chromium.launchPersistentContext(info.outputPath('local-browser-profile'), {
const context = await playwright.chromium.launchPersistentContext(path.join(runtime, 'profile'), {
channel: 'chromium', headless: true, viewport: null, deviceScaleFactor: undefined,
// The bundled browser otherwise disables the extension that owns real tab zoom.
ignoreDefaultArgs: ['--disable-extensions'],
args: ['--window-size=1280,900', `--disable-extensions-except=${extension}`, `--load-extension=${extension}`],
});
}).catch(async error => { await fs.rm(runtime, { recursive: true, force: true }); throw error; });
const admin = await playwright.request.newContext();
let adminHeaders: Record<string, string> | undefined;
let createdAdminId: string | undefined;
const records: unknown[] = [];
try {
const worker = context.serviceWorkers()[0] || await context.waitForEvent('serviceworker');
expect(await worker.evaluate(() => (globalThis as unknown as { auditZoomReady: boolean }).auditZoomReady)).toBe(true);
await context.route('**/*', route => {
const url = new URL(route.request().url());
return ['localhost', '127.0.0.1'].includes(url.hostname) || ['data:', 'blob:', 'about:'].includes(url.protocol) ? route.continue() : route.abort();
// The generated local extension must finish loading and may restart its own worker.
return url.href === worker.url() || ['localhost', '127.0.0.1'].includes(url.hostname) || ['data:', 'blob:', 'about:'].includes(url.protocol) ? route.continue() : route.abort();
});
await context.addInitScript(({ language, mode }) => {
localStorage.setItem('uiLanguage', language);
@@ -165,7 +171,8 @@ for (const [language, mode] of [['en', 'light'], ['nb', 'dark']] as const) {
} finally {
await info.attach('actual-browser-zoom-observations', { body: JSON.stringify({ method: 'chrome.tabs.setZoom; viewport:null; dpr and actual zoom asserted; not human acceptance', browser: context.browser()?.version(), records }, null, 2), contentType: 'application/json' });
await admin.dispose();
await context.close();
try { await context.close(); }
finally { await fs.rm(runtime, { recursive: true, force: true }); }
}
}
});