Skip to main content

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.
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.

Installation

First, install Google Chrome, then add Dusk as a development dependency.
composer require laravel/dusk --dev
php artisan dusk:install
To adjust the ChromeDriver version, use the dusk:chrome-driver command.
# 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.
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.
php artisan dusk:make LoginTest
php artisan dusk
To re-run only the failing tests:
php artisan dusk:fails

A basic example

<?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' => '[email protected]',
        ]);

        $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.
Do not use RefreshDatabase in Dusk tests. As noted in the official documentation, use DatabaseMigrations or DatabaseTruncation to reset data between tests.

Page object pattern

When testing complex screens, generating a page object with dusk:page improves maintainability.
php artisan dusk:page Login
Define url() and elements() in tests/Browser/Pages/Login.php and reuse them from your tests.
use Tests\Browser\Pages\Login;

$browser->visit(new Login)
    ->type('@email', '[email protected]')
    ->type('@password', 'password')
    ->click('@submit')
    ->assertSee('Dashboard');

Screenshots and debugging

Saving screenshots and console logs is effective for investigating failures.
$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.
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

Official documentation

Laravel Dusk — Official documentation

For the complete Dusk API (waiting, assertions, keyboard operations, iframe operations, and more), see the official documentation.
Last modified on July 13, 2026