// The single-file build. // // A build that produces a file proves nothing; this one runs the bundled // script against the fake DOM and plays a turn through it. That is the closest // thing to opening dist/theladder.html that is available without a browser — // it catches a broken bundle, which is otherwise only discovered by whoever // was handed the file. import { test } from 'node:test'; import assert from 'node:assert/strict'; import { execFileSync } from 'node:child_process'; import { readFileSync } from 'node:fs'; import { resolve, dirname } from 'node:path'; import { fileURLToPath } from 'node:url'; import { installFakeDom, byClass, firstByClass } from './fixtures/fake-dom.js'; const root = resolve(dirname(fileURLToPath(import.meta.url)), '..'); test('the bundle builds, and the bundled game boots and plays', () => { execFileSync('node', ['tools/build.js'], { cwd: root, stdio: 'pipe' }); const html = readFileSync(resolve(root, 'dist/theladder.html'), 'utf8'); assert.doesNotMatch(html, /([\s\S]*?)<\/script>/)?.[1]; assert.ok(script, 'the bundled script is present'); const dom = installFakeDom(); try { // eslint-disable-next-line no-new-func -- running the build output is the point new Function(script)(); // Nothing is saved and nothing is remembered, so a build shipping more // than one setting opens on the picker. Click into the first one and carry // on — this exercises the front door in the real bundle, which is the one // place the pack registry, the picker screen and the save slots all meet. assert.ok(firstByClass(dom.root, 'screen--packs'), 'the bundled game rendered the picker'); assert.match(dom.root.textContent, /Corporate Ladder/, 'the packs are named'); assert.match(dom.root.textContent, /The Frontier/); const start = byClass(dom.root, 'button').find((b) => /Start here|Keep playing/.test(b.textContent)); assert.ok(start, 'the picker offers a way in'); start.click(); assert.ok(firstByClass(dom.root, 'screen--turn'), 'the bundled game rendered a turn'); assert.match(dom.root.textContent, /Day 1/); assert.match(dom.root.textContent, /Marlene Hobb/); assert.match(dom.root.textContent, /The Ladder/, 'the status bar is in the bundle'); const playable = byClass(dom.root, 'option').filter((b) => !b.disabled); assert.ok(playable.length > 0, 'the bundled game offers choices'); playable[0].click(); assert.ok(firstByClass(dom.root, 'outcome'), 'a turn can be played in the bundle'); } finally { dom.restore(); } });