2026-1-18

Handling of the presentation role not suggested by Playwright Inspector

When dealing with accessible locators in Playwright, I encountered a dilemma: "How is an element with role='presentation' handled by the getByRole API, and should it be handled?" This was because, although Playwright Codegen cannot generate elements with role='presentation', I wanted to actively use the getByRole API to make E2E test code as stable as possible.

This article organizes the best practices based on TypeScript type definitions, selector generators, and Codegen implementations.

The conclusion is: "While it is possible to specify the presentation role with the getByRole API, it is not recommended, and you should avoid specifying locators with the presentation role whenever possible."

getByRole API Type Definitions

https://github.com/microsoft/playwright/blob/main/packages/playwright-client/types/types.d.ts

  getByRole(
    role:
      | "alert"
      | "alertdialog"
      // (omitted)
      | "presentation"
      // (omitted)
    options?: {
    // (omitted)
  }): Locator;

page.getByRole is defined in the above section and lists all non-abstract roles defined by WAI-ARIA. Since presentation is included here, page.getByRole('presentation') can be called type-safely in TypeScript. In other words, since the API level does not restrict role values, it is possible to specify the presentation role with the getByRole API, as mentioned at the beginning.

Internal Implementation of Selector Generator

https://github.com/microsoft/playwright/blob/daae9b5d7964432bed519ca3b462ca89e1012566/packages/injected/src/selectorGenerator.ts

Playwright Inspector / Codegen automatically generates candidates for getByRole and other selectors internally using generateSelector. This feature suggests the optimal locator when you click on an element on the browser screen.

In this implementation, roles are pushed as candidates in two places: buildNoTextCandidates and buildTextCandidates methods. Both have the following condition:

 if (ariaRole && !['none', 'presentation'].includes(ariaRole))
    candidates.push({ engine: 'internal:role', ... });

This indicates that elements with role='none' and role='presentation' are excluded from the locator candidates suggested by Codegen.

Background for Excluding the presentation Role

Why is the presentation role excluded from the locator candidates suggested by Codegen?

Tracing the commit history, it appears to have been introduced in the following PR:

https://github.com/microsoft/playwright/pull/18688

The commit message clearly states "ignore presentation role," suggesting that the adjustment was made to avoid automatically generating locators that depend on roles intended to remove elements from the accessibility tree.

To be honest, I wasn't very knowledgeable about front-end development and wasn't aware of this, but the presentation role is intended to "remove semantic meaning." It's a role used for elements that are not actually user-interactive buttons or links.

Using the presentation role - ARIA | MDN

The presentation role is used to remove the semantic meaning of an element and its associated children.

Now I understand why Playwright's Recorder, Inspector, and Codegen are designed to avoid mistakenly suggesting locators that point to "invisible dummy elements," in line with the intended use of the presentation role.

Summary

The getByRole API itself supports the presentation role, and it is included in the type definitions. However, Codegen's selector generator is implemented not to suggest presentation as a candidate. This is presumed to be a design decision to avoid generating locators that depend on roles that have no semantic meaning from an accessibility perspective.


In practice, scenarios where you directly target elements with role='presentation' are rare. As long as you use the locators suggested by the Inspector, you won't "accidentally specify the presentation role."

However, in the situation I encountered, the locators suggested by the Inspector were highly dependent on the DOM implementation. When I looked at the HTML implementation details, I found elements with role='presentation', which led me to question why the Inspector didn't suggest them. This article is an attempt to clarify that reason.

Although I stated in the conclusion at the beginning that "you should avoid specifying locators with the presentation role whenever possible," the exception is when the locators suggested by the Inspector are excessively DOM-dependent. In such cases, manually writing page.getByRole('presentation') might lead to more stable test code.