Skip to content

Selectors & scoping

Dawn reimplements Dusk's ElementResolver semantics on Playwright locators. Selectors are compiled lazily - the DOM is only queried when an action runs, so Playwright's auto-waiting applies with no find-then-act race.

@dusk selectors

php
$browser->click('@login-button');
// → [dusk="login-button"]

The HTML attribute is configurable, as in Dusk:

php
use Dawn\Dawn;

Dawn::selectorHtmlAttribute('data-testid');

Field resolution

Dusk's resolution orders are preserved:

  • type('email', …)#email by id, else input[name='email'], textarea[name='email'], else the string as a selector;
  • select('role', …) → id, else select[name='role'];
  • check('terms') → id, else input[type=checkbox][name='terms'];
  • press('Save') → as a selector, else by name, else submit value, else button text.

One documented divergence: Dusk tries these candidates one by one; Dawn compiles them into a single CSS list resolved in DOM order. The two only differ when multiple candidates match different elements at the same time.

Scoping with within()

php
$browser->within('.modal', function (Browser $modal) {
    $modal->assertSee('Confirm')
        ->press('OK');
});

Scopes compose by selector-prefixing (body .modal .actions …), exactly like Dusk - including the quirk that #id field lookups bypass the scope (Dusk resolves ids document-wide). elsewhere() escapes the current scope; whenAvailable() waits for the selector, then scopes into it.

Page element aliases

ElementResolver::pageElements() supports Dusk page-object shorthand maps (['@email' => 'input#email-address']), replaced longest-key-first before @ translation - verified against test cases ported from laravel/dusk's own suite. The full Dusk Pages & Components object model (Dawn\Page, Dawn\Component, visit(Page), component()) is supported - see the compatibility table.

Released under the MIT License. Not affiliated with Laravel.