> ## Documentation Index
> Fetch the complete documentation index at: https://kawax.biz/llms.txt
> Use this file to discover all available pages before exploring further.

# Browser tests (Dusk)

> How to run ChromeDriver-based browser E2E tests with Laravel Dusk

## What is Laravel Dusk

Laravel Dusk is an E2E testing tool that verifies your entire application by actually driving a browser.\
By default, Dusk can run tests via ChromeDriver without requiring a separate Selenium server.

<Warning>
  The official documentation also recommends Pest 4 browser tests for new projects. Use this page when you're using Dusk on an existing project, or when you want to use Dusk's API.
</Warning>

## Installation

First, install Google Chrome, then add Dusk as a development dependency.

```shell theme={null}
composer require laravel/dusk --dev
php artisan dusk:install
```

To adjust the ChromeDriver version, use the `dusk:chrome-driver` command.

```shell theme={null}
# Detect and install the version that matches your local Chrome
php artisan dusk:chrome-driver --detect
```

## Environment configuration (`.env.dusk.local`)

To use environment variables specific to Dusk, create a `.env.dusk.{environment}` file in the project root.\
For a local environment, use `.env.dusk.local`.

```ini theme={null}
APP_URL=http://127.0.0.1:8000
DB_CONNECTION=mysql
DB_DATABASE=app_testing
DB_USERNAME=root
DB_PASSWORD=root
```

While Dusk is running, `.env` is backed up and the contents of `.env.dusk.local` are temporarily applied.

## Basic browser tests

Generate a test and run it with `php artisan dusk`.

```shell theme={null}
php artisan dusk:make LoginTest
php artisan dusk
```

To re-run only the failing tests:

```shell theme={null}
php artisan dusk:fails
```

### A basic example

```php theme={null}
<?php

namespace Tests\Browser;

use App\Models\User;
use Laravel\Dusk\Browser;
use Tests\DuskTestCase;

class LoginTest extends DuskTestCase
{
    public function test_user_can_login(): void
    {
        $user = User::factory()->create([
            'email' => 'taylor@laravel.com',
        ]);

        $this->browse(function (Browser $browser) use ($user) {
            $browser->visit('/login')
                ->type('email', $user->email)
                ->type('password', 'password')
                ->press('Login')
                ->assertPathIs('/dashboard')
                ->assertSee('Dashboard');
        });
    }
}
```

`visit()`, `type()`, `press()`, and `assertSee()` are the most commonly used Dusk operations.

<Warning>
  Do not use `RefreshDatabase` in Dusk tests. As noted in the official documentation, use `DatabaseMigrations` or `DatabaseTruncation` to reset data between tests.
</Warning>

## Page object pattern

When testing complex screens, generating a page object with `dusk:page` improves maintainability.

```shell theme={null}
php artisan dusk:page Login
```

Define `url()` and `elements()` in `tests/Browser/Pages/Login.php` and reuse them from your tests.

```php theme={null}
use Tests\Browser\Pages\Login;

$browser->visit(new Login)
    ->type('@email', 'taylor@laravel.com')
    ->type('@password', 'password')
    ->click('@submit')
    ->assertSee('Dashboard');
```

## Screenshots and debugging

Saving screenshots and console logs is effective for investigating failures.

```php theme={null}
$browser->screenshot('login-failed');
$browser->responsiveScreenshots('login-page');
$browser->screenshotElement('#login-form', 'login-form');
$browser->storeConsoleLog('login-console');
```

* Screenshots: `tests/Browser/screenshots`
* Console logs: `tests/Browser/console`

## Running in CI (GitHub Actions)

On GitHub Actions, start ChromeDriver and Laravel's built-in server, then run `php artisan dusk`.

```yaml theme={null}
name: Dusk tests

on: [push, pull_request]

jobs:
  dusk:
    runs-on: ubuntu-latest
    env:
      APP_URL: http://127.0.0.1:8000
      DB_USERNAME: root
      DB_PASSWORD: root
      MAIL_MAILER: log
    steps:
      - uses: actions/checkout@v5
      - run: cp .env.example .env
      - run: composer install --no-progress --prefer-dist --optimize-autoloader
      - run: php artisan key:generate
      - run: php artisan dusk:chrome-driver --detect
      - run: ./vendor/laravel/dusk/bin/chromedriver-linux --port=9515 &
      - run: php artisan serve --no-reload &
      - run: php artisan dusk
```

## Dusk execution flow

```mermaid theme={null}
flowchart TD
    A["php artisan dusk"] --> B["Back up .env"]
    B --> C["Apply .env.dusk.local"]
    C --> D["Start ChromeDriver"]
    D --> E["Run browser tests<br>visit / type / click / assertSee"]
    E --> F{"Failed?"}
    F -->|Yes| G["Save screenshots and logs"]
    F -->|No| H["Tests complete"]
    G --> I["Restore .env"]
    H --> I
```

## Official documentation

<Card title="Laravel Dusk — Official documentation" icon="arrow-right" href="https://laravel.com/docs/dusk">
  For the complete Dusk API (waiting, assertions, keyboard operations, iframe operations, and more), see the official documentation.
</Card>


## Related topics

- [Laravel Maestro — the starter kit orchestrator](/en/blog/maestro-introduction.md)
- [Laravel Sail](/en/sail.md)
- [Develop Laravel packages with Testbench Workbench](/en/advanced/package-workbench.md)
- [April 2026 Laravel updates](/en/blog/changelog/202604.md)
- [Laravel Passkeys initial research (passkeys-server + @laravel/passkeys)](/en/blog/passkeys-introduction.md)
