import { readdirSync, readFileSync } from 'node:fs'; import { desktopBrowserContextOptions, desktopBrowserDeviceScaleFactor, desktopBrowserViewport, desktopBrowserViewportBounds, desktopBrowserViewportLabel } from './desktop-browser-viewport.mjs'; const expectedViewport = { width: 1920, height: 1080 }; const expectedBounds = { x: 0, y: 0, ...expectedViewport }; const errors = []; assertJsonEqual(desktopBrowserViewport, expectedViewport, 'central desktop browser viewport'); assertJsonEqual(desktopBrowserViewportBounds, expectedBounds, 'central desktop browser viewport bounds'); assertJsonEqual( desktopBrowserContextOptions, { viewport: expectedViewport, deviceScaleFactor: 1 }, 'central desktop browser context options' ); assert(desktopBrowserDeviceScaleFactor === 1, 'desktop browser device scale factor must be 1'); assert(desktopBrowserViewportLabel === '1920x1080', 'desktop browser viewport label must be 1920x1080'); const mainSource = readFileSync('src/main.ts', 'utf8'); assert(/width:\s*1920\s*,[\s\S]*?height:\s*1080\s*,/.test(mainSource), 'Phaser game config must remain 1920x1080'); const policySource = readFileSync('AGENTS.md', 'utf8'); assert(policySource.includes('1920x1080 CSS viewport at 100% browser zoom'), 'AGENTS.md must define the 1920x1080 browser QA baseline'); assert(policySource.includes("Never rely on an in-app browser's ambient/default viewport"), 'AGENTS.md must prohibit ambient browser viewport use'); const automatedBrowserChecks = readdirSync('scripts', { withFileTypes: true }) .filter((entry) => entry.isFile() && entry.name.endsWith('.mjs')) .map((entry) => `scripts/${entry.name}`) .filter((scriptPath) => { const source = readFileSync(scriptPath, 'utf8'); return source.includes("from 'playwright'") && /\b(?:newPage|newContext)\s*\(/.test(source); }) .sort(); assert(automatedBrowserChecks.length > 0, 'at least one automated browser check must be discovered'); for (const scriptPath of automatedBrowserChecks) { const source = readFileSync(scriptPath, 'utf8'); assert(source.includes("from './desktop-browser-viewport.mjs'"), `${scriptPath} must import the shared browser viewport`); assert( /\b(?:newPage|newContext)\(desktopBrowserContextOptions\)/.test(source), `${scriptPath} must explicitly create its primary browser page or context with the shared FHD context options` ); assert( !/viewport:\s*\{\s*width:\s*1920\s*,\s*height:\s*1080\s*\}/.test(source), `${scriptPath} must not duplicate the primary 1920x1080 viewport inline` ); } if (errors.length > 0) { throw new Error(`Desktop browser viewport verification failed:\n- ${errors.join('\n- ')}`); } console.log( `Verified ${desktopBrowserViewportLabel} desktop browser baseline at DPR ${desktopBrowserDeviceScaleFactor} across ${automatedBrowserChecks.length} browser checks.` ); function assert(condition, message) { if (!condition) { errors.push(message); } } function assertJsonEqual(actual, expected, label) { assert(JSON.stringify(actual) === JSON.stringify(expected), `${label} must be ${JSON.stringify(expected)}; received ${JSON.stringify(actual)}`); }