Skip to content

Latest commit

 

History

History
205 lines (155 loc) · 9.38 KB

File metadata and controls

205 lines (155 loc) · 9.38 KB

tests

ddev-playwright

example in action Example test validating phpinfo(), slowed down for the demo.

What is ddev-playwright?

This repository contains an addon for integrating Playwright tests into your ddev project.

Highlights include:

  • Support for both npm and yarn.
  • Support for running headless tests.
  • Support for running headed tests with remote access to the UI through your web browser.
  • Only installs the heavy Playwright dependencies if a given local opts in to them.
  • Does not require running Playwright in ddev, in case developers prefer to run on the host on locals.
  • Optimizations to reduce build time, especially on locals when ddev versions are upgraded.

Getting started

The full setup workflow is:

  1. Install the addon and commit the generated configuration.
  2. Initialize Playwright inside the container (creates package.json, config, etc.).
  3. Run ddev install-playwright to rebuild the web service with browser dependencies.

Tip: Re-run ddev restart any time you update the Playwright version in test/playwright/package.json so the matching browser binaries are installed.

Tip: Tests live in test/playwright by default. To use a different path (e.g. tests/playwright), add it to .ddev/.env:

PLAYWRIGHT_TEST_DIR=tests/playwright

then ddev restart before initializing Playwright. Substitute your chosen path for test/playwright in the commands below.

# 1. Install the addon.
ddev add-on get Lullabot/ddev-playwright
git add .
git add -f .ddev/config.playwright.yml

# 2. Initialize Playwright (choose npm or yarn).
mkdir -p test/playwright
ddev exec -d /var/www/html/test/playwright npm init playwright@latest
# Or yarn:
# ddev exec -d /var/www/html/test/playwright yarn create playwright

# 3. Install Playwright browser dependencies and cache them.
ddev install-playwright

# To run playwright's test command.
ddev playwright test
# To run with the UI.
ddev playwright test --headed
# To generate playwright code by browsing.
ddev playwright codegen
# To view the HTML test report. The command prints the URL to open; no --host
# flag is needed.
ddev playwright show-report
# The report is accessible at https://<PROJECT>.ddev.site:9324

The following services are exposed with this addon:

Service URL Notes
KasmVNC https://<PROJECT>.ddev.site:8444 Username is your local username. Password is secret.
Playwright Test Reports https://<PROJECT>.ddev.site:9324 This port is changed from the default to not conflict with running Playwright on the host.

Viewing test reports

ddev playwright show-report needs no flags. It serves the report from the web container and prints the URL to open:

ddev-playwright: view the report at https://<PROJECT>.ddev.site:9324
ddev-playwright: the address Playwright prints below is the in-container one.

  Serving HTML report at http://0.0.0.0:9323. Press Ctrl+C to quit.

Playwright's own line is accurate, but describes the address inside the container. The router publishes it on the host at the port in the table above.

Accessing other Playwright HTTP services beyond show-report

When running commands like show-trace, always:

  1. Bind 0.0.0.0, never localhost. The router connects over the Docker network, so a server on the container's loopback interface is invisible to it and the routed URL answers 502 Bad Gateway. Binding 0.0.0.0 does not expose anything to your network — the container port is not published, so the router is still the only way in.
  2. Use a port in web_extra_exposed_ports. Anything else is not routed at all, whatever it is bound to.

ddev playwright show-report already satisfies both, which is why it needs no flags. Playwright's other servers default to localhost and need saying explicitly — both of these come out at https://<PROJECT>.ddev.site:9324:

ddev playwright test --ui --ui-host=0.0.0.0 --ui-port=9323
ddev playwright show-trace --host=0.0.0.0 --port=9323

Run only one at a time; they share the single routed port.

SQLite tmpfs mount

This addon mounts /tmp/ddev-playwright as a tmpfs (in-memory) volume. The @lullabot/playwright-drupal package uses /tmp/ddev-playwright/sqlite for per-test SQLite database copies, and keeping the I/O in memory significantly improves parallel test performance. Feel free to use it for your own database driven tests.

For compatibility with existing versions of @lullabot/playwright-drupal, the same tmpfs remains mounted at /tmp/sqlite. Legacy versions therefore keep their existing path, while newer versions can use the namespaced directory.

Because tmpfs is volatile, ddev restart will clear the volume.

HTTPS certificates

DDEV signs every *.ddev.site certificate with a per-host mkcert root CA. On container start this addon makes Chromium, Firefox, and WebKit all trust that CA, so *.ddev.site loads cleanly without ignoreHTTPSErrors: true in any Playwright project. The setup lives in .ddev/web-entrypoint.d/mkcert-nssdb.sh:

  • Chromium reads ~/.pki/nssdb; the script imports every mkcert root via certutil.
  • Firefox (the Playwright build) reads an enterprise policy JSON whose path is given by PLAYWRIGHT_FIREFOX_POLICIES_JSON. The script writes that file; config.playwright.yml sets the env var.
  • WebKit reads the system CA bundle directly, which DDEV already seeds, so it needs no extra handling.

What the browser install sees

Browsers are installed in a Docker layer, and that layer needs to know which version of Playwright your project has locked. A pre-start hook stages the files a package manager reads to answer that question into .ddev/web-build/playwright:

package.json, package-lock.json, npm-shrinkwrap.json, yarn.lock, .yarnrc.yml, .npmrc, and any *.tgz in your Playwright directory (for local tarball dependencies).

Yarn Berry projects also get .yarn/releases, .yarn/patches, .yarn/plugins and .yarn/cache. Those are install inputs — .yarn/cache holds the packages themselves, so a zero-install project still installs. .yarn/install-state.gz, .yarn/unplugged/ and .yarn/build-state.yml are regenerated by yarn install and are left out. Note that .yarn/cache is sized by your dependency tree, so a Berry project stages more than an npm one — it changes only when your dependencies do, which is a rebuild you want.

Your specs, fixtures, and snapshot baselines are deliberately left out. The staged directory is bind-mounted into the build, so everything in it becomes part of that layer's cache key — staging a snapshot baseline would rebuild the web image, and every layer after it, each time you updated a screenshot. None of those files survive into the image anyway; the layer deletes its copy once the browsers are cached.

The practical consequence: a dependency in your package.json must be resolvable from the Playwright directory alone. A file: dependency pointing outside it (file:../../some-package.tgz) will fail to install during the build. Move the target inside the Playwright directory and reference it relatively.

Contributing

This project uses conventional commits for all commit messages. A pre-commit hook is included to validate commit messages locally before pushing.

To install pre-commit:

pip install pre-commit
pre-commit install
pre-commit install --hook-type commit-msg

If you use Claude Code or GitHub Copilot, pre-commit is installed automatically when a session starts.

Similar Tools

julienloizelet/ddev-playwright was a great inspiration for this work. It uses Playwright containers built by Microsoft for tests. A few questions on the implementation has some notes on the differences in the implementations. The main differences are:

  1. This addon stacks Playwright and KasmVNC into the web container. This makes accessing the system being tested (like Drupal) much easier. For example, with a Drupal site Playwright can easily call drush or other CLI tools to set up tests.
  2. The official Playwright containers do not ship with any sort of remote access to the Playwright UI. This repository (as well as julienloizelet/ddev-playwright) includes KasmVNC to run tests in headed mode or to generate code.
  3. By stacking Playwright into the web container, it simplifies permissions for writing Playwright's test reports back out.