patterntypescriptMajor
Playwright E2E: use locators over selectors for resilient element targeting
Viewed 0 times
playwright locatorsgetByRolegetByLabeltest resilienceselector strategy
Problem
Playwright tests that use CSS selectors like
.btn-primary or XPath break when developers refactor markup or rename classes. Tests become a maintenance burden rather than a safety net.Solution
Prefer Playwright's semantic locators:
getByRole, getByLabel, getByText, getByTestId. These target elements by their ARIA semantics or explicit test IDs, surviving markup refactors. Fall back to locator('[data-testid=...]') only when semantic options are insufficient.Why
Semantic locators are resilient to styling and structural changes.
getByRole('button', { name: 'Submit' }) will still work after a designer changes the button's class, position, or wrapping element. They also encourage accessible markup.Gotchas
- getByText does substring matching by default; use exact: true to avoid ambiguous matches
- getByRole requires correct ARIA roles in the DOM — if the button is a div, getByRole('button') won't find it
- data-testid attributes must be added by the dev team and kept in sync with the codebase
- Avoid locator chaining beyond 2 levels; it increases brittleness
Code Snippets
Semantic locators vs CSS selectors
// Fragile
await page.click('.btn.btn-primary');
// Resilient
await page.getByRole('button', { name: 'Submit' }).click();
await page.getByLabel('Email address').fill('alice@example.com');
await page.getByTestId('confirm-dialog').getByRole('button', { name: 'Confirm' }).click();Revisions (0)
No revisions yet.