Locators and auto-waiting
Playwright's locator priority (official guidance) — as the user sees it:
getByRole('button', { name: 'Pay' })— accessibility role + name (most durable)getByLabel('Email')— for form fieldsgetByPlaceholder,getByText— text-basedgetByTestId('checkout-btn')— thedata-testidattribute (agreed with devs)- CSS/XPath — LAST resort; structural chains (
div > div:nth-child(3)) break on refactoring
Auto-waiting: before every action Playwright itself waits for the element to be actionable (visible, enabled, stable, receiving events) — writing sleep() is unnecessary and WRONG.
Strict mode: if a locator matches more than one element, Playwright throws — preventing silently wrong picks. Fixes: make the locator more specific, use filter(), or first()/nth() when a set is intentional.
Chaining and filtering for complex UI: page.getByRole('row').filter({ hasText: 'Order #42' }).getByRole('button', { name: 'Cancel' }).
"Why is sleep bad?" is guaranteed in interviews: a fixed wait either waits TOO LONG (slowing the suite) or TOO LITTLE (flaky). Condition-based waiting (auto-wait, web-first assertions) waits exactly as long as needed — no more, no less.
📚 Sources and documentation
- Locatorsofficialplaywright.dev
- Auto-waiting / actionabilityofficialplaywright.dev
The official list of conditions Playwright waits for before every action.