import { defineConfig, devices } from '@playwright/test'; // The e2e runs inside the compose network (infra/run-e2e-check.sh); baseURL defaults to the // self-service service. Keep timeouts generous — the first navigation triggers the DigiD flow. const baseURL = process.env.SELF_SERVICE_URL ?? 'http://self-service'; // The behandel portal is a second origin the happy path visits (staff approve from the werkbak); // it needs the same insecure-origin-as-secure treatment as self-service for the PKCE login (below). const behandelURL = process.env.BEHANDEL_URL ?? 'http://behandel'; // The beheer portal is a third medewerker-realm origin (the read-only catalogus viewer, S-15a); it // needs the same insecure-origin-as-secure treatment as the others for the PKCE login (below). const beheerURL = process.env.BEHEER_URL ?? 'http://beheer'; export default defineConfig({ testDir: '.', timeout: 90_000, expect: { timeout: 15_000 }, retries: 1, // Run the specs serially. Each spec drives a full `channel: 'chromium'` browser, and the e2e // shares an 8 GB runner with the entire compose stack (OpenZaak, NRC, Keycloak, Flowable, 4× // Postgres, every service + 3 portals). Two parallel browsers exhaust memory and the renderer is // OOM-killed mid-action ("Page crashed") — fixing the flakiness at its source rather than leaning // on `retries` (CLAUDE.md §15). Only two long-running happy-path specs, so serial costs little. workers: 1, // `list` for the live log; `json` (→ /e2e/playwright-report.json in the container) is copied out // by run-e2e-check.sh and rendered as a per-spec table in the CI job summary (#136). reporter: [['list'], ['json', { outputFile: 'playwright-report.json' }]], use: { baseURL, trace: 'on-first-retry', // The portal is served over plain HTTP on a non-localhost origin (http://self-service) inside the // compose network, so it is NOT a secure context — and Web Crypto (`crypto.subtle`) is undefined // there. angular-auth-oidc-client needs SubtleCrypto to build the PKCE code challenge, so // `authorize()` throws and the login redirect never fires (the login form never appears). In // production the portal runs behind HTTPS, where this works. Rather than terminate TLS in the // throwaway e2e stack, tell Chromium to treat this origin as secure — which faithfully emulates // the production HTTPS context. This flag is only honoured by the full Chromium build (new // headless), not Playwright's default headless-shell, so pin `channel: 'chromium'`. channel: 'chromium', launchOptions: { args: [ `--unsafely-treat-insecure-origin-as-secure=${baseURL},${behandelURL},${beheerURL}`, // Write Chromium's shared memory to /tmp instead of the container's small /dev/shm, so a // large DOM/heap can't crash the renderer on the memory-constrained runner (belt-and-braces // alongside the single worker above). '--disable-dev-shm-usage', ], }, }, projects: [{ name: 'chromium', use: { ...devices['Desktop Chrome'] } }], });