PRACTICAL GUIDE / Playwright getByRole accessible description locator
Locate Elements by Accessible Description in Playwright
Learn Playwright getByRole accessible description locator with working code, failure cases, debugging steps, and CI evidence for reliable QA automation.
In this guide11 sections
- Start with the Semantic Identity
- Follow the Playwright 1.61.1 Matching Rules
- Build the Description through Real Markup
- Implement a Locator that Can Fail Clearly
- Compare Name, Description, Test ID, and Text
- Cover the Boundary and Failure Matrix
- Treat Descriptions as Stateful Product Content
- Debug a Missing or Ambiguous Description
- Govern Accessible Descriptions in CI
- Frequently Asked Questions
- What does description match in Playwright getByRole?
- Is accessible description the same as accessible name?
- How does exact affect name and description matching?
- Should description be used to resolve every strict-mode collision?
- How should accessible-description locators be tested in CI?
- Practice the Locator Decision in QABattle
What you will learn
- Start with the Semantic Identity
- Follow the Playwright 1.61.1 Matching Rules
- Build the Description through Real Markup
- Implement a Locator that Can Fail Clearly
Playwright getByRole accessible description locator support lets a test distinguish controls by the description computed for accessibility APIs. Pass description beside the role and usually name, then assert the description before acting. The first failure boundary is semantic: if the relation breaks, the locator should fail even when identical visible buttons still exist in the DOM.
This is valuable for repeated labels such as Delete, Open, or Learn more, where supporting text gives each control a different consequence. It is not a general text filter. The option asks the accessibility model for a computed description, which makes it expressive but also means the test must understand names, descriptions, matching rules, and product intent.
Start with the Semantic Identity
A role answers what the element is. An accessible name answers how a user identifies it. An accessible description adds supporting information that helps explain purpose, consequences, format, or constraints. A strong locator states only the parts of that identity that the product promises to keep stable.
Imagine two Delete buttons in a draft manager. One is described as Moves this draft to trash for 30 days; the other says Permanently deletes this draft and its comments. The shared name may be deliberate because each button sits in a separately named region, or it may be an accessibility design issue. Before adding description, decide whether users can reliably distinguish the controls in the actual interface.
The Playwright locator guide recommends user-facing attributes such as role and name because they align tests with the rendered experience. Description extends that strategy when extra semantic text truly disambiguates the target. It should not reach into a class name, data attribute, or adjacent paragraph that accessibility APIs do not associate with the element.
Write the locator decision as a sentence: "Choose the button named Delete whose accessible description states that the action is permanent." If the test cannot justify every clause, reduce it. If the sentence reveals that both buttons are indistinguishable to users, fix the interface before making the test cleverer.
Follow the Playwright 1.61.1 Matching Rules
The Playwright release notes identify description as an option added to page.getByRole(), locator.getByRole(), frame.getByRole(), and frameLocator.getByRole(). The installed 1.61.1 type is description?: string | RegExp. It sits beside existing role options such as name, checked, disabled, expanded, and includeHidden.
String description matching is case-insensitive and substring-based by default. With { exact: true }, string name and string description matching become case-sensitive and whole-string, while whitespace is still trimmed. exact is ignored for regular expressions, so case sensitivity and boundaries must be encoded in the expression itself.
That shared exact option is easy to overlook. This locator requires exact matching for both values:
Exact role locator: name and description together
const permanentDelete = page.getByRole('button', {
name: 'Delete',
description: 'Permanently deletes this draft and its comments.',
exact: true,
});Changing the description to lowercase would stop matching, but so would changing the name to Delete draft. If only one field needs flexible matching, use a deliberate regular expression for that field rather than assuming exact can be configured independently.
Role locators still exclude ARIA-hidden elements by default. A matching description does not make a hidden control eligible unless includeHidden is requested. Likewise, description does not bypass strictness: an action on a locator that resolves to multiple elements fails instead of selecting the first one silently.
Build the Description through Real Markup
The most readable fixture connects a control to explanatory text with an authored semantic relationship. aria-describedby is common for hints, constraints, and consequences. The locator matches the resulting computed description rather than the ID or the source element's CSS location.
Fixture: actions with distinct consequences
<section aria-labelledby="draft-heading">
<h2 id="draft-heading">Quarterly report draft</h2>
<p id="trash-help">Moves this draft to trash for 30 days.</p>
<button aria-describedby="trash-help">Delete</button>
<p id="permanent-help">
Permanently deletes this draft and its comments.
</p>
<button aria-describedby="permanent-help">Delete</button>
</section>This fixture contains two buttons with the same role and name but different descriptions. A test can scope first to the named section, then match the destructive consequence. Scoping remains useful even when description is unique because it documents which draft owns the action and prevents an unrelated dialog from creating a collision.
Do not test only the aria-describedby attribute value. An ID can remain present while pointing to a missing node, stale message, or text from another component. An attribute assertion proves wiring syntax; toHaveAccessibleDescription proves the computed result. The ARIA snapshot accessibility guide provides a wider view when the relationship must be understood within surrounding roles and hierarchy.
The description source may not have the visibility or layout behavior that the product requires. A computed description assertion does not prove that sighted users can see help text, that screen readers announce it at the intended moment, or that the wording is understandable. Add direct visible-text, focus, or user-journey checks when those are separate requirements.
Implement a Locator that Can Fail Clearly
Use a short sequence that exposes semantic problems before the destructive action:
- Navigate to deterministic data and scope the scenario to a named landmark or component.
- Locate the candidate by role and accessible name without description, then confirm how many controls share that identity.
- Add the computed
descriptiononly when it represents an intentional user-facing distinction. - Assert
toHaveAccessibleDescriptionso failure reports the semantic contract directly. - Perform the action through the final role locator and assert the durable product result.
- Retain scoped semantic evidence on failure, with private text removed before external sharing.
- Add a negative case that breaks the description relationship and must not reach the destructive outcome.
Playwright example: assert meaning before action
import { test, expect } from '@playwright/test';
test('permanent delete targets the described action', async ({ page }) => {
await page.goto('/drafts/quarterly-report');
const draft = page.getByRole('region', {
name: 'Quarterly report draft',
});
const candidate = draft.getByRole('button', {
name: 'Delete',
exact: true,
});
await expect(candidate).toHaveCount(1);
await expect(candidate).toHaveAccessibleDescription(
'Permanently deletes this draft and its comments.',
);
const permanentDelete = draft.getByRole('button', {
name: 'Delete',
description: 'Permanently deletes this draft and its comments.',
exact: true,
});
await permanentDelete.click();
await expect(page.getByRole('dialog', { name: 'Delete draft permanently' }))
.toBeVisible();
});The candidate locator deliberately does not filter by description. That gives a missing or changed description an expected-versus-received matcher failure instead of reporting that the final locator found nothing. After the semantic assertion passes, a separate description-filtered locator performs the action and proves that the same meaning can be used to select the intended control.
For repeated domain patterns, use a typed locator factory that accepts the intended consequence but returns a locator without clicking it. If the helper also owns assertions or actions, its name should make those effects clear. The custom matcher article shows how to preserve useful matcher diagnostics while centralizing a semantic contract.
Compare Name, Description, Test ID, and Text
Each locator signal answers a different question. Select the one that reflects the user contract, then combine signals only to resolve genuine ambiguity.
| Locator approach | Best use | Strength | Failure risk |
|---|---|---|---|
getByRole(role, { name }) | A control has a clear unique identity | Closely follows how users identify controls | Collides when names are intentionally repeated |
getByRole(role, { name, description }) | Repeated names have distinct computed explanations | Encodes role, identity, and consequence | Can hide a design problem if descriptions are not usable distinctions |
getByText() | The text node itself is the target or content assertion | Direct and readable for visible copy | Nearby text is not proof of a control's semantic description |
getByTestId() | No stable user-facing identity exists for an implementation control | Explicit testing contract independent of wording | Does not validate accessibility semantics |
| CSS locator | Structural or styling target cannot be expressed semantically | Precise access to authored markup | Couples tests to implementation and can survive broken semantics |
toHaveAccessibleDescription() | The computed description is the requirement | Produces a focused semantic assertion | Does not perform the user action or prove visible help |
Do not replace all test IDs with description locators. A canvas handle, internal drag surface, or visual swatch may need an explicit testing contract. Conversely, a submit button with a clear role and name should not use a test ID merely to avoid confronting a missing label. The accessibility testing tools overview explains why locator choice offers useful feedback but does not constitute a complete accessibility audit.
Description also differs from an ARIA snapshot. The locator chooses one element based on computed properties. A snapshot records a scoped semantic tree for comparison or diagnosis. Combine them when hierarchy matters, but avoid a large snapshot when a single focused matcher states the requirement more clearly.
Cover the Boundary and Failure Matrix
Description locators fail at semantic, state, language, and ownership boundaries. Plan those cases before a production incident turns a broad substring into the wrong click.
| Boundary | Concrete failure | Expected observation | CI decision |
|---|---|---|---|
| Role | Button is replaced by a clickable generic element | getByRole('button') cannot find the target | Block as a semantic and interaction regression |
| Accessible name | Delete becomes an unnamed icon | Name-based locator and name assertion fail | Block; do not compensate with description alone |
| Description relation | aria-describedby references a removed ID | Description locator and matcher fail | Block the owned component change |
| Description content | Help text describes the wrong retention period | Exact description assertion reports the wording mismatch | Block or route through approved copy change review |
| Duplicate identity | Two controls share role, name, and description | Action fails strict resolution | Fix scope or product semantics; never call first() by habit |
| Matching policy | Substring deletes this draft matches temporary and permanent actions | Count or strictness exposes ambiguity | Use exact string or anchored expression based on the contract |
| Dynamic state | Description changes only after selecting a plan | Precondition assertion shows old computed text | Wait for the owned state transition, not elapsed time |
| Localization | English description is used in a French project | Locale-specific semantic assertion fails | Classify fixture versus translation defect with locale metadata |
| Frame | Target action lives in an embedded editor | Page scope misses it; frame locator finds it | Use frame ownership explicitly and test load failure separately |
| Hidden state | Matching control is excluded from the ARIA tree | Default role locator does not match it | Assert intended visibility instead of forcing hidden inclusion |
An effective negative test removes the referenced description node but leaves both Delete buttons rendered. The permanent-action locator must fail, and the draft must remain. This proves the test is using computed semantics rather than DOM order. Another useful case gives both buttons the same description and expects strictness to expose the ambiguity.
The visual accessibility interview scenarios are a helpful reminder that text placement and semantic association can diverge. A paragraph directly under a button may look explanatory while contributing nothing to its accessible description.
Treat Descriptions as Stateful Product Content
Playwright locators are evaluated when they are used, not frozen to the element that matched when the locator variable was created. If a description changes after selection, validation, expansion, or a network response, an earlier locator with the old description can stop resolving. That is often correct: the semantic identity described by the locator no longer exists in the current state.
Model those transitions explicitly. A plan chooser might describe a button as Select Basic, $12 per month before selection and Basic is your current plan afterward. Use one locator and assertion for the pre-action state, trigger the selection, then use a second state-specific assertion. Reusing the old locator and increasing its timeout would obscure the fact that the application moved to a new contract.
Descriptions can be composed from more than one source. An aria-describedby value may reference multiple IDs, and the computed result follows the accessibility description algorithm rather than DOM proximity. Assert the resulting description in the order and wording the product intends. Do not join source nodes in test code and assume that hand-built string proves what the browser exposes.
Keep validation errors separate. aria-errormessage represents an accessible error-message relationship, and Playwright provides toHaveAccessibleErrorMessage for that contract. Do not assume a getByRole({ description }) locator will select a field by its error message. A field can have stable instructions as its description and a changing validation error as a distinct property. Testing each with its matching semantic assertion produces clearer failure ownership.
Localization turns exact description text into a project-specific contract. Seed the locale, avoid machine-dependent formatting, and store approved expectations with the language they represent. A regular expression is suitable only when it describes allowed variability, such as a localized count placeholder. It should not make all translated wording optional. The locator guide remains useful here because narrowing to a named form or region can reduce dependence on repeated translated controls.
Responsive design adds another boundary. Computed descriptions should not change merely because helper text moves visually, but component implementations sometimes swap markup between breakpoints. Run the semantic contract at each supported component variant when the DOM differs. If only clipping, wrapping, or placement changes, diagnose that through the visual snapshot CI guide rather than weakening the description assertion.
Page objects should expose intent, not description-source mechanics. A method such as permanentDeleteButton() can return the role, name, and computed-description locator. It should not accept an aria-describedby ID from the test, because that couples callers to implementation and bypasses the semantic result. Keep the expected consequence readable at the call site or in a domain-named helper.
Finally, classify description text as test data. Help content can contain names, account limits, file titles, or other user-derived details. Use synthetic values and scoped attachments. When a failure artifact must leave CI, sanitize the computed output without changing the local assertion that protected the exact user experience. If sanitization removes the distinction needed by an AI reviewer, keep the case local instead of sending ambiguous evidence.
Debug a Missing or Ambiguous Description
Start with a broad but semantic probe. Locate by role and name, inspect its count, then use toHaveAccessibleDescription with the expected value. If the control exists but the matcher fails, inspect the authored relationship and source text. If the broad locator also fails, investigate role, name, hidden state, frame, or readiness before blaming description matching.
Capture ariaSnapshot() on the smallest parent region to see the roles and names around the target. The snapshot is diagnostic context, not a substitute for the focused description matcher. If a failed locator assertion populates additional ARIA context, Playwright exposes that through TestInfoError.errorContext, documented in the official TestInfoError API. Preserve the original error alongside any extra attachment.
Check matching rules deliberately. Log whether the test passed a string or regular expression and whether exact is true. A case-only change can break exact string matching. A substring can match more controls after new copy is added. An unanchored regular expression can accept suffixes the product did not approve. Do not add i or .* until the allowed variability is written down.
For dynamic descriptions, assert the transition. A password field may change from At least 12 characters to a validation result after blur. Locate and assert the before state, perform the interaction, then assert the new description. This chronology distinguishes a stale relation from a locator that was evaluated too early.
When the action is keyboard-driven, pair the semantic locator with keyboard navigation testing. The existence of a correctly described button does not prove focus order, visible focus, Enter or Space activation, or post-action focus placement.
Govern Accessible Descriptions in CI
Treat names and descriptions as product interfaces. Copy changes can be intentional, but they should not be bulk-approved as selector maintenance. A reviewer should decide whether the meaning changed, whether localization owns the difference, and whether the test should use exact text, a narrower invariant, or a locale-specific expectation.
Run a compact contract suite across ordinary, missing, duplicate, localized, dynamic, hidden, and framed cases. Report the role, expected name, expected description, locale, frame, and locator scope on failure. That metadata is more actionable than a generic timeout and avoids opening traces merely to discover which language project ran.
Do not retry semantic ambiguity. If two controls match, more time will not make the locator's intent clearer. Retries can help a known asynchronous state reach its milestone, but strictness and wrong computed text require a product, fixture, or test-contract change. The guide to reviewing AI-written Playwright tests is particularly relevant because generated locators often add broad text filters to make a scenario pass once.
Retain scoped ARIA evidence for failed semantic contracts, not full pages by default. Redact user-generated descriptions and values before external analysis. Pin Playwright and browser versions during adoption, then run the contract fixtures during upgrades so accessibility mapping changes are reviewed separately from application changes.
Track why description was added. A short code comment is unnecessary when the locator reads clearly, but a helper or test title can state the domain distinction, such as temporary versus permanent deletion. Periodically review description locators with recurring collisions. If the same names need increasingly detailed descriptions, the interface may need clearer labels or stronger component scope.
For the wider semantics program, connect this suite to ARIA snapshot accessibility testing and manual review. Locator success is valuable early feedback, but it does not certify announcement order, clarity, keyboard use, or compliance.
Frequently Asked Questions
What does description match in Playwright getByRole?
The description option matches the element's computed accessible description, not a CSS attribute or any nearby text. That description can be produced by relationships such as aria-describedby. Use it with the role and, when stable, the accessible name so the locator expresses the same semantic identity exposed through accessibility APIs.
Is accessible description the same as accessible name?
No. The accessible name identifies a control, while the accessible description supplies additional explanation. A button might be named Delete and described as Permanently deletes this draft. Tests should normally locate by role and name, adding description when that extra semantic distinction is part of the real interface contract.
How does exact affect name and description matching?
For string values, exact makes both name and description matching case-sensitive and whole-string, although surrounding whitespace is still trimmed. Without exact, string matching is case-insensitive and can match a substring. When either option uses a regular expression, exact does not alter that regular expression's matching behavior.
Should description be used to resolve every strict-mode collision?
No. First decide whether the controls should have distinct accessible names or a narrower semantic scope. Add description only when users genuinely receive that differentiating description and the product intends it as part of the control's identity. A test must not use hidden implementation detail to conceal an accessibility design problem.
How should accessible-description locators be tested in CI?
Cover the ordinary description, a missing relationship, duplicate controls, localization, dynamic help text, and frame boundaries. Assert the description directly before the action, then assert the user outcome. CI should block owned semantic regressions, classify fixture or translation drift separately, and retain scoped ARIA context for diagnosis.
Practice the Locator Decision in QABattle
Start with one repeated action label. Identify its role, name, computed description, component scope, and outcome. Then break the description relationship while leaving the visible layout intact. A trustworthy test should refuse to choose by order and should explain the missing semantic distinction before any destructive action occurs.
Try that review loop in QABattle battles. Select a locator challenge, state what a user can identify before writing the selector, and verify the result after the action. The exercise turns description from a convenient collision filter into a deliberate accessibility contract with a clear CI owner.
// LIVE COURSE / THE TESTING ACADEMY
Playwright Automation Mastery
Go beyond Selenium. Master Playwright with JS/TS in 90 days.
From the instructor behind this guide.
Playwright jobs are growing 8x faster than Selenium. 90 days / 75+ live hrs / Tue-Thu-Sat 7 AM IST.
PRIMARY REFERENCES
Verify the details at the source
QABattle guides are practical explanations. Product behavior, standards, and APIs can change, so use these primary references for the canonical details.
- 01Official playwright.dev reference
playwright.dev
Primary documentation selected and verified for the claims in this guide.
- 02Official playwright.dev reference
playwright.dev
Primary documentation selected and verified for the claims in this guide.
- 03Official playwright.dev reference
playwright.dev
Primary documentation selected and verified for the claims in this guide.
- 04Official playwright.dev reference
playwright.dev
Primary documentation selected and verified for the claims in this guide.
FAQ / QUICK ANSWERS
Questions testers ask
What does description match in Playwright getByRole?
The description option matches the element's computed accessible description, not a CSS attribute or any nearby text. That description can be produced by relationships such as aria-describedby. Use it with the role and, when stable, the accessible name so the locator expresses the same semantic identity exposed through accessibility APIs.
Is accessible description the same as accessible name?
No. The accessible name identifies a control, while the accessible description supplies additional explanation. A button might be named Delete and described as Permanently deletes this draft. Tests should normally locate by role and name, adding description when that extra semantic distinction is part of the real interface contract.
How does exact affect name and description matching?
For string values, exact makes both name and description matching case-sensitive and whole-string, although surrounding whitespace is still trimmed. Without exact, string matching is case-insensitive and can match a substring. When either option uses a regular expression, exact does not alter that regular expression's matching behavior.
Should description be used to resolve every strict-mode collision?
No. First decide whether the controls should have distinct accessible names or a narrower semantic scope. Add description only when users genuinely receive that differentiating description and the product intends it as part of the control's identity. A test must not use hidden implementation detail to conceal an accessibility design problem.
How should accessible-description locators be tested in CI?
Cover the ordinary description, a missing relationship, duplicate controls, localization, dynamic help text, and frame boundaries. Assert the description directly before the action, then assert the user outcome. CI should block owned semantic regressions, classify fixture or translation drift separately, and retain scoped ARIA context for diagnosis.
RELATED GUIDES
Continue the learning route
GUIDE 01
Playwright Locators Guide: Find Elements Reliably
Playwright locators guide for stable UI tests with role selectors, filters, assertions, strict mode, debugging, and flaky selector fixes in CI.
GUIDE 02
Playwright ARIA Snapshots for Testing Accessible Structure
Use Playwright ARIA snapshots to verify roles, names, states, and hierarchy with scoped templates, deliberate strictness, reviewable updates, and layered a11y tests.
GUIDE 03
How to Test ARIA Labels
Learn how to test ARIA labels: accessible names, aria-label vs aria-labelledby, roles, states, screen reader checks, and common ARIA mistakes.
GUIDE 04
Keyboard Navigation Testing
Learn keyboard navigation testing for web apps: tab order, focus indicators, skip links, modal focus traps, and practical QA test cases you can run today.
GUIDE 05
Custom Playwright Matchers: Extend and Merge expect Safely
Create retry-aware Playwright custom matchers, merge expect modules without collisions, and preserve useful negation, timeout, and failure output.