In Laravel 13, how do you set up Laravel Dusk and write a first browser test that signs a new user up?
answer
- dev dependency, then dusk:install
- tests/Browser and DuskTestCase
- APP_URL must reach a running app
- browse() hands you a Browser
- php artisan dusk runs the suite
basics
~20 sRequire laravel/dusk as a dev dependency and run php artisan dusk:install, which creates tests/Browser and DuskTestCase and downloads ChromeDriver. Point APP_URL at the running app, chain visit(), type() and press() inside $this->browse(), and run php artisan dusk.
solid answer
~40 sInstall with `composer require laravel/dusk --dev`, then `php artisan dusk:install`: it creates `tests/Browser` with an example test and page classes, writes `tests/DuskTestCase.php`, and downloads a ChromeDriver binary for your OS. Set `APP_URL` to the address where the app is actually served, because Dusk drives a real Chrome against that URL and does not start a web server. A test calls `$this->browse(function (Browser $browser) { ... })` and chains `visit('/register')`, `type('name', 'Ada')`, `type('email', ...)`, `press('Register')`, then `assertPathIs('/dashboard')`. `type()` finds an input or textarea by its `name` when given a plain word; `press()` finds a button by text, name or selector. Run it with `php artisan dusk`, not `php artisan test`. With Pest installed, `dusk:install` wires `tests/Browser` to `DuskTestCase` in `tests/Pest.php`. The Laravel 13 docs now recommend Pest 4's browser testing for new projects.
code
bash · 4 linescomposer require laravel/dusk --dev
php artisan dusk:install
php artisan serve --no-reload &
php artisan duskgo deeper
Recall the install steps, dusk:install, the tests/Browser folder, and the browse() closure with visit, type, press and an assertion.
Explain that Dusk drives real Chrome via ChromeDriver against the app at APP_URL, and how type() and press() find elements.
Keep Dusk as a dev-only dependency, match ChromeDriver to Chrome, and use a dedicated .env.dusk file so browser runs never touch real data.
Decide whether browser tests belong in Dusk or Pest's browser plugin for your stack, weighing existing suites against the docs' current recommendation.
## What Dusk is **Laravel Dusk** is Laravel's first-party browser automation package. A Dusk test starts a real Chrome through **ChromeDriver** (a small server that speaks the WebDriver protocol), points it at your running application, and clicks and types like a user. Because the page runs its own JavaScript, Dusk can test what HTTP feature tests cannot: date pickers, modals, Alpine or Livewire behaviour, redirects done in the browser. ## Installing it 1. `composer require laravel/dusk --dev`. It must stay a **dev** dependency; the package registers login helper routes in every non-production environment. 2. `php artisan dusk:install`. This creates `tests/Browser/` with an `ExampleTest.php` and `Pages/` classes, writes `tests/DuskTestCase.php`, and installs a ChromeDriver binary for your operating system. 3. Set `APP_URL` in `.env` to the URL the app is served on, for example `http://127.0.0.1:8000` with `php artisan serve`. Dusk **does not start your application**; it sends the browser to that URL. 4. Optionally create `.env.dusk.local`: when `php artisan dusk` runs in the `local` environment, it backs up `.env`, swaps in that file for the run, and restores it afterwards. If Chrome on the machine is newer than the downloaded driver, `php artisan dusk:chrome-driver --detect` installs the matching version. ## The generated base class `tests/DuskTestCase.php` extends `Laravel\Dusk\TestCase`. Its `prepare()` method, marked with PHPUnit's `#[BeforeClass]` attribute, starts ChromeDriver on port 9515 (unless running in Sail), and its `driver()` method builds Chrome options: a 1920x1080 window, and `--headless=new` plus `--disable-gpu` unless headless mode is disabled. `DUSK_DRIVER_URL` can point it at a different WebDriver server. ## The first test: a sign-up flow ```php $this->browse(function (Browser $browser) { $browser->visit('/register') ->type('name', 'Ada Lovelace') ->type('email', '[email protected]') ->type('password', 'secret-password') ->type('password_confirmation', 'secret-password') ->press('Register') ->assertPathIs('/dashboard'); }); ``` - `browse()` takes a closure and passes it one `Browser` per parameter, so a two-parameter closure gets two browsers. - `visit()` is relative to `APP_URL`. - `type('email', ...)` clears the field and sends keystrokes. A plain word is matched against an `input` or `textarea` with that `name`; an `#id` or any other CSS or `@` selector is used as given. - `press('Register')` finds a button by selector, name, value or visible text and clicks it. - Assertions such as `assertPathIs()`, `assertSee()` and `assertInputValue()` read the live page. ## Page classes `dusk:install` also creates `tests/Browser/Pages/Page.php` and `HomePage.php`, and `php artisan dusk:page SignupPage` generates more. A page class declares its `url()`, an `assert()` method that checks the browser really is on that page, and an `elements()` map of shorthand selectors such as `'@email' => 'input[name=email]'`. `$browser->visit(new SignupPage)` navigates to the URL and runs the page's assertions, so a sign-up flow reads as steps on named pages rather than raw URLs and selectors. ## Running | Command | Purpose | |---|---| | `php artisan dusk` | run the browser suite (accepts the usual PHPUnit or Pest arguments) | | `php artisan dusk --browse` | open a visible browser instead of headless mode, outside CI | | `php artisan dusk:fails` | re-run only the tests that failed last time | | `php artisan dusk:make SignupTest` | generate a new test in `tests/Browser` | ## Dusk with Pest When Pest is installed, `dusk:install` writes a Pest-style example test and adds `pest()->extend(Tests\DuskTestCase::class)->in('Browser')` to `tests/Pest.php`, so `test('...', function () { $this->browse(...); })` works. That is Dusk running under Pest. Separately, the Laravel 13.x documentation now carries a warning that **Pest 4 includes its own browser testing** and recommends it over Dusk for new projects; Dusk remains supported and is what many existing suites use. ## What to say in an interview - Dusk drives real Chrome via ChromeDriver; no Selenium or JDK is required by default. - The app must be running at `APP_URL`. - `browse()`, `visit()`, `type()`, `press()`, then an assertion. - `php artisan dusk`, not `php artisan test`.
- The first Dusk run fails with a connection error before any page loads. What do you check first?That the app is actually being served at `APP_URL` (Dusk never starts it; run `php artisan serve` or use your local server), and that ChromeDriver matches the installed Chrome. `php artisan dusk:chrome-driver --detect` installs the driver version that matches the detected Chrome.
- Should a brand-new Laravel 13 project start its browser tests with Dusk?The 13.x Dusk docs recommend Pest 4's built-in browser testing for new projects, citing performance and usability. Dusk is still maintained and suits teams with existing Dusk suites or a PHPUnit-only codebase; a new project already on Pest has a reason to start there.
saying these in an interview costs you the question
- Dusk starts its own web server, so APP_URL does not matter
- Dusk tests run with php artisan test like feature tests
- Dusk needs a Selenium server and a JDK installed
- laravel/dusk belongs in require so production can run browser tests
- Dusk simulates HTTP requests in-process like the feature test client