// Decode screenshots in headless chromium and verify expected pixel signatures. 'use strict'; import { createRequire } from 'node:module'; import { readFileSync } from 'node:fs'; const require = createRequire('/root/kidcraft/node_modules/'); const { chromium } = require('playwright-core'); const EXE = '/root/.cache/ms-playwright/chromium_headless_shell-1234/chrome-headless-shell-linux64/chrome-headless-shell'; let failures = 0; const ok = (c, l) => { console.log(`${c ? 'PASS' : 'FAIL'} ${l}`); if (!c) failures++; }; async function stats(page, path, x0, y0, x1, y1) { const b64 = readFileSync(path).toString('base64'); return await page.evaluate(async ({ b64, x0, y0, x1, y1 }) => { const img = new Image(); img.src = 'data:image/png;base64,' + b64; await new Promise(r => { img.onload = r; }); const cv = document.createElement('canvas'); cv.width = img.width; cv.height = img.height; const cx = cv.getContext('2d'); cx.drawImage(img, 0, 0); const d = cx.getImageData(x0, y0, x1 - x0, y1 - y0).data; let blue = 0, green = 0, tan = 0, red = 0, dark = 0, n = 0; for (let i = 0; i < d.length; i += 4) { const [r, g, b] = [d[i], d[i + 1], d[i + 2]]; n++; if (b > r + 20 && b > g + 10) blue++; else if (g > r + 15 && g > b + 15) green++; else if (r > 150 && g > 130 && b < g) tan++; else if (r > 140 && r > g + 50 && r > b + 50) red++; if (r + g + b < 120) dark++; } return { w: img.width, h: img.height, frac: { blue: blue / n, green: green / n, tan: tan / n, red: red / n, dark: dark / n } }; }, { b64, x0, y0, x1, y1 }); } const browser = await chromium.launch({ executablePath: EXE, args: ['--no-sandbox'] }); const page = await browser.newPage(); await page.goto('about:blank'); // ---- menu ---- const menu = await stats(page, '/tmp/shot-menu.png', 0, 0, 1280, 800); ok(menu.w === 1280 && menu.h === 800, `menu screenshot size ${menu.w}x${menu.h}`); ok(menu.frac.dark < 0.98, 'menu is not a black screen'); // ---- gameplay full frame ---- const game = await stats(page, '/tmp/shot-game-a.png', 0, 0, 1280, 800); ok(game.frac.blue > 0.05 || game.frac.green > 0.05, `island terrain painted (blue ${game.frac.blue.toFixed(2)}, green ${game.frac.green.toFixed(2)})`); // bottom-left vitals region should contain red-ish HP fill const vitals = await stats(page, '/tmp/shot-game-a.png', 16, 800 - 160, 256, 790); ok(vitals.frac.red > 0.02, `HP bar red present (${vitals.frac.red.toFixed(3)})`); // top-right minimap region not empty const mm = await stats(page, '/tmp/shot-game-a.png', 1116, 14, 1266, 178); ok(mm.frac.dark < 0.95 && (mm.frac.blue > 0.03 || mm.frac.green > 0.03), 'minimap rendered island'); await browser.close(); console.log(failures === 0 ? '\nPIXEL CHECKS PASSED' : `\n${failures} PIXEL CHECK(S) FAILED`); process.exit(failures ? 1 : 0);