$npx -y skills add LambdaTest/agent-skills --skill laravel-dusk-skillGenerates Laravel Dusk browser tests in PHP. Chrome-based E2E testing for Laravel apps. Use when user mentions "Dusk", "Laravel Dusk", "$browser->visit", "DuskTestCase". Triggers on: "Laravel Dusk", "Dusk test", "$browser->visit", "DuskTestCase".
| 1 | # Laravel Dusk Skill |
| 2 | |
| 3 | For TestMu AI cloud execution, see [reference/cloud-integration.md](reference/cloud-integration.md) and [shared/testmu-cloud-reference.md](../shared/testmu-cloud-reference.md). |
| 4 | |
| 5 | ## Core Patterns |
| 6 | |
| 7 | ### Basic Test |
| 8 | |
| 9 | ```php |
| 10 | <?php |
| 11 | namespace Tests\Browser; |
| 12 | |
| 13 | use Laravel\Dusk\Browser; |
| 14 | use Tests\DuskTestCase; |
| 15 | |
| 16 | class LoginTest extends DuskTestCase |
| 17 | { |
| 18 | public function testLoginWithValidCredentials(): void |
| 19 | { |
| 20 | $this->browse(function (Browser $browser) { |
| 21 | $browser->visit('/login') |
| 22 | ->type('email', 'user@test.com') |
| 23 | ->type('password', 'password123') |
| 24 | ->press('Login') |
| 25 | ->assertPathIs('/dashboard') |
| 26 | ->assertSee('Welcome'); |
| 27 | }); |
| 28 | } |
| 29 | |
| 30 | public function testLoginWithInvalidCredentials(): void |
| 31 | { |
| 32 | $this->browse(function (Browser $browser) { |
| 33 | $browser->visit('/login') |
| 34 | ->type('email', 'wrong@test.com') |
| 35 | ->type('password', 'wrong') |
| 36 | ->press('Login') |
| 37 | ->assertPathIs('/login') |
| 38 | ->assertSee('Invalid credentials'); |
| 39 | }); |
| 40 | } |
| 41 | } |
| 42 | ``` |
| 43 | |
| 44 | ### Browser Methods |
| 45 | |
| 46 | ```php |
| 47 | // Navigation |
| 48 | $browser->visit('/path'); |
| 49 | $browser->back(); |
| 50 | $browser->forward(); |
| 51 | $browser->refresh(); |
| 52 | |
| 53 | // Forms |
| 54 | $browser->type('name', 'value'); |
| 55 | $browser->clear('name'); |
| 56 | $browser->select('select', 'option'); |
| 57 | $browser->check('checkbox'); |
| 58 | $browser->uncheck('checkbox'); |
| 59 | $browser->radio('radio', 'value'); |
| 60 | $browser->attach('file', '/path/to/file'); |
| 61 | $browser->press('Button Text'); |
| 62 | $browser->click('.selector'); |
| 63 | |
| 64 | // Assertions |
| 65 | $browser->assertSee('text'); |
| 66 | $browser->assertDontSee('text'); |
| 67 | $browser->assertPathIs('/expected'); |
| 68 | $browser->assertUrlIs('http://full-url'); |
| 69 | $browser->assertInputValue('name', 'value'); |
| 70 | $browser->assertChecked('checkbox'); |
| 71 | $browser->assertVisible('.element'); |
| 72 | $browser->assertMissing('.element'); |
| 73 | $browser->assertTitle('Page Title'); |
| 74 | $browser->assertPresent('.selector'); |
| 75 | |
| 76 | // Waiting |
| 77 | $browser->waitFor('.element'); |
| 78 | $browser->waitFor('.element', 10); // 10 seconds |
| 79 | $browser->waitUntilMissing('.loading'); |
| 80 | $browser->waitForText('Loaded'); |
| 81 | $browser->waitForLink('Click Me'); |
| 82 | $browser->pause(1000); // milliseconds |
| 83 | ``` |
| 84 | |
| 85 | ### Page Objects |
| 86 | |
| 87 | ```php |
| 88 | <?php |
| 89 | namespace Tests\Browser\Pages; |
| 90 | |
| 91 | use Laravel\Dusk\Page; |
| 92 | |
| 93 | class LoginPage extends Page |
| 94 | { |
| 95 | public function url(): string { return '/login'; } |
| 96 | |
| 97 | public function assert(Browser $browser): void |
| 98 | { |
| 99 | $browser->assertPathIs($this->url()); |
| 100 | } |
| 101 | |
| 102 | public function login(Browser $browser, string $email, string $password): void |
| 103 | { |
| 104 | $browser->type('email', $email) |
| 105 | ->type('password', $password) |
| 106 | ->press('Login'); |
| 107 | } |
| 108 | } |
| 109 | |
| 110 | // Usage |
| 111 | $browser->visit(new LoginPage) |
| 112 | ->login($browser, 'user@test.com', 'password123'); |
| 113 | ``` |
| 114 | |
| 115 | ### Cloud: Override `DuskTestCase::driver()` to return `RemoteWebDriver` with LT caps |
| 116 | |
| 117 | ## Setup: `composer require --dev laravel/dusk && php artisan dusk:install` |
| 118 | |
| 119 | ### Cloud Execution on TestMu AI |
| 120 | |
| 121 | Set `.env` variables: `LT_USERNAME`, `LT_ACCESS_KEY` |
| 122 | |
| 123 | ```php |
| 124 | // tests/DuskTestCase.php |
| 125 | protected function driver() |
| 126 | { |
| 127 | $options = (new ChromeOptions)->addArguments(['--disable-gpu', '--no-sandbox']); |
| 128 | $ltOptions = [ |
| 129 | 'user' => env('LT_USERNAME'), |
| 130 | 'accessKey' => env('LT_ACCESS_KEY'), |
| 131 | 'build' => 'Laravel Dusk Build', |
| 132 | 'name' => $this->getName(), |
| 133 | 'platformName' => 'Windows 11', |
| 134 | 'video' => true, |
| 135 | 'console' => true, |
| 136 | ]; |
| 137 | $options->setExperimentalOption('LT:Options', $ltOptions); |
| 138 | return RemoteWebDriver::create( |
| 139 | 'https://hub.lambdatest.com/wd/hub', $options |
| 140 | ); |
| 141 | } |
| 142 | ``` |
| 143 | ## Run: `php artisan dusk` or `php artisan dusk tests/Browser/LoginTest.php` |
| 144 | |
| 145 | ## Deep Patterns |
| 146 | |
| 147 | See `reference/playbook.md` for production-grade patterns: |
| 148 | |
| 149 | | Section | What You Get | |
| 150 | |---------|-------------| |
| 151 | | §1 Project Setup | Installation, DuskTestCase, .env.dusk configuration | |
| 152 | | §2 Browser Tests | Login flows, forms, multi-step wizards, multiple browsers | |
| 153 | | §3 Page Objects | Page class with elements, custom methods, assertions | |
| 154 | | §4 Components | DatePicker, Modal, reusable component pattern | |
| 155 | | §5 Advanced Interactions | JavaScript, scrolling, drag-and-drop, waiting strategies | |
| 156 | | §6 Database & Data | DatabaseMigrations, factories, screenshots, console logs | |
| 157 | | §7 LambdaTest Integration | Remote WebDriver with LT:Options capabilities | |
| 158 | | §8 CI/CD Integration | GitHub Actions with MySQL, ChromeDriver, artifact upload | |
| 159 | | §9 Debugging Table | 12 common problems with causes and fixes | |
| 160 | | §10 Best Practices | 14-item Lar |