An In-Depth Understanding of getByRole in Playwright

Priyanshu S Avatar

GetByRole in Playwright — Most of us regularly use page.getByRole in Playwright, but I doubt many are not fully aware of its benefits for accessibility testing. Additionally, the examples on the Playwright official website don’t provide detailed explanations on when to use this method and when to avoid it.

This powerful method not only helps us to locate elements on a page but also ensures that accessibility standards are being met.

Surprised? It’s a two-in-one utility in PlayWright that finds elements while simultaneously validating the use of correct ARIA roles. It is the Swiss Army knife of Playwright Locator strategy, helping QAs to both in selecting elements and checking for accessible web design, something that can enhance both usability and compliance with accessibility guidelines.

Interesting, right?

So when you write a locator as below, it not only locates the Buy With Credit Card button, but it also ensures that screen readers will be able to understand this as button, and will read it correctly.

await page.getByRole('button', { name: 'Buy With Credit Card' });

Through this article, I will highlight the advance usage of the Playwright GetByRole locator strategy. As the PlayWright official document only captures the basic examples, which does not provide comprehensive information on usage of GetByRole.

Additionally, I’ll help you to identify situations where GetByRole should be avoided.

I promise, this article will serve as a one-stop solution for understanding the Playwright GetByRole locator strategy using effectively.

The ARIA Roles in HTML

As per the WAI-ARIA Roles guidelines, it is recommended to developers to use native HTML elements like <button>, <input>, <select>, etc., because they inherently support accessibility features.

For PlayWright users, the native HTML elements will work as per their role suggested by WAI-ARIA guidelines.

For native HTML elements, the getByRole works even if their HTML representation does not contain role attribute.

With the help of following table, you would be able to clearly understand what are the native elements in HTML and their corresponding role as per the WAI-ARIA Role guidelines.

HTML native elements with role.
Native HTML elements and their role as per https://www.w3.org/TR/wai-aria/#role_definitions

PlayWright’s getByRole Implementation

PlayWright Implementation of GetByRole method.

The roles are specified as “alert”|”alertdialog”|”application”|”article”| ..etc.

The attribute which getByRole supports are checked?: boolean;
disabled?: boolean;
exact?: boolean;
expanded?: boolean;
includeHidden?: boolean;
level?: number;
name?: string|RegExp;
pressed?: boolean;
selected?: boolean;

getByRole(role: "alert"|"alertdialog"|"application"|"article"|"banner"|"blockquote"|"button"|"caption"|"cell"|"checkbox"|"code"|"columnheader"|"combobox"|"complementary"|"contentinfo"|"definition"|"deletion"|"dialog"|"directory"|"document"|"emphasis"|"feed"|"figure"|"form"|"generic"|"grid"|"gridcell"|"group"|"heading"|"img"|"insertion"|"link"|"list"|"listbox"|"listitem"|"log"|"main"|"marquee"|"math"|"meter"|"menu"|"menubar"|"menuitem"|"menuitemcheckbox"|"menuitemradio"|"navigation"|"none"|"note"|"option"|"paragraph"|"presentation"|"progressbar"|"radio"|"radiogroup"|"region"|"row"|"rowgroup"|"rowheader"|"scrollbar"|"search"|"searchbox"|"separator"|"slider"|"spinbutton"|"status"|"strong"|"subscript"|"superscript"|"switch"|"tab"|"table"|"tablist"|"tabpanel"|"term"|"textbox"|"time"|"timer"|"toolbar"|"tooltip"|"tree"|"treegrid"|"treeitem", options?: {
    checked?: boolean;
    disabled?: boolean;
    exact?: boolean;
    expanded?: boolean;
    includeHidden?: boolean;
    level?: number;
    name?: string|RegExp;
    pressed?: boolean;
    selected?: boolean;
  }): Locator;

,

getByRole in PlayWright for Native HTML Elements

A button with does not have attribute role but still it can’t identified by getByRole in PlayWright as button is an example of native html element.

<div className="mb-6">
        <label className="block mb-2 text-sm font-medium text-gray-700">
          Button:
        </label>
        <button className="px-4 py-2 bg-blue-500 text-white rounded">Click Here</button>
      </div>
await page.getByRole('button', {name: 'Click Here'}).click();
await expect(page.getByRole('button', {name: 'Clicked'})).toBeVisible();

An input check which is having an attribute as aria-checked="true" can also be identified in PlayWright getByRole as

await expect(page.getByRole('checkbox', {selected: true })).toBeVisible();

Another example of list:

<ul>
  <li>Item 1</li>
  <li>Item 2</li>
  <li>Item 3</li>
</ul>

const item1 = await page.getByRole('listitem', { name: 'Item 1' });
const item2 = await page.getByRole('listitem', { name: 'Item 2' });
const item3 = await page.getByRole('listitem', { name: 'Item 3' });

GetByRole in PlayWright for Non-Native Elements

Often, developers use non-native elements to design user interface.

One of the common example of usage of non-native element is div. A button can also be designed as div by having something like:

<div onclick="toggleButton(this)">Click Me</div>

This creates a confusion for PlayWright users to understand whether getByRole will work in this case or not.

The answer is NO, the div is designed to work as button but it is not a native element as suggested by WAI-ARIA. For this div, if we write page.getByRole('button', {name: 'Click Me'}) will result in failure.

As per the guidelines of WAI-ARIA, developer should specify the role of the div. The screen readers will be able to identify is as button only if specifies role as <div onclick="toggleButton(this)" role="button">Click Me</div>

Playwright can locate elements using the getByRole function if a role is defined.

How to understand when to use getByRole?

To make it easier for Playwright users to understand when to use the getByRole function, consider this:

  • For native elements, getByRole will work regardless of whether the role attribute is present.
  • For non-native elements, getByRole will only work if a role attribute is specified.

Isn’t it easy now to understand when to use getByRole?

When to avoid getByRole?

getByRole should be avoided only if a non-native element without role is present in HTML. As explained above, the non-native elements won’t be located by getByRole. In this case, it is recommended to use other method like page.locator() , page.getByText(), etc.

Additionally, GetByRole should be avoided when you are planning to run tests against different languages.

Other benefits of GetByRole

Thought it can’t be completely replaced for accessibility testing, but having locator finding strategy using getByRole at least ensures that screen-readers will work for the given html element. So it is recommended for PlayWright users to prefer getByRole and in case it does not work for any element, a suggestion can be made to developers to fix the HTML to have attributes like role and others as per WAI-ARIA guidelines.

Impact on Test Execution Speed by usage of GetByRole in PlayWright

The following screenshot shows my basic test execution using both getByRole and CSS locator by ID. If you look at the execution time on the right-hand side of each line, you’ll see there’s no significant difference between the two methods: getByRole took 145 ms, while the locator by ID took around 147 ms. Both methods perform equally well, so I don’t see any slowness introduced by the getByRole method, as some have claimed.

However, a more detailed comparison is needed to understand how these methods behave on a complex, dynamic page.

Screenshot showing execution speed for getByRole and css locator

Your subscription encourages me to write more insightful articles.

Subscribe to my newsletter and explore Quality Assurance beyond just manual and automation testing!

We don’t spam! Read our privacy policy for more info.

Thank you for reading this post, don’t forget to subscribe!

Priyanshu S Avatar