Skip to main content
QATraining
Back to curriculum
Chapter 2 of 7

Locators & Auto-Waiting

Write resilient selectors using accessibility-first locators, and stop writing explicit waits forever thanks to Playwright's actionability checks.

15 min guide5 reference questions folded into the guide material
Code samples in
Guided briefing

Locators & Auto-Waiting video demo

A practical screen-share style walkthrough for chapter 2, showing how the Playwright idea works in TypeScript and Java.

Briefing focus

The locator priority

This is a structured lesson briefing. Real video/audio can be added later as a media source.

Estimated time

10 min

  1. 1The locator priority
  2. 2Auto-waiting explained
  3. 3Web-first assertions

Transcript brief

Write resilient selectors using accessibility-first locators, and stop writing explicit waits forever thanks to Playwright's actionability checks. The video brief explains the mental model first, then demonstrates the workflow using the course code samples, and finishes with reliability checks you can apply in CI.

Key takeaways

  • Translate the concept into a maintainable Playwright test.
  • Understand the TypeScript and Java equivalents without changing the test intent.
  • Avoid the common source of flaky or slow end-to-end tests for this topic.

The locator priority

Playwright recommends accessibility-first locators because they double as accessibility checks and survive most UI changes.

getByRole / getByLabelRecommended · accessibility-firstgetByText / getByPlaceholderUser-visible textgetByTestIdWhen semantic locators aren't enoughCSS / XPathAvoid — fragile and implementation-coupledHigher = more resilient to UI changes
Prefer the top of the pyramid — accessibility-visible attributes — over fragile CSS/XPath.
// Role + accessible name — first choice
await page.getByRole('button', { name: 'Sign in' }).click();

// Label text — great for inputs
await page.getByLabel('Email').fill('alex@qatraining.uk');

// Visible text content
await page.getByText('Forgot password?').click();

// Last resort — a stable test id
await page.getByTestId('quiz-submit').click();

// Chain locators for scope
const row = page.getByRole('row', { name: 'Alex Smith' });
await row.getByRole('button', { name: 'Edit' }).click();
The recommended locator API.

Auto-waiting explained

Before every action, Playwright runs a series of actionability checks and re-evaluates them until they pass or the timeout expires. This is why you almost never need an explicit `waitFor`.

1Attached to DOM2Visible3Stable (not animating)4Enabled5Receives eventsPlaywright re-checks every actionability step until timeout
Each action (click, fill, press) loops through these checks until the element is truly ready.
ActionBuilt-in checks
click / dblclickattached · visible · stable · enabled · receives events
fill / typeattached · visible · enabled · editable
check / uncheckattached · visible · stable · enabled · receives events
hoverattached · visible · stable · receives events
press / focusattached · focusable

Stop using sleep()

If you find yourself reaching for waitForTimeout(1000) — stop. Either use an assertion (await expect(...).toBeVisible()) or rely on the action's built-in auto-wait. Fixed timeouts are the #1 cause of flaky E2E tests.

Web-first assertions

Playwright's expect() built-in assertions retry automatically until the matcher passes or the timeout expires. This is the magic that eliminates the ‘try/retry’ helpers you wrote in Selenium.

await expect(page.getByRole('alert')).toHaveText(/saved/i);
await expect(page.getByTestId('cart-count')).toHaveText('3');
await expect(page).toHaveTitle(/dashboard/i);
await expect(page.getByRole('button', { name: 'Submit' })).toBeEnabled();
Retrying assertions replace waitFor loops.

Real-life scenario · Healthcare portal

Killing 300 explicit waits in one afternoon

Situation. A healthcare provider's E2E suite had 300+ custom waitFor helpers around SPA navigations. We replaced them with retrying expect() assertions and role-based locators. 14 flaky tests → 0. Maintenance burden dropped from 6h/week to 30 min/week.

Lesson. Auto-wait + retrying assertions are Playwright's killer features. Adopt them and most ‘flaky’ tests disappear.