Playwright testing capabilities
| Capability | What it gives you |
|---|---|
| Cross-browser runtime checks | Validate core flows on Chromium and Firefox engines |
| UI and interaction coverage | Test popup/options/content-script behavior with real browser contexts |
| CI-ready reports | Capture traces/screenshots/videos for failed tests |
| Regression safety | Catch integration bugs that unit tests usually miss |
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 aplaywright.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 that Extension.js generates:dist/extension-js/<browser>/ready.jsondist/extension-js/<browser>/events.ndjson(newline-delimited JSON for watch/rebuild events)
ready.json includes stable fields intended for scripts/agents:
status:starting|ready|errorcommand:dev|start|previewbrowserdistPathmanifestPathportpidrunIdstartedAtcompiledAterrors
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.
Development mode vs test mode
devis for watch-mode iteration (extension dev --no-browser+extension dev --wait).startis 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 step that tells Playwright when the extension is ready.
--no-browser produces build output. The wait step confirms readiness before tests proceed. If your environment cannot run a second CLI process, poll ready.json directly.
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
- 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 timeouts.
- 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
Your repository includes a Playwright configuration at:playwright.config.ts
Next steps
- Set up CI templates.
- Keep command workflows aligned with dev and build.

