Skip to content

getByRole

getByRole queries the accessibility tree — the same structure screen readers use. It is Playwright's most recommended locator for interactive elements.

Roles and Accessible Names

Every meaningful UI control has an implicit or explicit ARIA role: button, link, textbox, checkbox, heading, etc. The accessible name comes from visible text, aria-label, or associated <label>.

getByRole('button', { name: 'Save' }) finds a button whose accessible name includes 'Save'. Use { exact: true } when partial matches are too loose.

await page.getByRole('link', { name: 'Documentation' }).click();
await page.getByRole('heading', { level: 1 }).toBeVisible();
await page.getByRole('checkbox', { name: 'Accept terms' }).check();
await page.getByRole('combobox', { name: 'Country' }).selectOption('US');

Roles match ARIA semantics — a <div onclick> without role won't appear as button.

Common Roles

button | link | textbox | checkbox | radio
heading | listitem | row | cell | dialog
navigation | main | alert | status
  • Match role to element semantics, not visual appearance.
  • name option filters by accessible name (substring by default).
  • checked, expanded, selected refine form and menu locators.
  • Headings support { level: 1 } through { level: 6 }.

getByRole Examples

Everyday patterns for typical UI controls.

UI Element Locator
Submit button getByRole('button', { name: 'Submit' })
Nav link getByRole('link', { name: 'Home' })
Email field getByRole('textbox', { name: 'Email' })
Modal getByRole('dialog')
Error alert getByRole('alert')
Data table row getByRole('row', { name: 'John' })
Menu item getByRole('menuitem', { name: 'Copy' })
Tab getByRole('tab', { name: 'Settings' })

Implicit vs Explicit Roles

Native HTML elements get implicit roles: <button> → button, <a href> → link. Custom components need explicit role attributes or you should use getByTestId / getByLabel instead.

  • If getByRole fails, check Accessibility pane in DevTools.
  • Ask developers to use semantic HTML before adding test ids.
  • Radix/shadcn components often expose correct roles when composed properly.

Using the name Option

When multiple elements share a role, pass { name: 'Submit' } matching visible text or aria-label. Without name, strict mode may fail if more than one match exists.

Common Mistakes

  • Using role button on non-button elements without verifying accessibility tree.
  • Omitting name and matching dozens of generic buttons.
  • Confusing textbox with searchbox or spinbutton.
  • Not using { exact: true } when 'Save' matches 'Save draft'.

Key Takeaways

  • getByRole aligns tests with accessibility and user perception.
  • Accessible name comes from text, labels, or aria-label.
  • Semantic HTML makes role locators easy; fix markup when they fail.
  • Use role-specific options like checked and level.

Pro Tip

Enable axe in dev — if a control has no accessible name, getByRole will struggle and real users with screen readers will too.