Files
claude-skills-reference/engineering-team/playwright-pro/reference/locators.md
Alireza Rezvani d33d03da50 feat: add playwright-pro plugin — production-grade Playwright testing toolkit (#254)
Complete Claude Code plugin with:
- 9 skills (/pw:init, generate, review, fix, migrate, coverage, testrail, browserstack, report)
- 3 specialized agents (test-architect, test-debugger, migration-planner)
- 55 test case templates across 11 categories (auth, CRUD, checkout, search, forms, dashboard, settings, onboarding, notifications, API, accessibility)
- TestRail MCP server (TypeScript) — 8 tools for bidirectional sync
- BrowserStack MCP server (TypeScript) — 7 tools for cross-browser testing
- Smart hooks (auto-validate tests, auto-detect Playwright projects)
- 6 curated reference docs (golden rules, locators, assertions, fixtures, pitfalls, flaky tests)
- Leverages Claude Code built-ins (/batch, /debug, Explore subagent)
- Zero-config for core features; TestRail/BrowserStack via env vars
- Both TypeScript and JavaScript support throughout

Co-authored-by: Leo <leo@openclaw.ai>
2026-03-05 13:50:05 +01:00

2.1 KiB

Locator Priority

Use the first option that works:

Priority Locator Use for
1 getByRole('button', { name: 'Submit' }) Buttons, links, headings, form elements
2 getByLabel('Email address') Form fields with associated labels
3 getByText('Welcome back') Non-interactive text content
4 getByPlaceholder('Search...') Inputs with placeholder text
5 getByAltText('Company logo') Images with alt text
6 getByTitle('Close dialog') Elements with title attribute
7 getByTestId('checkout-summary') When no semantic option exists
8 page.locator('.legacy-widget') CSS/XPath — absolute last resort

Role Locator Cheat Sheet

// Buttons — <button>, <input type="submit">, [role="button"]
page.getByRole('button', { name: 'Save changes' })

// Links — <a href>
page.getByRole('link', { name: 'View profile' })

// Headings — h1-h6
page.getByRole('heading', { name: 'Dashboard', level: 1 })

// Text inputs — by label association
page.getByRole('textbox', { name: 'Email' })

// Checkboxes
page.getByRole('checkbox', { name: 'Remember me' })

// Radio buttons
page.getByRole('radio', { name: 'Monthly billing' })

// Dropdowns — <select>
page.getByRole('combobox', { name: 'Country' })

// Navigation
page.getByRole('navigation', { name: 'Main' })

// Tables
page.getByRole('table', { name: 'Recent orders' })

// Rows within tables
page.getByRole('row', { name: /Order #123/ })

// Tab panels
page.getByRole('tab', { name: 'Settings' })

// Dialogs
page.getByRole('dialog', { name: 'Confirm deletion' })

// Alerts
page.getByRole('alert')

Filtering and Chaining

// Filter by text
page.getByRole('listitem').filter({ hasText: 'Product A' })

// Filter by child locator
page.getByRole('listitem').filter({
  has: page.getByRole('button', { name: 'Buy' })
})

// Chain locators
page.getByRole('navigation').getByRole('link', { name: 'Settings' })

// Nth match
page.getByRole('listitem').nth(0)
page.getByRole('listitem').first()
page.getByRole('listitem').last()