import { defineConfig } from '@playwright/test'; import * as setup from './tests/ui/global-setup.ts'; // Before anything else, including the servers below. setup.prepare(); // Measuring the API (#394): an instrumented binary writes its coverage only as it exits, and // Playwright otherwise kills its servers outright. Asked to stop, both shut down on their own. // Where they write it, as coverage.sh sets it; passed on to each server whatever Playwright passes. const PROFILE: Record = process.env.LLVM_PROFILE_FILE ? { LLVM_PROFILE_FILE: process.env.LLVM_PROFILE_FILE } : {}; const STOP = setup.API_COVERAGE ? { gracefulShutdown: { signal: 'SIGTERM' as const, timeout: 15_000 } } : {}; // Real browser against a real daemon. The stub-DOM smoke test catches a script that // fails to load; it cannot catch a wrong selector, a handler that runs but does nothing, // or a page that renders empty -- which is exactly what has slipped through before. export default defineConfig({ testDir: './tests/ui', timeout: 30_000, expect: { timeout: 10_000 }, fullyParallel: false, // one daemon, one database workers: 1, // The page's coverage, with IPX_COVERAGE=1 (#390): cleared first, written last. globalSetup: './tests/ui/coverage-setup.ts', globalTeardown: './tests/ui/coverage-teardown.ts', reporter: process.env.CI ? 'line' : [['list']], use: { baseURL: 'http://127.0.0.1:8791', trace: 'retain-on-failure', screenshot: 'only-on-failure', // The offline service worker (#389) answers requests before page.route sees them, which the // tests that fake an answer rely on. The offline tests allow it for themselves. serviceWorkers: 'block', }, webServer: [ { command: 'node tests/ui/fixtures/serve.ts', port: 8792, reuseExistingServer: false, stdout: 'ignore', }, { // The directory the Directory shows (#205), on SQLite in the scratch directory. command: `${setup.API_COVERAGE ? '' : 'cargo build -q -p ipx-directory && '}exec ${setup.DIRECTORY_BIN} --config ${setup.root}/directory.toml`, url: `${setup.DIRECTORY}/healthz`, reuseExistingServer: false, timeout: 180_000, stdout: 'ignore', env: { DIRECTORY_DATABASE_URL: `sqlite://${setup.root}/directory.db?mode=rwc`, ...PROFILE }, ...STOP, }, { // ipx-play (#447), where a shared episode's link goes, on SQLite in the scratch directory. command: `${setup.API_COVERAGE ? '' : 'cargo build -q -p ipx-play && '}exec ${setup.PLAY_BIN} --config ${setup.root}/play.toml`, url: `${setup.PLAY}/healthz`, reuseExistingServer: false, timeout: 180_000, stdout: 'ignore', env: { PLAY_DATABASE_URL: `sqlite://${setup.root}/play.db?mode=rwc`, ...PROFILE }, ...STOP, }, { // The frontend as production serves it (#203): built from web/, served by Caddy on the // suite's port, the API passed to the daemon behind it. command: `node web/build.mts ${setup.root}/web && exec caddy run --config web/Caddyfile --adapter caddyfile`, url: 'http://127.0.0.1:8791/favicon.png', reuseExistingServer: false, timeout: 60_000, stdout: 'ignore', env: { IPX_COVERAGE: process.env.IPX_COVERAGE ?? '', WEB_BIND: '127.0.0.1:8791', WEB_ROOT: `${setup.root}/web`, IPX_UPSTREAM: '127.0.0.1:8796', HOME: setup.root, XDG_DATA_HOME: setup.root, XDG_CONFIG_HOME: setup.root }, }, { // Build first so the tests always run against current source, unless the instrumented // build is what is measured (#394). command: `${setup.API_COVERAGE ? '' : 'cargo build -q && '}exec ${setup.IPX_BIN} daemon`, port: 8796, reuseExistingServer: false, timeout: 180_000, stdout: 'pipe', env: { IPX_CONFIG: `${setup.root}/config/config.toml`, IPX_DATA_DIR: `${setup.root}/data`, IPX_LOG: 'ipx=info', // Blank, whatever the shell running the suite has: the test daemon sends no traces to // production's Tempo and never opens production's database. OTEL_EXPORTER_OTLP_ENDPOINT: '', IPX_DATABASE_URL: '', // The server's TypeSafe key is the shell's: /src/.envrc's is a development key, for this. // Without one, the tests of the server paying for Signals see that it cannot. TYPESAFE_KEY: process.env.TYPESAFE_KEY ?? '', IPX_TYPESAFE_URL: 'http://127.0.0.1:8792/jev', ...PROFILE, }, ...STOP, }, ], });