← back to 90210 Agentabrams

tests/e2e.mjs

53 lines

// Headless E2E for the 90210 topic hub. Spins a static server (fetch of
// games.json fails on file://), loads the hub, and checks the four Beverly
// Hills games render + play + deep-link, with zero console/page errors.
import { createRequire } from 'module';
import { fileURLToPath } from 'url';
import path from 'path'; import http from 'http'; import fs from 'fs';
const require = createRequire(import.meta.url);
let chromium;
try { ({ chromium } = require('/Users/macstudio3/.npm-global/lib/node_modules/playwright')); }
catch { ({ chromium } = require('playwright')); }
const root = path.dirname(path.dirname(fileURLToPath(import.meta.url)));
const MIME = { '.html':'text/html', '.json':'application/json', '.js':'text/javascript', '.aa':'text/html' };
const server = http.createServer((req,res)=>{
  let p = decodeURIComponent(req.url.split('?')[0].split('#')[0]); if(p.endsWith('/')) p+='index.html';
  const f = path.join(root,p);
  if(!f.startsWith(root)||!fs.existsSync(f)||fs.statSync(f).isDirectory()){ res.writeHead(404); res.end('nf'); return; }
  res.writeHead(200,{'Content-Type':MIME[path.extname(f)]||'text/plain'}); fs.createReadStream(f).pipe(res);
});
await new Promise(r=>server.listen(0,'127.0.0.1',r));
const url = `http://127.0.0.1:${server.address().port}/`;
const browser = await chromium.launch();
const page = await browser.newPage({ viewport:{width:1200,height:800} });
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 results=[]; const check=(n,ok)=>{ results.push(ok); console.log((ok?'PASS':'FAIL')+'  '+n); };

await page.goto(url);
await page.locator('#heroEnter').click().catch(()=>{});          // dismiss splash
await page.waitForSelector('.game');
const names = await page.locator('.game .fname').allTextContents();
check('four games render', (await page.locator('.game').count()) === 4);
check('PinkPalaceSlots.aa listed', names.includes('PinkPalaceSlots.aa'));
check('a game auto-selected', (await page.locator('.game.active').count()) === 1);

await page.goto(url + '#beverly-hills-slots');
await page.waitForSelector('.game.active');
const frame = page.frameLocator('#frame');
await frame.locator('#spinBtn').waitFor({ timeout: 15000 });
check('slots iframe loads via deep-link', await frame.locator('#spinBtn').isVisible());

await page.goto(url + '#rodeo-runner');
await page.waitForSelector('.game.active');
await page.frameLocator('#frame').locator('#startBtn').waitFor({ timeout: 15000 });
check('runner iframe loads via deep-link', true);

await page.screenshot({ path: path.join(root,'tests','screenshot.png') });
check('no console/page errors', errors.length===0);
if(errors.length) console.log(errors.join('\n'));
await browser.close(); server.close();
const failed = results.filter(x=>!x).length;
console.log(`\n${results.length-failed}/${results.length} passed`);
process.exit(failed?1:0);