Skip to content

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:

bash
vendor/bin/playwright-install --browsers

The 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.

php
// 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, @dusk selectors all behave as before.
  • Your use Laravel\Dusk\Browser; imports keep working - Dawn aliases the class automatically when Dusk is absent.
  • Your @dusk attributes, 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)
WaitingPHP-side polling loopsPlaywright native auto-wait
FlakinessActions fire before DOM is readyActions wait for actionability
Browser setupChromeDriver binary + version driftplaywright install, always matched
TransportSelenium wire protocolDirect CDP - faster
BrowsersChromeChromium, Firefox, WebKit
AssertionsPoint-in-timePoint-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\WebDriver interfaces, 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 is waitUsing(), 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

Released under the MIT License. Not affiliated with Laravel.