--- name: laravel-dusk description: Laravel Dusk - Browser automation and testing API for Laravel applications. Use when writing browser tests, automating UI testing, testing JavaScript interactions, or implementing end-to-end tests in Laravel. --- # Laravel Dusk Skill Comprehensive assistance with Laravel Dusk browser automation and testing, providing expert guidance on writing expressive, easy-to-use browser tests for your Laravel applications. ## When to Use This Skill This skill should be triggered when: - Writing or debugging browser automation tests for Laravel - Testing user interfaces and JavaScript interactions - Implementing end-to-end (E2E) testing workflows - Setting up automated UI testing in Laravel applications - Working with form submissions, authentication flows, or page navigation tests - Configuring ChromeDriver or alternative browser drivers - Using the Page Object pattern for test organization - Testing Vue.js components or waiting for JavaScript events - Troubleshooting browser test failures or timing issues ## Quick Reference ### 1. Basic Browser Test ```php public function testBasicExample(): void { $this->browse(function (Browser $browser) { $browser->visit('/login') ->type('email', 'user@example.com') ->type('password', 'password') ->press('Login') ->assertPathIs('/home'); }); } ``` ### 2. Using Dusk Selectors (Recommended) ```html ``` ```php // In your test - use @ prefix for dusk selectors $browser->type('@email-input', 'user@example.com') ->click('@login-button'); ``` ### 3. Testing Multiple Browsers ```php public function testMultiUserInteraction(): void { $this->browse(function (Browser $first, Browser $second) { $first->loginAs(User::find(1)) ->visit('/home'); $second->loginAs(User::find(2)) ->visit('/home'); }); } ``` ### 4. Waiting for Elements ```php // Wait for element to appear $browser->waitFor('.modal') ->assertSee('Confirmation Required'); // Wait for text to appear $browser->waitForText('Hello World'); // Wait for JavaScript condition $browser->waitUntil('App.data.servers.length > 0'); // Wait when element is available $browser->whenAvailable('.modal', function (Browser $modal) { $modal->assertSee('Delete Account') ->press('OK'); }); ``` ### 5. Form Interactions ```php // Text input $browser->type('email', 'user@example.com') ->append('notes', 'Additional text') ->clear('description'); // Dropdown selection $browser->select('size', 'Large') ->select('categories', ['Art', 'Music']); // Multiple // Checkboxes and radio buttons $browser->check('terms') ->radio('gender', 'male'); // File upload $browser->attach('photo', __DIR__.'/photos/profile.jpg'); ``` ### 6. Page Object Pattern ```php // Generate page object // php artisan dusk:page Login // app/tests/Browser/Pages/Login.php class Login extends Page { public function url(): string { return '/login'; } public function elements(): array { return [ '@email' => 'input[name=email]', '@password' => 'input[name=password]', '@submit' => 'button[type=submit]', ]; } public function login(Browser $browser, $email, $password): void { $browser->type('@email', $email) ->type('@password', $password) ->press('@submit'); } } // Use in test $browser->visit(new Login) ->login('user@example.com', 'password') ->assertPathIs('/dashboard'); ``` ### 7. Browser Macros (Reusable Methods) ```php // In AppServiceProvider or DuskServiceProvider use Laravel\Dusk\Browser; Browser::macro('scrollToElement', function (string $element) { $this->script("$('html, body').animate({ scrollTop: $('{$element}').offset().top }, 0);"); return $this; }); // Use in tests $browser->scrollToElement('#footer') ->assertSee('Copyright 2024'); ``` ### 8. Database Management in Tests ```php use Illuminate\Foundation\Testing\DatabaseMigrations; use Illuminate\Foundation\Testing\DatabaseTruncation; class ExampleTest extends DuskTestCase { // Option 1: Run migrations before each test (slower) use DatabaseMigrations; // Option 2: Truncate tables after first migration (faster) use DatabaseTruncation; // Exclude specific tables from truncation protected $exceptTables = ['migrations']; } ``` ### 9. JavaScript Execution ```php // Execute JavaScript $browser->script('document.documentElement.scrollTop = 0'); // Get JavaScript return value $path = $browser->script('return window.location.pathname'); // Wait for reload after action $browser->waitForReload(function (Browser $browser) { $browser->press('Submit'); })->assertSee('Success'); ``` ### 10. Common Assertions ```php // Page assertions $browser->assertPathIs('/dashboard') ->assertRouteIs('dashboard') ->assertTitle('Dashboard') ->assertSee('Welcome Back') ->assertDontSee('Error'); // Form assertions $browser->assertInputValue('email', 'user@example.com') ->assertChecked('remember') ->assertSelected('role', 'admin') ->assertEnabled('submit-button'); // Element assertions $browser->assertVisible('.success-message') ->assertMissing('.error-alert') ->assertPresent('button[type=submit]'); // Authentication assertions $browser->assertAuthenticated() ->assertAuthenticatedAs($user); ``` ## Key Concepts ### Dusk Selectors vs CSS Selectors **Dusk selectors** (recommended) use HTML `dusk` attributes that won't change with UI updates: - More stable than CSS classes or IDs - Explicitly mark elements for testing - Use `@` prefix in tests: `$browser->click('@submit-button')` - Add to HTML: `` **CSS selectors** are more brittle but sometimes necessary: - `.class-name`, `#id`, `div > button` - Can break when HTML structure changes - Use when you don't control the HTML ### Waiting Strategies **Always wait explicitly** rather than using arbitrary pauses: - `waitFor('.selector')` - Wait for element to exist - `waitUntilMissing('.selector')` - Wait for element to disappear - `waitForText('text')` - Wait for text to appear - `waitUntil('condition')` - Wait for JavaScript condition - `whenAvailable('.selector', callback)` - Run callback when available ### Page Objects Organize complex test logic into **Page classes**: - Define URL, assertions, and element selectors - Create reusable methods for page-specific actions - Improve test readability and maintainability - Generate with: `php artisan dusk:page PageName` ### Browser Macros Define **reusable browser methods** for common patterns: - Register in service provider's `boot()` method - Use across all tests - Chain like built-in methods - Example: scrolling, modal interactions, custom assertions ## Reference Files This skill includes comprehensive documentation in `references/`: - **other.md** - Complete Laravel Dusk documentation covering: - Installation and configuration - ChromeDriver management - Test generation and execution - Browser interaction methods - Form handling and file uploads - Waiting strategies and assertions - Page Objects and Components patterns - CI/CD integration examples Use the reference file when you need: - Detailed API documentation for specific methods - Complete list of available assertions (70+) - Configuration options for different environments - Advanced topics like iframes, JavaScript dialogs, or keyboard macros ## Working with This Skill ### For Beginners 1. **Start with basic tests**: Use simple `visit()`, `type()`, `press()`, and `assertSee()` methods 2. **Use Dusk selectors**: Add `dusk` attributes to your HTML for stable selectors 3. **Learn waiting**: Always use `waitFor()` instead of `pause()` for reliable tests 4. **Run tests**: Execute with `php artisan dusk` to see results ### For Intermediate Users 1. **Implement Page Objects**: Organize complex tests with the Page pattern 2. **Use database traits**: Choose between `DatabaseMigrations` or `DatabaseTruncation` 3. **Create browser macros**: Define reusable methods for common workflows 4. **Test authentication**: Use `loginAs()` to bypass login screens 5. **Handle JavaScript**: Use `waitUntil()` for dynamic content and AJAX ### For Advanced Users 1. **Multi-browser testing**: Test real-time features with multiple browsers 2. **Custom waiting logic**: Use `waitUsing()` for complex conditions 3. **Component pattern**: Create reusable components for shared UI elements 4. **CI/CD integration**: Set up Dusk in GitHub Actions, Travis CI, or other platforms 5. **Alternative drivers**: Configure Selenium Grid or other browsers beyond ChromeDriver ### Navigation Tips - **Quick examples**: Check the Quick Reference section above for common patterns - **Method documentation**: See `other.md` for complete API reference - **Assertions list**: Reference file contains all 70+ available assertions - **Configuration**: Check reference file for environment setup and driver options - **Best practices**: Look for "Best Practices" section in reference documentation ## Installation & Setup ```bash # Install Laravel Dusk composer require laravel/dusk --dev # Run installation php artisan dusk:install # Update ChromeDriver php artisan dusk:chrome-driver # Make binaries executable (Unix) chmod -R 0755 vendor/laravel/dusk/bin/ # Run tests php artisan dusk ``` ## Common Commands ```bash # Generate new test php artisan dusk:make LoginTest # Generate page object php artisan dusk:page Dashboard # Generate component php artisan dusk:component Modal # Run all tests php artisan dusk # Run specific test php artisan dusk tests/Browser/LoginTest.php # Run failed tests only php artisan dusk:fails # Run with filter php artisan dusk --group=authentication # Update ChromeDriver php artisan dusk:chrome-driver --detect ``` ## Resources ### Official Documentation - Laravel Dusk Documentation: https://laravel.com/docs/12.x/dusk - API Reference: See `references/other.md` for complete method listings ### Common Patterns in Reference Files The reference documentation includes: - 70+ assertion methods with descriptions - Complete form interaction API - Waiting strategies and timing best practices - Page Object pattern examples - Browser macro definitions - CI/CD configuration examples - Environment-specific test setup ## Best Practices 1. **Use Dusk selectors** (`dusk` attributes) instead of CSS classes for stability 2. **Wait explicitly** with `waitFor()` methods instead of arbitrary `pause()` 3. **Organize with Page Objects** for complex test scenarios 4. **Leverage database truncation** for faster test execution 5. **Create browser macros** for frequently repeated actions 6. **Scope selectors** with `with()` or `elsewhere()` for specific page regions 7. **Test user behavior** rather than implementation details 8. **Use authentication shortcuts** like `loginAs()` to skip login flows 9. **Take screenshots** with `screenshot()` for debugging failures 10. **Group related tests** and use `--group` flag for targeted execution ## Troubleshooting ### Common Issues **ChromeDriver version mismatch:** ```bash php artisan dusk:chrome-driver --detect ``` **Elements not found:** - Use `waitFor('.selector')` before interacting - Check if element is in an iframe - Verify selector with browser dev tools **Tests failing randomly:** - Replace `pause()` with explicit waits - Increase timeout: `waitFor('.selector', 10)` - Use `waitUntil()` for JavaScript conditions **Database state issues:** - Use `DatabaseTruncation` trait - Reset data in `setUp()` method - Check for transactions in application code ## Notes - Laravel Dusk uses ChromeDriver by default (no Selenium/JDK required) - Supports alternative browsers via Selenium WebDriver protocol - Tests are stored in `tests/Browser` directory - Page objects go in `tests/Browser/Pages` - Screenshots saved to `tests/Browser/screenshots` on failure - Console logs saved to `tests/Browser/console` for debugging