Files
healer-man/scripts/playtest-dungeon-simulation.cjs
T
2026-09-16 14:30:58 -04:00

100 lines
5.3 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
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;
});