Weave Code
Code Weaver
Helps Laravel developers discover, compare, and choose open-source packages. See popularity, security, maintainers, and scores at a glance to make better decisions.
Feedback
Share your thoughts, report bugs, or suggest improvements.
Subject
Message

Dusk Laravel Package

laravel/dusk

Laravel Dusk is a browser automation and end-to-end testing tool for Laravel. It provides an expressive API for driving real browsers, ships with a standalone Chromedriver (no Selenium/JDK required by default), and can use other Selenium drivers.

View on GitHub
Deep Wiki
Context7
## Getting Started

### Minimal Setup
1. **Installation**:
   ```bash
   composer require --dev laravel/dusk

Run the Dusk installer:

php artisan dusk:install

This sets up ChromeDriver, configures PHPUnit, and generates a base test class.

  1. First Test: Create a test in tests/Browser/ExampleTest.php:

    use Laravel\Dusk\TestCase;
    
    class ExampleTest extends TestCase
    {
        /** @test */
        public function it_loads_the_main_page()
        {
            $this->browse(function ($browser) {
                $browser->visit('/')
                        ->assertSee('Welcome');
            });
        }
    }
    

    Run tests with:

    php artisan dusk
    
  2. Key Files:

    • tests/Browser/ – Store all Dusk tests here.
    • dusk.config.php – Configure drivers, browsers, and environments.
    • phpunit.xml – PHPUnit configuration for Dusk.

Implementation Patterns

Core Workflow

  1. Browser Interaction: Use the $browser instance inside browse() to chain actions:

    $browser->visit('/dashboard')
            ->click('@login-button')
            ->type('@email-input', 'user@example.com')
            ->press('Login')
            ->assertPathIs('/dashboard');
    
  2. Element Selection: Use Dusk selectors (e.g., @id, .class, #element) or custom CSS selectors:

    $browser->click('@submit-button'); // Uses data-dusk attribute
    $browser->assertSee('Success')->click('button[type="submit"]'); // CSS selector
    
  3. Pages & Components: Create reusable page classes (e.g., LoginPage.php) to encapsulate logic:

    namespace Tests\Browser\Pages;
    
    use Laravel\Dusk\Page;
    
    class LoginPage extends Page
    {
        public function __construct()
        {
            $this->url = '/login';
        }
    
        public function submit($email, $password)
        {
            $this->browse(function ($browser) use ($email, $password) {
                $browser->type('@email', $email)
                        ->type('@password', $password)
                        ->click('@login-button');
            });
        }
    }
    

    Use in tests:

    $this->browse(function ($browser) {
        $loginPage = new LoginPage();
        $loginPage->submit('user@example.com', 'password');
    });
    
  4. Assertions: Leverage built-in assertions for UI validation:

    $browser->assertSee('Welcome')
            ->assertDontSee('Error')
            ->assertPathIs('/dashboard')
            ->assertAttribute('value', 'expected', '@input-field');
    
  5. Data-Driven Tests: Use PHPUnit data providers for parameterized tests:

    public function test_login_with_credentials()
    {
        $credentials = [
            ['user@example.com', 'password', true],
            ['wrong@example.com', 'wrong', false],
        ];
    
        foreach ($credentials as [$email, $password, $shouldSucceed]) {
            $this->browse(function ($browser) use ($email, $password, $shouldSucceed) {
                $browser->visit('/login')
                        ->type('@email', $email)
                        ->type('@password', $password)
                        ->click('@login-button');
    
                if ($shouldSucceed) {
                    $browser->assertPathIs('/dashboard');
                } else {
                    $browser->assertSee('Invalid credentials');
                }
            });
        }
    }
    
  6. Debugging Tools:

    • Screenshots: Automatically saved on failure ($browser->screenshot()).
    • Console Logs: Capture logs with $browser->consoleLog().
    • Debugging: Use dd($browser->driver->getCurrentUrl()) or dump($browser->driver->getPageSource()).
  7. Headless Mode: Configure in dusk.config.php:

    'headless' => [
        'chrome' => true,
        'firefox' => false,
    ],
    
  8. Custom Drivers: Extend Laravel\Dusk\Browser or use DUSK_DRIVER_URL to point to a remote Selenium grid.


Gotchas and Tips

Common Pitfalls

  1. Element Not Found:

    • Ensure elements have data-dusk attributes (e.g., data-dusk="login-button").
    • Use waitFor() to handle dynamic content:
      $browser->waitForText('Loading...')->assertDontSee('Loading...');
      
    • Debug with $browser->driver->getPageSource() to inspect the DOM.
  2. Flaky Tests:

    • Add small delays for AJAX-heavy pages:
      $browser->pause(1000); // 1-second pause
      
    • Use waitFor() or waitForElement() to avoid race conditions.
  3. ChromeDriver Issues:

    • Ensure Chrome and Chromedriver versions are compatible.
    • Update Chromedriver via:
      php artisan dusk:chrome-driver
      
    • For CI, use Docker or pre-downloaded binaries to avoid installation delays.
  4. Assertion Failures:

    • Use assertSeeIn() or assertDontSeeIn() for partial text matches:
      $browser->assertSeeIn('body', 'partial text');
      
    • Case-sensitive assertions can fail; use assertSeeIn() with str_contains() if needed.
  5. Environment Configuration:

    • Set APP_ENV=testing and DB_CONNECTION=sqlite_testing in .env.
    • Use DUSK_DRIVER=chrome or DUSK_DRIVER=firefox to override defaults.
  6. Performance:

    • Disable unnecessary features (e.g., smooth scrolling) in DuskTestCase:
      protected function tearDown(): void
      {
          $this->browse(function ($browser) {
              $browser->driver->executeScript("Object.defineProperty(navigator, 'webdriver', {get: () => undefined})");
          });
          parent::tearDown();
      }
      

Pro Tips

  1. Custom Selectors: Extend Dusk’s selector engine by adding a custom resolver:

    $browser->addCustomSelector('custom', function ($selector) {
        return '.custom-class[data-custom="' . $selector . '"]';
    });
    

    Usage:

    $browser->click('custom:user-button');
    
  2. Component Testing: Use component() to test Blade components in isolation:

    $browser->component('alert', ['message' => 'Test'])
            ->assertSee('Test');
    
  3. Parallel Testing: Configure PHPUnit for parallel runs in phpunit.xml:

    <phpunit ...>
        <parallel>
            <processes>4</processes>
        </parallel>
    </phpunit>
    
  4. CI Optimization:

    • Cache Chromedriver in CI (e.g., Docker layers or artifact storage).
    • Use DUSK_HEADLESS=true to skip GUI rendering.
  5. Debugging Helpers:

    • Element Screenshot:
      $browser->screenshotElement('@element')->saveAs('screenshot.png');
      
    • Console Logs:
      $browser->consoleLog()->saveAs('logs.txt');
      
  6. Laravel-Specific Tips:

    • Use actingAs() for authenticated tests:
      $this->browse(function ($browser) {
          $browser->actingAs(User::first())
                  ->visit('/dashboard');
      });
      
    • Reset the database between tests:
      public function tearDown(): void
      {
          Artisan::call('migrate:fresh --env=testing');
          parent::tearDown();
      }
      
  7. Pest Integration: Dusk works seamlessly with Pest. Example:

    it('loads the homepage', function () {
        $this->browse(function ($browser) {
            $browser->visit('/')
                    ->assertSee('Welcome');
        });
    });
    
  8. Custom Commands: Extend Laravel\Dusk\Browser to add domain-specific methods:

    namespace Tests\Browser;
    
    use Laravel\Dusk\Browser;
    
    class CustomBrowser extends Browser
    {
        public function loginAsAdmin()
        {
            $this->type('@email', 'admin@example.com')
                 ->type('@password', 'admin')
                 ->click('@login-button');
        }
    }
    

    Usage in DuskTestCase:

    protected function createBrowser()
    {
        return new CustomBrowser();
    }
    
  9. Handling Iframes: Switch to an iframe using:

    $browser->driver->switchToFrame('iframe-id');
    

    Return to the parent frame with

Weaver

How can I help you explore Laravel packages today?

Conversation history is not saved when not logged in.
Prompt
Add packages to context
No packages found.
hexters/coinpayment
rjcodes/rjcms
act-training/laravel-permissions-manager
alimarchal/laravel-chart-of-accounts
babenkoivan/elastic-scout-driver
mkwebdesign/filament-watchdog-v5
renatomarinho/laravel-page-speed
zedmagdy/filament-business-hours
renatovdemoura/blade-elements-ui
devgeek/beacon-admin
benjamin-rqt/data-watcher-bundle
atriumphp/atrium
sandermuller/package-boost-laravel
sandermuller/boost-skills
redaxo/core
yusufgenc/filament-api-forge
l3aro/rating-star-for-filament
leek/filament-subtenant-scope
anil/file-picker
broqit/fields-ai