const { chromium } = require('C:/Users/phenom/.cache/codex-runtimes/codex-primary-runtime/dependencies/node/node_modules/playwright'); const assert = require('node:assert/strict'); const fs = require('node:fs'); const path = require('node:path'); const directory = path.resolve('playtest-artifacts', 'dungeon-simulation'); fs.mkdirSync(directory, { recursive: true }); const databaseDirectory = path.join(directory, 'test-database'); fs.rmSync(databaseDirectory, { recursive: true, force: true }); (async () => { const { createGameServer } = await import('../server/server.mjs'); const runtime = createGameServer({ dataDir: databaseDirectory, enableShelvedModes: false, }); await new Promise((resolve) => runtime.server.listen(4189, '127.0.0.1', resolve)); const browser = await chromium.launch({ channel: 'msedge', headless: true }); const context = await browser.newContext({ viewport: { width: 1600, height: 1000 }, acceptDownloads: true }); const page = await context.newPage(); page.setDefaultTimeout(90000); const errors = []; page.on('pageerror', (error) => errors.push(error.message)); const capture = (name) => page.screenshot({ path: path.join(directory, `${name}.png`), fullPage: true }); try { await page.goto('http://127.0.0.1:4189', { waitUntil: 'domcontentloaded' }); await page.getByLabel('Username').fill('Phenom'); await page.getByLabel('Password').fill('dungeon-route-admin'); await page.getByRole('button', { name: /Create account/ }).click(); await page.getByRole('button', { name: /Create character/ }).click(); await page.getByRole('button', { name: /Customize & name/ }).click(); await page.getByLabel('Character name').fill('Routewatcher'); await page.getByRole('button', { name: /Create character/ }).click(); await page.getByRole('button', { name: /Continue/ }).first().click(); await page.getByRole('button', { name: /GM Tools/ }).click(); await page.getByRole('heading', { name: 'Dungeon route simulations' }).waitFor(); await capture('01-gm-route-launch'); const routeSelects = page.locator('.dungeon-sim-admin__catalog select'); await routeSelects.nth(0).selectOption('wailing-caverns'); await routeSelects.nth(1).selectOption('navigation-only'); await page.locator('.dungeon-sim-admin__catalog input').fill('browser-smoke-fixed-seed'); await page.getByRole('button', { name: 'Launch spectate mode' }).click(); await page.locator('canvas').waitFor(); await page.getByLabel('Dungeon simulation controls').waitFor(); await page.waitForTimeout(6000); await capture('02-live-navigation-simulation'); await page.getByRole('button', { name: 'Pause' }).click(); const pausedTime = await page.locator('.dungeon-sim-hud__header > time').innerText(); await page.waitForTimeout(700); assert.equal(await page.locator('.dungeon-sim-hud__header > time').innerText(), pausedTime, 'pause freezes simulation time'); await page.getByRole('button', { name: 'Step' }).click(); await page.getByRole('button', { name: 'Step' }).click(); await page.waitForTimeout(200); assert.notEqual(await page.locator('.dungeon-sim-hud__header > time').innerText(), pausedTime, 'single-step advances simulation time'); await page.getByRole('button', { name: 'Follow camera' }).click(); await page.getByRole('button', { name: 'Free-fly camera' }).waitFor(); await capture('03-paused-free-fly'); await page.getByRole('button', { name: '4×' }).click(); await page.getByRole('button', { name: 'Play' }).click(); await page.waitForTimeout(1200); await page.getByRole('button', { name: 'Stop & save' }).click(); await page.getByRole('button', { name: 'Return to GM Tools' }).waitFor(); await capture('04-finished-report'); await page.getByRole('button', { name: 'Return to GM Tools' }).click(); await page.getByRole('heading', { name: 'Dungeon route simulations' }).waitFor(); await page.locator('.dungeon-sim-admin__catalog select').nth(0).selectOption('wailing-caverns'); await page.getByText(/1 runs for this route/).waitFor(); await capture('05-saved-replay'); await page.getByRole('button', { name: 'Watch' }).first().click(); await page.getByText('Recorded replay').waitFor(); await page.getByLabel('Replay position').waitFor(); await page.waitForTimeout(6000); await page.getByRole('button', { name: 'Play' }).click(); await page.waitForTimeout(800); await capture('06-replay-controls'); await page.getByRole('button', { name: 'Pause' }).click(); const pausedReplayTime = await page.locator('.dungeon-sim-hud__header > time').innerText(); await page.waitForTimeout(500); assert.equal(await page.locator('.dungeon-sim-hud__header > time').innerText(), pausedReplayTime, 'replay pause freezes playback time'); await page.getByRole('button', { name: '4×' }).click(); await page.getByRole('button', { name: 'Play' }).click(); await page.waitForTimeout(600); await capture('07-replay-4x'); assert.deepEqual(errors, [], `No browser page errors: ${errors.join('; ')}`); console.log('Dungeon simulation browser smoke test passed.'); } finally { await browser.close(); await new Promise((resolve) => runtime.server.close(resolve)); } })().catch((error) => { console.error(error); process.exitCode = 1; });