Essentials

Locators, actions, and assertions side by side. Copy a line, drop it into your test, keep moving.

PlaywrightPHP Essentials
playwright-php.dev

Locators

Find the element the way a user would. Locators are lazy: nothing touches the page until an action or an assertion runs.

Call Note
getByRole('button', ['name' => 'Save']) Preferred: how users perceive it
getByLabel('Email') Form fields, by their label
getByText('Welcome') Visible text, substring by default
getByPlaceholder('Search') Inputs with no label
getByTestId('cart-total') Escape hatch, for data-testid
getByTitle('Close') The title attribute
getByAltText('Logo') Images, by alt text
locator('.card')->first() CSS or XPath, when you must
->filter(['hasText' => 'new']) Narrow any locator
->and($other) / ->or($other) Combine two locators
->first() ->last() ->nth(2) Pick one out of many
->count() / ->all() How many, and each of them

Actions

Each action waits for the actionability checks that apply to it. If you are reaching for sleep(), assert or wait for the page state the next step actually needs.

Call Note
->click() / ->dblclick() Waits for actionable, then clicks
->fill('ada@example.com') Clears, then types
->clear() Empties the field
->press('Enter') One key, including Meta+K
->type('slowly') Key by key, for live search
->check() / ->uncheck() Checkboxes and radios
->selectOption('fr') Dropdowns
->hover() / ->dragTo($target) Pointer gestures
->setInputFiles('cv.pdf') Uploads, with no dialog to handle
->focus() / ->blur() Move focus around
$page->goto('/checkout') Navigates, and waits for load

Assertions

Assert on the locator, not on a value you pulled out of it. expect() retries until it passes or the timeout runs out; a plain assertSame($el->textContent(), ...) checks once and flakes.

Call Note
expect($el)->toBeVisible() Retries until it passes or times out
->toContainText('Saved') Substring
->toHaveText('Saved') Whole text
->toHaveValue('42') Inputs and selects
->toHaveCount(3) List length, without the flake
->toBeChecked() / ->toBeEnabled() State
->toHaveAttribute('href', '/x') Attributes
->toHaveClass('is-open') Classes
expect($page)->toHaveURL('/done') Page level
expect($page)->toHaveTitle('Docs') Page level
->not()->toBeVisible() Negate anything
->withTimeout(10_000) Override the wait, for one check

Engines

Call Note
Playwright::chromium() Playwright-managed Chromium by default
Playwright::firefox() Playwright-managed Firefox
Playwright::webkit() Playwright's WebKit build, not installed Safari
->withHeadless(false)->launch() Watch it drive itself
PlaywrightFactory::create() The client, when you need several contexts
$context->newPage() A tab in that session

Devices

Ships separately, in playwright-php/devices.

php
use Playwright\Device\DeviceRegistry;

$device = (new DeviceRegistry())->get('iPhone 15 Pro');
$device->landscape();

Setup

bash
composer require --dev playwright-php/playwright
vendor/bin/playwright-install chromium

Trace a failure

php
$context->startTracing($page, ['screenshots' => true, 'snapshots' => true]);
// ... the run ...
$context->stopTracing($page, 'trace.zip');

See record a trace for the whole loop.

Deeper reads

PHP 8.2+ · MIT · playwright-php.dev/cheatsheets/essentials Not affiliated with Microsoft