wpstarter/dusk
Laravel Dusk browser automation and testing for WP Starter/Laravel-style apps. Write expressive end-to-end tests using a standalone Chromedriver by default (no JDK/Selenium required), with the option to use other Selenium drivers.
Installation:
composer require --dev laravel/dusk
Laravel Dusk includes a DuskTestCase base class and a Browser class for testing.
Configuration: Run the Dusk installer:
php artisan dusk:install
This sets up the necessary ChromeDriver and configures the DuskTestCase.
First Test:
Create a test file in tests/Browser/ExampleTest.php:
<?php
namespace Tests\Browser;
use Laravel\Dusk\Browser;
use Tests\DuskTestCase;
class ExampleTest extends DuskTestCase
{
/** @test */
public function it_loads_the_homepage()
{
$this->browse(function (Browser $browser) {
$browser->visit('/')
->assertSee('Welcome');
});
}
}
Run Tests:
php artisan dusk
public function it_logs_in()
{
$this->browse(function (Browser $browser) {
$browser->visit('/login')
->type('email', '[email protected]')
->type('password', 'password')
->press('Login')
->assertPathIs('/dashboard');
});
}
public function it_submits_a_form()
{
$this->browse(function (Browser $browser) {
$browser->visit('/contact')
->type('name', 'John Doe')
->select('country', 'United States')
->press('Submit')
->assertSee('Thank you!');
});
}
public function it_asserts_dynamic_content()
{
$this->browse(function (Browser $browser) {
$browser->visit('/posts')
->waitForText('Post Title')
->assertSee('Post Title')
->assertSeeIn('@posts', 'Published');
});
}
public function it_asserts_vue_data()
{
$this->browse(function (Browser $browser) {
$browser->visit('/dashboard')
->assertVue('count', 5)
->assertVueIsNot('error', null);
});
}
public function it_takes_responsive_screenshots()
{
$this->browse(function (Browser $browser) {
$browser->visit('/dashboard')
->resize(1920, 1080)
->screenshot('desktop')
->resize(375, 812)
->screenshot('mobile');
});
}
Middleware: Use withSession() to test authenticated routes:
$this->browse(function (Browser $browser) {
$browser->withSession(function ($browser) {
$browser->loginAs($user)
->visit('/admin')
->assertSee('Admin Panel');
});
});
Custom Commands: Extend Browser for reusable actions:
use Laravel\Dusk\Browser;
class CustomBrowser extends Browser
{
public function fillProfile($name, $email)
{
$this->type('name', $name)
->type('email', $email);
}
}
Headless Mode: Run tests without opening a browser:
php artisan dusk --headless
Slow Tests:
sleep(); use waitFor() methods like waitForText() or waitForLocation().$browser->waitForText('Loading...')->assertDontSee('Loading...');
Flaky Selectors:
//div[2].elseWhenAvailable() for fallback selectors:
$browser->click('@submit-button')->elseWhenAvailable('@fallback-submit');
ChromeDriver Issues:
php artisan dusk:chrome-driver
Vue.js Quirks:
assertVue() with the correct syntax:
// Vue 2 (Options API)
$browser->assertVue('count', 5);
// Vue 3 (Composition API)
$browser->assertVue('count.value', 5);
Assertion Failures:
->screenshot() before assertions to debug:
$browser->assertSee('Error')->screenshot('error-state');
phpunit.xml:
<env name="DUSK_CAPTURE_SOURCE" value="true"/>
Log Browser Actions:
Enable debug mode in DuskTestCase:
protected $debug = true;
Inspect Elements:
Use pause() to manually inspect the page:
$browser->pause(5); // Pauses for 5 seconds
Custom Error Handling:
Override failed() in DuskTestCase:
protected function failed(TestResult $result)
{
$this->browse(function (Browser $browser) {
$browser->screenshot('failure-' . $result->test->getName());
});
}
Custom Assertions:
Extend Browser to add assertions:
class CustomBrowser extends Browser
{
public function assertTableRowExists($rowText)
{
$this->assertSee($rowText);
}
}
Hooks:
Use setUp() and tearDown() in DuskTestCase:
protected function setUp(): void
{
parent::setUp();
$this->artisan('migrate:fresh');
}
Configuration:
Override Dusk settings in phpunit.xml:
<env name="DUSK_BROWSER" value="chrome"/>
<env name="DUSK_HEADLESS" value="true"/>
Parallel Testing: Use Pest for parallel test execution:
composer require --dev pestphp/pest --dev pestphp/pest-plugin-laravel
Update phpunit.xml to use Pest’s parallelizer.
How can I help you explore Laravel packages today?