Browser Testing
Browser Testing
The chromium tier ships everything both modern browser-testing stacks need,
so vendor/bin/pest and php artisan dusk run without downloading a
browser first. This page gives the working recipe for each and explains the
one version rule you need to know.
Use a -chromium (or -dev) image - browser testing needs PHP, Node and
the browser in the same container (Pest's Playwright server and its test
HTTP server both bind 127.0.0.1; a browser sidecar cannot reach them).
Pest v4 browser testing (Playwright)
Pest's browser plugin drives Playwright, and Playwright insists on its own
browser builds - it cannot use the distro Chromium (no executable override
in released plugin versions; watch
pest-plugin-browser#243).
The image therefore bakes Playwright's Chromium at
PLAYWRIGHT_BROWSERS_PATH=/ms-playwright, refreshed to playwright@latest
on every weekly rebuild.
composer require pestphp/pest-plugin-browser --dev
npm install playwright@latest
vendor/bin/pest
Expected: tests run immediately - npx playwright install is NOT needed,
because the baked browsers already match playwright@latest on a current
image.
Both plugin majors are validated against the same baked build (their
Playwright contracts overlap): Pest 4 (pest-plugin-browser ^4, playwright
= 1.59.1) and Pest 5 (^5, playwright >= 1.62.1) each ran a real browser test with zero downloads.
it('has a welcome page', function () {
$page = visit('/');
$page->assertSee('Laravel');
});
The one version rule
Playwright browser builds are revision-locked to the npm package version.
The image bakes the revision matching playwright@latest at build time;
the weekly rebuild keeps that current.
❌ Symptom of version skew (old image + newer npm playwright):
Error: Executable doesn't exist at /ms-playwright/chromium_headless_shell-.../...
✅ Fix: docker pull the current weekly image, or top the shared dir
up once: npx playwright install chromium (it lands in /ms-playwright
because the env is already set; add a named volume on that path in CI to
cache it across runs).
Stability hints (not requirements)
- Playwright always launches Chromium with
--disable-dev-shm-usage, so a small/dev/shmwill not crash it - but for heavy suites give the container--ipc=host(orshm_size: 1gb) per Playwright's own Docker guidance. - Running as root is fine: Playwright launches with its Chromium sandbox
off by default (unlike Puppeteer, no
--no-sandboxjuggling). - cbox-init is PID 1 and reaps the browser process tree - the
--initflag Playwright's docs ask for is already covered. - Emoji and unicode fonts (
fonts-noto-color-emoji,fonts-unifont,fonts-freefont-ttf) are in the image, so screenshot assertions render glyphs instead of tofu boxes.
Laravel Dusk (chromedriver)
Debian keeps chromium and chromium-driver version-matched, and both are
in the image - so Dusk needs no dusk:chrome-driver download at all. Two
small changes in tests/DuskTestCase.php:
public static function prepare(): void
{
// Use the image's chromedriver instead of downloading one into vendor/
static::useChromedriver('/usr/bin/chromedriver');
static::startChromeDriver();
}
protected function driver(): RemoteWebDriver
{
$options = (new ChromeOptions)
->setBinary('/usr/bin/chromium') // the image's Chromium
->addArguments(['--headless=new', '--disable-gpu', '--window-size=1920,1080']);
return RemoteWebDriver::create(
$_ENV['DUSK_DRIVER_URL'] ?? 'http://localhost:9515',
DesiredCapabilities::chrome()->setCapability(ChromeOptions::CAPABILITY, $options)
);
}
Expected:
php artisan dusk
# PASS Tests\Browser\ExampleTest - no chromedriver download, versions always match
Note: Laravel's own docs now recommend Pest browser testing over Dusk for new projects; both are first-class on this image.
Browsershot / Puppeteer
Unchanged and still zero-config: PUPPETEER_EXECUTABLE_PATH=/usr/bin/chromium
and PUPPETEER_SKIP_CHROMIUM_DOWNLOAD=true are baked in. See the
Image Processing guide for PDF generation examples.
What is in the chromium tier for this
| Component | Purpose |
|---|---|
chromium (distro) |
Browsershot/Puppeteer, Dusk browser |
chromium-driver (distro) |
Dusk - apt keeps it version-matched with chromium |
Playwright Chromium at /ms-playwright |
Pest v4 browser tests - refreshed weekly to playwright@latest |
PLAYWRIGHT_BROWSERS_PATH=/ms-playwright |
Any npx playwright install lands in the shared dir |
| Node.js 22 + npm | Playwright's runtime |
| Emoji/unicode fonts | Deterministic screenshot assertions |