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.