Playwright and Docker
In the article Ddev, Drupal and Playwright (April 23, 2026), we looked at how to integrate Drupal, Ddev and Playwright using the Lullabot/ddev-playwright extension.
Although it works great, this raises the question of strong coupling between these technologies. In other words, if Ddev falls out of favour (as Kalabox or Lando did); or if Playwright falls out of favour (as Selenium or Puppeteer did), will we need a new “glue” layer to replace the Lullabot/ddev-playwright extension?
Or can we do without it?
In this article we will explore the possibility of plugging Playwright into Ddev without the Lullabot/ddev-playwright extension, as good and well maintained as it is, with the goal of looser coupling between our systems.
What are we trying to accomplish?
Our Ddev setup is basically a layer on top of Docker. So we will try to plug Playwright into Ddev’s Docker setup directly; eventually we can use the same appraoch to plug in other tools, such as broken link checkers, accessibility checkers, in much the same way.
Step one: running Playwright on Docker
Let’s start by running a playwright test directly on Docker, without any integration to anything.
Let’s say we want to confirm that the site Amazon.com contains the words “Sign in”, we might create a file which is the only file in ./test/playwright/amazon.spec.ts which contains:
import { test, expect } from '@playwright/test';
test('Amazon contains Sign In', async ({ page }) => {
await page.goto('https://www.amazon.com');
await expect(page.getByText('Sign in')).toBeVisible();
});
Now we can run this test directly on Playwright’s Docker image, like this:
docker run --rm \
-v "$(pwd)":/app \
-w /app \
--ipc=host \
mcr.microsoft.com/playwright:v1.59.1-noble \
bash -c "npm init -y && npm install @playwright/test && npx playwright test test/playwright/amazon.spec.ts"
And you will should see something like:
✓ 1 test/playwright/amazon.spec.ts:3:5 › Amazon contains Sign In (801ms)
1 passed (1.5s)
Step two: Plugging Playwright onto your own project
Let’s start by grabbing the https://github.com/dcycle/starterkit-drupal-ddev and starting it:
ddev start
ddev describe
Your website should now be up and running.
Before continuing, remember how we ran our Playwright tests (with Lullabot/ddev-playwright) in the article Ddev, Drupal and Playwright (April 23, 2026):
ddev install-playwright
./scripts/playwright-test.sh
And you will see the passing tests:
9 passed (5.3s)
This same approach is exactly what we are using in GitHub Actions for continuous integration and running it on GitHub Actions takes about 4 minutes.
Now let’s try running this without Lullabot/ddev-playwright:
The first thing we need to do is to figure out the name of network we’re using:
\$ docker network ls
NETWORK ID NAME DRIVER SCOPE
c9cf026f319b ddev-starterkit-drupal-ddev_default bridge local
...
So in our case our network is called dev-starterkit-drupal-ddev_default, so we need to attach our Docker container to this docker network.
Within that network, our Drupal site is available at http://web (the name of the container within the network), so in:
- ./test/playwright/tests/article-list.spec.ts
- ./test/playwright/tests/login.spec.ts
Let’s change all instances of:
https://starterkit-drupal-ddev.ddev.site
to
http://web
And remove these lines:
test.use({
ignoreHTTPSErrors: true,
});
And now, let’s run our login without Lullabot/ddev-playwright.:
docker run --rm \
-v "$(pwd)/test/playwright/tests":/app/test \
--network ddev-starterkit-drupal-ddev_default \
-w /app \
--ipc=host \
mcr.microsoft.com/playwright:v1.59.1-noble \
bash -c "npm init -y && npm install @playwright/test && npx playwright test test/login.spec.ts"
That should work fine. To run the test which logs on as an administrator, we’ll rest the admin password and inform our test of it:
PASSWORD=$(openssl rand -base64 12)
ddev drush upwd admin $PASSWORD
docker run --rm \
-v "$(pwd)/test/playwright/tests":/app/test \
-e ADMIN_PASSWORD=$PASSWORD \
--network ddev-starterkit-drupal-ddev_default \
-w /app \
--ipc=host \
mcr.microsoft.com/playwright:v1.59.1-noble \
bash -c "npm init -y && npm install @playwright/test && npx playwright test test"
This should give you:
✓ 1 test/login.spec.ts:3:5 › home page has "Log in" (119ms)
✓ 2 test/article-list.spec.ts:3:5 › Anonymous users see 5 latest published articles. (134ms)
Using the password from the environment variable ADMIN_PASSWORD: yUVNCdOp/TrIxHv+
✓ 3 test/article-list.spec.ts:14:5 › Admins users see 5 latest articles, whether they are published or not. (410ms)
3 passed (1.1s)
I have created a new branch “no-extension” in the dcycle/starterkit-drupal-ddev which cleans this up a bit and runs the test on GitHub Actions.
The test is run rather quickly, within 2.5 minutes.
A few notes:
- Our “direct” approach does not use multiple browsers, just Chromium.
- We could still tweak this a bit, for example it might be interesting to maintain an image based on mcr.microsoft.com/playwright:v1.59.1-noble, for example, with @playwright/test preinstalled
Regarding the use of different browsers, this is an interesting idea, although I’m not against just testing on Chromium if it means more speed and simplicity, at least for certain projects.