A FIELD GUIDE TO LARAVEL · VOLUME II · THE ECOSYSTEM
ENTRY II.13 · BROWSER TESTING
Dusk
Laravel\Dusk · Package · first recorded 22 January 2017, v1.0.0 on Packagist; with Laravel 5.4
Browser tests through ChromeDriver, with no Selenium or JDK to install. A test opens a real Chrome against your app at APP_URL and asserts on what a user sees. The docs now point new projects to Pest 4's browser testing.
Specification
Kind Package, dev only. A test harness plus a ChromeDriver binary
Driver ChromeDriver by default; any Selenium-compatible driver
Client Google Chrome, headless or visible, one or more windows
Installed by composer require laravel/dusk --dev · php artisan dusk:install
Voice dusk · dusk:fails · dusk:make · dusk:page · dusk:chrome-driver
Scales by Several Browser arguments in one test; CI runs against artisan serve
Range Cloud: no: a test tool, run in CI, never deployed
Forge, VPS: no: the same. Keep its provider out of production
Vapor: no: the same, a test tool
Neighbours
Laravel's HTTP tests simulate the request inside the test process, so no browser or JavaScript is involved. Pest 4 includes browser testing of its own, and the Dusk docs recommend it for new projects. Dusk's distinction is a real Chrome through ChromeDriver, in PHP, in the same suite as the rest.
Field marks
tests/Browser/
.env.dusk.local
dusk="..." attributes in HTML
DuskServiceProvider, never in production
Fig. II.13.1 · one browser test, exploded
Parts
1 Test. In tests/Browser, extending DuskTestCase. $this->browse(fn (Browser $b) => $b->visit('/login')...).
2 ChromeDriver, a binary dusk:install fetched for your OS; dusk:chrome-driver --detect matches it to the Chrome you have.
3 Chrome. A real browser, one per Browser argument. Elements found by a dusk="login-button" attribute, @login-button.
4 Your app, served at APP_URL, in CI by php artisan serve. .env.dusk.local swaps in for the run and back out after.
5 Database. Shared by browser and test process, so no in-memory SQLite and no RefreshDatabase; truncate or migrate instead.
6 On failure. A screenshot to tests/Browser/screenshots; console logs to tests/Browser/console every run. CI uploads both.
Hidden joinery
Dusk backs up .env, renames .env.dusk.local into place, and restores the original when the run ends. On failure it resizes the window to fit the content before the screenshot, so nothing is cropped. loginAs keeps the session for the rest of the file. The waits poll (waitFor, waitForText, waitUntilVue), so a fixed pause is rare.
Every line checked on 2026-10-08 against the 13.x docs, the laravel/dusk source and Packagist.
TITLE
Dusk · one browser test
SOURCES
laravel.com/docs/13.x/dusk · github.com/laravel/dusk · packagist.org/packages/laravel/dusk · packagist.org/packages/laravel/framework · pestphp.com/ · laravel.com/docs/13.x/http-tests
STATUS
Verified · 2026-10-08
SHEET
II.13 of 48
REV
A · 2026-10-08
DRAWN
BS
FINISH
All faces, including the back