race / test_runtime.js
Code-Gen's picture
Upload 17 files
33d96a3 verified
Raw History Blame
3.29 kB
// Runtime smoke test: load the real game in headless Chromium and drive it.
const puppeteer = require('puppeteer');
const path = require('path');
(async () => {
const browser = await puppeteer.launch({
headless: 'new',
args: ['--no-sandbox', '--disable-setuid-sandbox', '--use-gl=swiftshader',
'--enable-unsafe-swiftshader', '--disable-gpu-sandbox'],
});
const page = await browser.newPage();
await page.setViewport({ width: 1280, height: 720 });
const errors = [];
page.on('pageerror', e => errors.push('PAGEERROR: ' + e.message));
page.on('console', m => { if (m.type() === 'error') errors.push('CONSOLE: ' + m.text()); });
const url = 'file://' + path.resolve(__dirname, 'index.html');
await page.goto(url, { waitUntil: 'networkidle2', timeout: 60000 });
await new Promise(r => setTimeout(r, 1500));
// basic state
let st = await page.evaluate(() => ({
hasG: typeof G !== 'undefined',
state: G.state,
three: typeof THREE !== 'undefined',
cars: G.cars ? G.cars.length : 0,
}));
console.log('BOOT:', JSON.stringify(st));
// start race
await page.evaluate(() => startRace());
await new Promise(r => setTimeout(r, 500));
st = await page.evaluate(() => ({ state: G.state, raceTime: G.raceTime.toFixed(2) }));
console.log('AFTER START:', JSON.stringify(st));
// hold gas + steer a bit for ~6 simulated seconds
await page.keyboard.down('ArrowUp');
await new Promise(r => setTimeout(r, 3000));
await page.keyboard.down('ArrowLeft');
await new Promise(r => setTimeout(r, 1500));
await page.keyboard.up('ArrowLeft');
// use nitro briefly
await page.keyboard.down('Shift');
await new Promise(r => setTimeout(r, 1200));
await page.keyboard.up('Shift');
await new Promise(r => setTimeout(r, 1500));
st = await page.evaluate(() => {
const p = G.player;
return {
state: G.state,
raceTime: +G.raceTime.toFixed(1),
speed: +(Math.hypot(p.vx, p.vz) * 3.6).toFixed(0),
lap: p.lap, s: Math.round(p.s), x: +p.x.toFixed(1), z: +p.z.toFixed(1),
nitro: +p.nitro.toFixed(2),
aiSpeeds: G.cars.filter(c => !c.isPlayer).map(a => +(a.v * 3.6).toFixed(0)),
rank: getRank(),
hudSpeed: document.getElementById('speed').textContent,
};
});
console.log('AFTER DRIVING:', JSON.stringify(st));
await page.keyboard.up('ArrowUp');
// run 20 more seconds idle (AI keeps going), check laps progress & no NaN
await new Promise(r => setTimeout(r, 20000));
st = await page.evaluate(() => {
const p = G.player;
const bad = [p.x, p.z, p.vx, p.vz, p.heading].some(v => !isFinite(v));
return {
raceTime: +G.raceTime.toFixed(1),
aiLaps: G.cars.filter(c => !c.isPlayer).map(a => a.lap),
playerPos: [ +p.x.toFixed(0), +p.z.toFixed(0) ],
anyNaN: bad,
cam: [ +camera.position.x.toFixed(0), +camera.position.y.toFixed(0), +camera.position.z.toFixed(0) ],
};
});
console.log('AFTER 20s IDLE:', JSON.stringify(st));
await page.screenshot({ path: 'shot_menu_race.png' });
console.log('ERRORS(' + errors.length + '):');
errors.slice(0, 20).forEach(e => console.log(' ' + e));
await browser.close();
process.exit(errors.length ? 1 : 0);
})().catch(e => { console.error('FATAL', e); process.exit(2); });