Selectors & Locators
Use role, text, label locators and the Locators API for resilient element selection.
User-Facing Locators
getByRole with name option matches accessible name—buttons, links, headings. getByLabel finds form controls by associated label. getByPlaceholder and getByText cover additional cases.
Playwright generates selectors prioritizing accessibility tree—tests break when UX breaks for assistive tech, aligning quality with user experience.
await page.getByRole("button", { name: "Submit" }).click();
await page.getByLabel("Password").fill("secret");
await page.getByRole("checkbox", { name: "Remember me" }).check();CSS and XPath
page.locator("css=...") and xpath= when no accessible handle exists. data-testid via getByTestId if team convention.
CSS locators chain: page.locator(".card").filter({ hasText: "Premium" }).getByRole("link")
- Avoid brittle selectors tied to CSS modules hash classes
- Prefer filter({ has: locator }) over complex XPath
- Use nth(n) sparingly—indicates missing unique accessible name
await page.getByTestId("checkout-summary");
await page.locator("section.promo").getByRole("button").click();Locators API
Locators are strict by default in actions—error if multiple matches unless intentional. first(), last(), nth() disambiguate. all() returns locator array for iteration.
Locators lazy-evaluate on each action—DOM changes between definition and click handled automatically.
const rows = page.getByRole("row");
await expect(rows).toHaveCount(3);
await rows.filter({ hasText: "Paid" }).getByRole("button", { name: "Refund" }).click();Chaining and Scoping
Locate within parent to narrow scope: page.getByRole("dialog").getByRole("button", { name: "OK" }). frameLocator enters iframes consistently.
Component locators in component testing mirror same API on mounted component.
const modal = page.getByRole("dialog", { name: "Confirm delete" });
await modal.getByRole("button", { name: "Delete" }).click();Codegen and Selector Tools
npx playwright codegen url records actions and generates locators—good starting point, review for quality. Pick Locator option in inspector copies best selector.
Replace codegen CSS with getByRole during test hardening pass.
npx playwright codegen http://localhost:3000