Files
ipx/playwright.config.ts
rays f8408a3d26 Tests, tooling and the served scripts are TypeScript (#392)
The page and the service worker were strict TypeScript; the tests, the
build, the home page's generator, the load tests, boot.js and the
directory's site.js were plain JavaScript that nothing checked. All of
it is TypeScript now, in five programs, each with its own globals, all
checked by npm run typecheck: the page (tsconfig.json, with boot.ts and
the directory's site.ts), the worker, Node's (tsconfig.tools.json: the
Node tests, the browser suite, the build, the site generator, the load
harness), and k6's (tsconfig.k6.json, with @types/k6).

Node 24 runs the .ts files by stripping their types, so they hold only
TypeScript that erases (erasableSyntaxOnly) and import each other by
.ts name; package.json says "type": "module" for it, and Dockerfile.web
moves to Node 24 to run build.mts. k6 2.3 strips its scripts' types
itself.

The browser suite's page.evaluate calls reach the page's globals; the
page's tsc run now also writes its declarations to target/page-types,
which the suite's program includes, so those calls are typed by the
page's own code rather than by hand-written copies.

boot.ts is compiled by build.mts with swc, as the worker is, and named
by the hash of what is served. The directory's build has no Node, so
site.js is compiled from site.ts and committed (node web/build.mts
--directory-script), and tests/directory-script.ts fails if they drift.

Checked: the site generator's 139 pages are byte for byte what the
JavaScript made; the page build's app.js is identical and only boot.js
(now minified) and its hash differ; contrast, page-smoke, page-unit,
native-bridge, the browser suite (96 passed, 2 skipped) and the
directory's and ipx's Rust tests pass; k6 parses each load script. The
load tests themselves did not run: they build a release binary outside
the capped builder. .agents/skills/security-audit is an installed
skill's, not ours, and is left as it is.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-07 02:23:22 +00:00

77 lines
3.3 KiB
TypeScript

import { defineConfig } from '@playwright/test';
import * as setup from './tests/ui/global-setup.ts';
// Before anything else, including the servers below.
setup.prepare();
// 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: `cargo build -q -p ipx-directory && exec ./target/debug/ipx-directory --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` },
},
{
// 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.
command: 'cargo build -q && exec ./target/debug/ipx 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',
},
},
],
});