All challenges · Foundations

Challenge 2 of 29 · Beginner-friendly · Foundations

Click a Button with getByRole

Find a control the way a user does, by its role and visible name, and act on it. You work out which control produces the result the challenge asks for.

Skills you will practise

  • locators
  • getByRole
  • click

The concept

A user does not see div.btn-primary-2. They see a button that says “Save”. Playwright's getByRole() locates elements the same way: by their accessible role (button, link, checkbox) and their accessible name, which is usually the visible text or an aria-label.

Role-based locators are the first choice recommended in Playwright's own docs because they survive redesigns. If a developer swaps a class name or moves a button into a new wrapper, the role and name usually stay the same. They also nudge you towards accessible markup: if you cannot find a button by role, a screen reader user probably cannot either.

Locators in Playwright are lazy and strict. A locator is not resolved until you act on it, and if it matches more than one element when you click, Playwright throws rather than guessing.

The fragile version

Fragile
await page.locator('.btn.btn-primary:nth-child(2)').click();

Why it breaks: This depends on styling classes and DOM order. Add a new button, reorder the toolbar or rename a CSS class and the test either fails or, worse, clicks the wrong control.

A robust Playwright version

Robust
await page.getByRole('button', { name: 'Save' }).click();
// If several buttons share a name, narrow the scope:
await page.getByRole('dialog').getByRole('button', { name: 'Save' }).click();

The locator describes what the user sees. Scoping to a container resolves ambiguity without relying on position.

This is a general example on a made-up page, not the challenge’s reference solution.

Common mistakes

  • Using .first() or nth() to silence a strict-mode error instead of scoping properly.
  • Matching names loosely: name: 'Save' also matches “Save draft” unless you pass exact: true.
  • Clicking an element that looks like a button but has no button role (a styled div).

FAQ

Why does Playwright say my locator resolved to 2 elements?

Strict mode: actions need exactly one match. Make the name more specific, use exact: true, or scope to a parent region.

Is getByRole better than CSS selectors?

For user-facing controls, usually yes. It is tied to role and name rather than implementation details, so it changes less often.

How do I find the accessible name of a button?

Open browser DevTools, inspect the element and check the Accessibility pane, or use Playwright's codegen / pick locator tool.

Try it

Practise this in Challenge 2. You write the code in the browser editor with no setup. It runs in a fresh Chromium, a hidden validator checks what actually happened, and you get pass or fail, the logs and a video of the run. Challenges 1 to 10 are open without an account; create a free one any time to keep your progress. The reference solution and the hidden validator are shown only after you pass. We never publish solutions here.