Roadmap
Selector Foundations Beginner
Playwright locators inherit CSS awareness and layer on
modern pseudo selectors such as :has(),
:text(), and :nth-match(). Start with
deterministic hooks whenever you can.
Static locator checklist
- Prefer semantic IDs (
#static-username). -
Use
data-testordata-testidattributes for automation. -
Scope by component (
.login-form input[name='static-password']). - Add a short assertion so the selector fails loudly.
locator() auto-waits for the
element to be actionable. Avoid page.waitForTimeout -
let locators synchronize the UI for you.
Intermediate Patterns Skilled
Once the DOM becomes noisy, compose locators by combining attribute wildcards, structural filters, and scoping.
| Pattern | When to use | Example |
|---|---|---|
[data-row-id^='user-'] |
ID prefixes (server-generated handles). |
page.locator("[data-row-id^='user-']").first()
|
.feed-card:has-text('Pinned') |
Cards or rows with unique copy. |
page.locator("li.feed-card:has-text('Pinned')")
|
:nth-match(locator, index) |
Multiple identical CTAs. | page.locator("button.promote-btn").nth(1) |
Advanced Dynamic Targeting Advanced
Complex enterprise apps often generate GUID-based IDs and nested components. Combine Playwright-only capabilities with fallback XPath for the rare edge case.
Debugging & Anti-Flake Expert
Bad selectors usually manifest as flaky tests. Instrument your locators the same way you observe API calls.
-
Use
locator.highlight()in headed mode: Keep a helper that callspage.pause()and highlights the selector so you can visually confirm the match. -
Leverage trace viewer:
npx playwright show-tracedisplays animations, DOM snapshots, and the exact selector Playwright attempted. -
Record custom data hooks: Ask frontend teams to
add
data-qa/data-testidattributes as part of their definition of done to guarantee future proof selectors.
PlaywrightSelectorTest so you can iterate on selectors
in isolation without touching production UIs.