The boot smoke
@spawnite/testing/e2e is a game’s one Playwright check: its built bundle boots in a real browser. A game’s playwright.config.ts names a preview port no other game uses:
import { defineGameConfig } from "@spawnite/testing/e2e";
export default defineGameConfig({ port: 4177 });The config builds the game, serves the bundle with vite preview, and opens it in full Chromium in its headless mode, one browser at a time, with the report and traces under .work/. It returns a plain Playwright config, so a game overrides a field by spreading it.
To boot the game in other browsers, set E2E_BROWSERS to a comma-separated list of chromium, firefox and webkit: the config adds a headless Playwright project for each, and --project <name> runs one of them.
test/e2e/boot.spec.ts calls bootSmoke, which opens the page, waits for a canvas to show, runs the game’s own steps, and fails on any uncaught error or console error the page reported meanwhile:
import { expect, test } from "@playwright/test";import { bootSmoke } from "@spawnite/testing/e2e";
test("the app boots, Play starts the run, and the page reports no error", async ({ page,}) => { await bootSmoke(page, { steps: async () => { await page.getByRole("button", { name: "Play" }).click(); await expect(page.getByText("WASD walks")).toBeVisible(); }, });});path opens another address, such as /?quality=minimum, and timeout changes the canvas’s 30 seconds. A check that opens several pages, such as two players in one room, calls watchErrors(page) on each and asserts the list it returns is empty.
@playwright/test is an optional peer, needed only for this entry. A game’s e2e run opens Playwright’s Chromium, so install it once with pnpm exec playwright install chromium, and firefox and webkit beside it for the other two.