Single-file ink-painting wuxia sect-survival RPG. Lead a sect through 100 days: martial arts combos, cultivation, tactical combat, faction war, chronicle endings. - src/ 13 modules (data, sim, combat, render, UI, app shell) - wuxia.html self-contained build (no dependencies) - tools/build.js bundler - tests: headless 100-day sims + jsdom UI smoke + real-browser Chromium click-through (playwright)
53 lines
2.4 KiB
JavaScript
53 lines
2.4 KiB
JavaScript
#!/usr/bin/env node
|
|
/* Real-browser repro: loads the game in headless Chromium, captures console
|
|
errors, and performs TRUE hit-tested clicks on the title menu buttons. */
|
|
const { chromium } = require('/app/node_modules/.pnpm/playwright@1.61.1/node_modules/playwright');
|
|
|
|
(async () => {
|
|
const browser = await chromium.launch({ executablePath: '/root/.cache/ms-playwright/chromium-1234/chrome-linux64/chrome', args: ['--no-sandbox'] });
|
|
const page = await browser.newPage({ viewport: { width: 1280, height: 800 } });
|
|
const logs = [];
|
|
page.on('console', m => logs.push(`[console.${m.type()}] ${m.text()}`));
|
|
page.on('pageerror', e => logs.push(`[PAGEERROR] ${e.message}`));
|
|
|
|
await page.goto(process.argv[2] || 'http://127.0.0.1:8914/wuxia.html', { waitUntil: 'load' });
|
|
await page.waitForTimeout(1200);
|
|
|
|
// What's at the center of the New Journey button?
|
|
const probe = await page.evaluate(() => {
|
|
const btns = [...document.querySelectorAll('.title-menu .btn')];
|
|
return btns.map(b => {
|
|
const r = b.getBoundingClientRect();
|
|
const cx = r.x + r.width / 2, cy = r.y + r.height / 2;
|
|
const top = document.elementFromPoint(cx, cy);
|
|
return {
|
|
label: b.textContent.trim().slice(0, 24),
|
|
rect: `${Math.round(r.x)},${Math.round(r.y)} ${Math.round(r.width)}x${Math.round(r.height)}`,
|
|
topElement: top ? (top.tagName + '.' + String(top.className).split(' ').join('.')) : 'NULL (offscreen?)',
|
|
topIsButtonOrChild: top ? b.contains(top) || top === b : false,
|
|
};
|
|
});
|
|
});
|
|
console.log('Title buttons hit-test:');
|
|
for (const p of probe) console.log(' •', JSON.stringify(p));
|
|
|
|
// True click attempt on New Journey
|
|
const nj = page.locator('.title-menu .btn', { hasText: 'New Journey' }).first();
|
|
try {
|
|
await nj.click({ timeout: 3000 });
|
|
console.log('CLICK: dispatched');
|
|
} catch (e) {
|
|
console.log('CLICK FAILED:', e.message.split('\n')[0]);
|
|
}
|
|
await page.waitForTimeout(400);
|
|
const createVisible = await page.evaluate(() => !document.querySelector('.screen-create').classList.contains('hidden'));
|
|
console.log('creation screen visible after click:', createVisible);
|
|
|
|
// Screenshot for visual confirmation
|
|
await page.screenshot({ path: '/tmp/title_after_click.png' });
|
|
|
|
console.log('\nConsole/page errors:');
|
|
logs.length ? logs.forEach(l => console.log(' ', l)) : console.log(' (none)');
|
|
await browser.close();
|
|
})().catch(e => { console.error('REPRO ERROR:', e.message); process.exit(1); });
|