Playwright E2E
Validate extension behavior across browsers with repeatable end-to-end tests.
Extension.js projects can use Playwright to test extension flows, UI rendering, and integration behavior in CI and local environments.
Playwright testing capabilities
Why use it
- catch runtime regressions that unit tests miss
- validate extension behavior on real browser engines
- verify multi-browser changes before release
Typical setup
Install Playwright test dependencies in your project:
Create a playwright.config.ts and define browser projects and reporting.
Recommended baseline
Automation contract (recommended)
For deterministic automation, do not parse terminal text. Use the metadata files generated by Extension.js:
dist/extension-js/<browser>/ready.jsondist/extension-js/<browser>/events.ndjson(watch/rebuild events)
ready.json includes stable fields intended for scripts/agents:
status:starting|ready|errorcommand:dev|start|previewbrowserdistPathmanifestPathportpidrunIdstartedAtcompiledAterrors
Use this contract as the source of truth for readiness and failures.
Running tests
Canonical Playwright flow (AI-friendly)
- Start Extension.js in no-browser mode.
- Wait until
ready.jsonreportsstatus: "ready". - Launch Playwright with the extension output from
distPath. - Run tests and shut down.
Dev friend vs test friend
devis the dev friend for watch-mode iteration (extension dev --no-browser+extension dev --wait).startis the test friend for production-style checks (extension start --no-browser+extension start --wait).
Important distinction: run mode vs readiness gate
--no-browseris the run mode: it starts the extension pipeline without launching a browser.- A readiness gate (
extension dev --wait --browser=<browser>) is the synchronization primitive for Playwright/AI.
In other words, --no-browser produces build/watch output, and your wait step consumes the machine contract before tests proceed. If your environment cannot run a second CLI process, you can fall back to directly polling ready.json.
Use this two-process pattern:
- Process A:
extension dev --no-browser - Process B:
extension dev --wait --browser=<browser> --wait-format=json - Start Playwright only after the wait step exits successfully
Production-oriented variant:
- Process A:
extension start --no-browser - Process B:
extension start --wait --browser=<browser> --wait-format=json - Start Playwright only after the wait step exits successfully
Practical guidance for extensions
- Keep test fixtures deterministic; extension startup can be sensitive to profile state.
- Prefer explicit waits on extension UI conditions over fixed sleeps.
- Run Chromium and Firefox projects in CI for cross-engine confidence.
- Capture traces/screenshots/videos on failure for faster debugging.
- Prefer
ready.json/events.ndjsonover stdout parsing for machine reliability.
Common pitfalls
- relying on fixed timeouts instead of state-based waits
- running only one browser target in CI
- skipping artifact upload for failed runs
- coupling tests to local-only profile or environment assumptions
Repository reference
This repository includes a Playwright config at:
playwright.config.ts
Next steps
- Set up CI templates.
- Keep command workflows aligned with dev and build.
