Why Dawn is a game-changer
Laravel Dusk gave PHP developers a beautiful browser-testing API. But almost every painful thing about a Dusk suite - the flakiness, the CI breakage, the "works on my machine" - traces back to one thing underneath it: WebDriver.
Dawn keeps everything you love about Dusk's API and replaces the layer that causes the pain.
The three problems Dawn removes
1. No more ChromeDriver version roulette
With Dusk you install a ChromeDriver binary and keep its version matched to the Chrome on every developer machine and CI runner. Chrome auto-updates; your pinned driver doesn't; the suite dies with session not created: This version of ChromeDriver only supports Chrome version N.
Dawn uses Playwright, which ships its own matched browser builds:
vendor/bin/playwright-install --browsersThe browser and the automation layer are always in lockstep. Version drift as a category of failure simply disappears.
2. No more polling-loop flakiness
Dusk waits by polling the DOM from PHP in a loop, and many actions fire immediately - so a click can land before the button exists, and you paper over it with ->pause(500) or an extra waitFor. Those sleeps are where suites rot: too short and they flake, too long and the suite crawls.
Dawn delegates waiting to Playwright's native auto-wait. Before every action, Playwright waits for the element to be attached, visible, stable and enabled - then acts. Your explicit waitFor* calls map onto Playwright's own waiting primitives, not onto a re-implemented PHP loop.
// No pause(), no race - Playwright waits for the button to be actionable.
$browser->press('Save')
->waitForText('Saved');The result is fewer flakes and a faster suite, with test bodies you didn't touch. → How waiting works
3. No rewrite, no new framework to learn
This is the part that makes Dawn a drop-in rather than a migration project.
- Your test bodies don't change -
visit,type,press,waitFor,assertSee,within,loginAs,@duskselectors all behave as before. - Your
use Laravel\Dusk\Browser;imports keep working - Dawn aliases the class automatically when Dusk is absent. - Your
@duskattributes,loginAs(), DatabaseMigrations, and screenshot/console artifact paths are all preserved.
You change one line - the base class - and delete the WebDriver plumbing. That's the whole migration. → Migration guide
Side by side
| Dusk (Selenium / ChromeDriver) | Dawn (Playwright) | |
|---|---|---|
| Waiting | PHP-side polling loops | Playwright native auto-wait |
| Flakiness | Actions fire before DOM is ready | Actions wait for actionability |
| Browser setup | ChromeDriver binary + version drift | playwright install, always matched |
| Transport | Selenium wire protocol | Direct CDP - faster |
| Browsers | Chrome | Chromium, Firefox, WebKit |
| Assertions | Point-in-time | Point-in-time (identical) |
| Your test code | - | Unchanged |
What Dawn deliberately is not
Being honest about the boundaries is part of why you can trust the drop-in promise:
- Not a WebDriver driver swap. No
Facebook\WebDriverinterfaces, no W3C endpoint. Dawn reimplements Dusk's API surface, not its transport. - Not a poller. No
sleep()or DOM-polling loops in the source. The single documented exception iswaitUsing(), whose contract is an arbitrary PHP closure Playwright can't evaluate - and it lives in one isolated class that CI guards. - Not a Pest plugin. Class-based and PHPUnit-native, mirroring
DuskTestCase, for teams that can't move to Pest's closure-style browser testing. - Not an HTTP bridge. Your tests stay in PHP; nothing gets rewritten in TypeScript.
Who it's for
If you have an existing Dusk suite and you're tired of fighting ChromeDriver and chasing flaky waits - but you can't afford to rewrite hundreds of browser tests - Dawn is built exactly for you. Swap the base class, keep the suite, get a faster and steadier run.
Ready? → Get started