Add browser debugging support
This commit is contained in:
@@ -1,58 +1,128 @@
|
||||
import { spawn } from 'node:child_process';
|
||||
import { chromium } from 'playwright';
|
||||
|
||||
const targetUrl = process.env.VERIFY_URL ?? 'http://localhost:5173/';
|
||||
|
||||
const browser = await chromium.launch({ headless: true });
|
||||
const page = await browser.newPage({ viewport: { width: 1280, height: 720 } });
|
||||
let serverProcess;
|
||||
let browser;
|
||||
|
||||
await page.goto(targetUrl, { waitUntil: 'networkidle' });
|
||||
await page.waitForSelector('canvas');
|
||||
await page.waitForFunction(() => window.__HEROS_GAME__ !== undefined);
|
||||
await page.waitForTimeout(500);
|
||||
try {
|
||||
serverProcess = await ensureLocalServer(targetUrl);
|
||||
|
||||
await page.mouse.click(962, 240);
|
||||
await page.waitForTimeout(250);
|
||||
browser = await chromium.launch({ headless: true });
|
||||
const page = await browser.newPage({ viewport: { width: 1280, height: 720 } });
|
||||
|
||||
for (let i = 0; i < 20; i += 1) {
|
||||
const isBattleActive = await page.evaluate(() => {
|
||||
await page.goto(targetUrl, { waitUntil: 'networkidle' });
|
||||
await page.waitForSelector('canvas');
|
||||
await page.waitForFunction(() => window.__HEROS_GAME__ !== undefined);
|
||||
await page.waitForFunction(() => window.__HEROS_DEBUG__ !== undefined);
|
||||
await page.waitForTimeout(500);
|
||||
|
||||
const debugBeforeBattle = await page.evaluate(() => window.__HEROS_DEBUG__?.activeScenes() ?? []);
|
||||
if (!debugBeforeBattle.includes('TitleScene')) {
|
||||
throw new Error(`Expected TitleScene before starting. Active scenes: ${debugBeforeBattle.join(', ')}`);
|
||||
}
|
||||
|
||||
await page.mouse.click(962, 240);
|
||||
await page.waitForTimeout(250);
|
||||
|
||||
for (let i = 0; i < 20; i += 1) {
|
||||
const isBattleActive = await page.evaluate(() => {
|
||||
const activeScenes = window.__HEROS_GAME__?.scene.getScenes(true) ?? [];
|
||||
return activeScenes.some((scene) => scene.scene.key === 'BattleScene');
|
||||
});
|
||||
|
||||
if (isBattleActive) {
|
||||
break;
|
||||
}
|
||||
|
||||
await page.keyboard.press('Space');
|
||||
await page.waitForTimeout(220);
|
||||
}
|
||||
|
||||
await page.waitForFunction(() => {
|
||||
const activeScenes = window.__HEROS_GAME__?.scene.getScenes(true) ?? [];
|
||||
return activeScenes.some((scene) => scene.scene.key === 'BattleScene');
|
||||
});
|
||||
|
||||
if (isBattleActive) {
|
||||
break;
|
||||
await page.keyboard.press('F9');
|
||||
await page.waitForTimeout(100);
|
||||
await page.screenshot({ path: 'dist/verification-battle.png', fullPage: true });
|
||||
|
||||
const result = await page.evaluate(() => {
|
||||
const canvas = document.querySelector('canvas');
|
||||
const activeScenes = window.__HEROS_DEBUG__?.activeScenes() ?? [];
|
||||
const battleState = window.__HEROS_DEBUG__?.battle();
|
||||
|
||||
return {
|
||||
activeScenes,
|
||||
battleState,
|
||||
canvasWidth: canvas?.width ?? 0,
|
||||
canvasHeight: canvas?.height ?? 0
|
||||
};
|
||||
});
|
||||
|
||||
if (result.canvasWidth !== 1280 || result.canvasHeight !== 720) {
|
||||
throw new Error(`Unexpected canvas size: ${result.canvasWidth}x${result.canvasHeight}`);
|
||||
}
|
||||
|
||||
await page.keyboard.press('Space');
|
||||
await page.waitForTimeout(220);
|
||||
if (!result.activeScenes.includes('BattleScene')) {
|
||||
throw new Error(`BattleScene was not active. Active scenes: ${result.activeScenes.join(', ')}`);
|
||||
}
|
||||
|
||||
if (!result.battleState || result.battleState.scene !== 'BattleScene') {
|
||||
throw new Error(`Debug battle state was not available: ${JSON.stringify(result.battleState)}`);
|
||||
}
|
||||
|
||||
console.log(`Verified title-to-battle flow and debug API at ${targetUrl}`);
|
||||
} finally {
|
||||
await browser?.close();
|
||||
if (serverProcess && !serverProcess.killed) {
|
||||
serverProcess.kill();
|
||||
}
|
||||
}
|
||||
|
||||
await page.waitForFunction(() => {
|
||||
const activeScenes = window.__HEROS_GAME__?.scene.getScenes(true) ?? [];
|
||||
return activeScenes.some((scene) => scene.scene.key === 'BattleScene');
|
||||
});
|
||||
async function ensureLocalServer(url) {
|
||||
if (await canReach(url)) {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
await page.screenshot({ path: 'dist/verification-battle.png', fullPage: true });
|
||||
const parsed = new URL(url);
|
||||
const isLocal = ['localhost', '127.0.0.1', '0.0.0.0'].includes(parsed.hostname);
|
||||
if (!isLocal) {
|
||||
throw new Error(`No server responded at ${url}`);
|
||||
}
|
||||
|
||||
const result = await page.evaluate(() => {
|
||||
const canvas = document.querySelector('canvas');
|
||||
const activeScenes = window.__HEROS_GAME__?.scene.getScenes(true).map((scene) => scene.scene.key) ?? [];
|
||||
const stderr = [];
|
||||
const child = spawn(process.execPath, ['node_modules/vite/bin/vite.js', '--host', '127.0.0.1', '--port', parsed.port || '5173'], {
|
||||
cwd: process.cwd(),
|
||||
env: process.env,
|
||||
stdio: ['ignore', 'pipe', 'pipe']
|
||||
});
|
||||
|
||||
return {
|
||||
activeScenes,
|
||||
canvasWidth: canvas?.width ?? 0,
|
||||
canvasHeight: canvas?.height ?? 0
|
||||
};
|
||||
});
|
||||
child.stderr.on('data', (chunk) => stderr.push(chunk.toString()));
|
||||
child.stdout.on('data', () => {});
|
||||
|
||||
await browser.close();
|
||||
for (let i = 0; i < 80; i += 1) {
|
||||
if (await canReach(url)) {
|
||||
return child;
|
||||
}
|
||||
await delay(250);
|
||||
}
|
||||
|
||||
if (result.canvasWidth !== 1280 || result.canvasHeight !== 720) {
|
||||
throw new Error(`Unexpected canvas size: ${result.canvasWidth}x${result.canvasHeight}`);
|
||||
child.kill();
|
||||
throw new Error(`Vite server did not start at ${url}\n${stderr.join('')}`);
|
||||
}
|
||||
|
||||
if (!result.activeScenes.includes('BattleScene')) {
|
||||
throw new Error(`BattleScene was not active. Active scenes: ${result.activeScenes.join(', ')}`);
|
||||
async function canReach(url) {
|
||||
try {
|
||||
const response = await fetch(url, { signal: AbortSignal.timeout(1000) });
|
||||
return response.ok;
|
||||
} catch {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
console.log(`Verified title-to-battle flow at ${targetUrl}`);
|
||||
function delay(ms) {
|
||||
return new Promise((resolve) => setTimeout(resolve, ms));
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user