71 / 139 · 13 Browser Automation with Playwright · Locator Strategies← prev⊞ allnext →☰ Read as one page
7.2The Locator Hierarchy
Playwright recommends locators in this priority order:
| Priority | Locator | Example | Why |
|---|---|---|---|
| 1 | Role | getByRole('button', { name: 'Submit' }) |
Mirrors accessibility tree; resilient to markup changes |
| 2 | Text | getByText('Sign in') |
User-visible; breaks only when copy changes |
| 3 | Test ID | getByTestId('login-form') |
Explicit contract between dev and test |
| 4 | Label | getByLabel('Email address') |
Form fields via associated label |
| 5 | Placeholder | getByPlaceholder('Enter email') |
Inputs without visible labels |
| 6 | CSS/XPath | page.locator('.btn-primary') |
Last resort for complex DOM traversal |
Role-Based Locators (Preferred)
Role locators use the accessibility tree, not the DOM structure. They find elements the way a screen reader would — which means they are resilient to HTML refactoring.
// Finds <button>, <input type="submit">, or any element with role="button"
await page.getByRole('button', { name: 'Submit' }).click();
// Finds <a> elements or elements with role="link"
await page.getByRole('link', { name: 'Sign up' }).click();
// Finds <h1>–<h6> or elements with role="heading"
await expect(page.getByRole('heading', { name: 'Dashboard' })).toBeVisible();
// Checkboxes and radio buttons
await page.getByRole('checkbox', { name: 'Remember me' }).check();
Text Locators
// Exact text
await page.getByText('Welcome back', { exact: true }).click();
// Substring match (default)
await page.getByText('Welcome').click();
// Regex
await page.getByText(/welcome/i).click();
Test ID Locators
When role and text locators are not viable (e.g., elements without meaningful text or multiple identical elements), test IDs provide a stable contract.
// In the application: <div data-testid="user-profile">...</div>
await page.getByTestId('user-profile').click();
// Configure the attribute name in playwright.config.ts:
// use: { testIdAttribute: 'data-qa' }
Label and Placeholder Locators
// Finds input by its associated <label>
await page.getByLabel('Email address').fill('user@example.com');
// Finds input by placeholder text
await page.getByPlaceholder('Search products').fill('laptop');