Files
vngeoguessr/playwright.config.mjs
tiennm99 d5c97fab5c test(e2e): cover the URL contract, and compile game routes before the race
Adds coverage for this branch's behaviour: the homoglyph 404 through a real
percent-encoded request, href assertions on both not-found exits (a visible
link to nowhere is still a dead end), and the two halves of InlineScript's
contract -- no console error where React renders the script on the client, and
an executable type in the served markup everywhere else.

That second one is asserted on raw HTML, with no browser, because in a browser
the regression is invisible: ThemeToggle re-applies the theme on mount, so
<html> ends up correct whether or not the script ran -- just a flash later.
Mutating the helper to always emit text/plain previously failed nothing.

global-setup fixes a real flake. next dev compiles a route on first request,
and 8 workers demanded the same cold compile at once, so every test navigating
to a /game URL failed together at the 60s timeout -- reproducible by touching
any source file. One serial warm-up pays the compile once: 28 passed in 14s.
The fetch is bounded and its failure logged, because a skipped warm-up
otherwise looks exactly like the flake it prevents.

eslint ignores Playwright's artifact dirs, which are gitignored but were still
walked, crashing a lint run concurrent with a test run.
2026-09-06 19:51:16 +07:00

38 lines
1.5 KiB
JavaScript

import { defineConfig, devices } from '@playwright/test';
// E2E smoke tests for the UI that vitest cannot reach. Every /api/* call and
// the panorama image are stubbed at the browser boundary (tests/e2e/helpers.js),
// so the dev server this config starts never touches Redis, Neon, or Mapillary
// -- the suite runs offline with no .env at all.
//
// Specs are *.spec.js so vitest (tests/**/*.test.js) never picks them up, and
// vice versa.
export default defineConfig({
testDir: 'tests/e2e',
testMatch: '**/*.spec.js',
// Compiles the game routes once, before the workers race for them. See the
// file for why the suite fails in a block of 8 without it.
globalSetup: './tests/e2e/global-setup.js',
fullyParallel: true,
// The suite is deterministic (no live services); a failure is a real one.
retries: 0,
// A cold `next dev` compiles /game on first navigation, which can take
// longer than the 30s default while workers race for the same compile.
timeout: 60_000,
reporter: [['list']],
use: {
baseURL: 'http://localhost:3000',
trace: 'retain-on-failure',
},
projects: [{ name: 'chromium', use: { ...devices['Desktop Chrome'] } }],
webServer: {
command: 'npm run dev',
url: 'http://localhost:3000',
// Reuse a dev server the developer already has running; the stubs make the
// tests indifferent to whatever backend that server is configured with.
// Never in CI, where adopting an unknown :3000 would hide a broken build.
reuseExistingServer: !process.env.CI,
timeout: 120_000,
},
});