Finding an element in a Playwright test has usually been straightforward for me until I come across controls that do not have visible text or an obvious selector. If you rely on DOM structure or changing attributes to find them, even small updates to the page can leave you fixing tests that were working perfectly before.
ARIA labels give you a more meaningful way to target these elements. With Playwright, you can locate controls by the accessible name users and assistive technologies rely on. This can make your tests easier to understand while keeping them closer to how people actually interact with the application.
I’ve gathered all the information that has helped me take up this method and help you through using ARIA labels to locate elements in Playwright. I’ll also incorporate practical examples and where this approach fits alongside other locator options.
What is Playwright’s getByAriaLabel?
getByAriaLabel is a Playwright method used to locate elements by their ARIA label attribute, which is widely used for web accessibility. ARIA labels provide additional context to elements, making them accessible to screen readers, thus enhancing usability for users with disabilities.
Using getByAriaLabel helps testers target elements that are described by these labels, ensuring their tests cover accessibility and usability aspects.
What Happens When You Use ARIA Labels
Playwright locates elements using getByAriaLabel by referencing the aria-label attribute on HTML elements. This attribute is often used to provide a meaningful description of an element for accessibility purposes. When a user runs a Playwright script with getByAriaLabel, Playwright queries the DOM and returns the element whose aria-label matches the given string.
Playwright does not have a getByAriaLabel() locator. To find an element by its accessible label, you use getByLabel().
For example, consider an icon-only close button:
<button aria-label="Close"> <svg>...</svg> </button>
You can locate it with:
const closeButton = page.getByLabel('Close');
await closeButton.click();getByLabel() is useful because it is not limited to directly reading the aria-label attribute. It can locate form controls through associated <label> elements as well as accessibility attributes such as aria-label and aria-labelledby.
Syntax and Basic Usage Examples
If an element has an aria-label, you can locate it using Playwright’s getByLabel() method:
const button = page.getByLabel('Submit');
await button.click();If you want to target the attribute directly with a CSS selector:
const button = page.locator('[aria-label="Submit"]');
await button.click();For most tests, getByLabel() is the more readable option because it works with the element’s accessible label rather than tying the locator directly to an HTML attribute.
You can use the returned locator with common Playwright actions and assertions:
// Fill an input
await page.getByLabel('Email address').fill('user@example.com');
// Click a button
await page.getByLabel('Submit').click();
// Check visibility
await expect(page.getByLabel('Close')).toBeVisible();If you want to use partial matching when the accessible label may contain additional text:
const button = page.getByLabel(/Submit/i);
Advanced Usage Scenarios
While getByAriaLabel is simple to use, there are advanced scenarios where you can leverage it more effectively.
Using Regular Expressions with getByAriaLabel
Playwright allows the use of regular expressions to match aria-label values. This feature helps when the label contains dynamic content.
Example:
const element = await page.locator(‘[aria-label^=”Submit”]’);In this example, the ^ operator indicates that the aria-label value starts with the word “Submit,” helping match multiple variations of a button or link with similar starting labels.
Filtering multiple matching elements
In some cases, multiple elements may share the same aria-label value. To filter them, Playwright supports chaining locators or using more specific selectors.
Example:
const button = await page.locator(‘[aria-label=”Submit”]’).first();await button.click();This code ensures that the first element with the aria-label “Submit” is selected.
Combining getByAriaLabel with other locator methods
Combining getByAriaLabel with other locators, such as text or role, can help create more precise selectors.
Example:
const button = await page.locator(‘[aria-label=”Submit”][role=”button”]’);await button.click();Here, Playwright will locate a button with both the aria-label “Submit” and the role “button.”
Writing Stable Locators with Accessible Labels
To make the most of getByAriaLabel, follow these best practices:
- Use clear and descriptive labels: Avoid generic labels like “button” or “link.” Instead, opt for specific labels like “Submit form” or “Navigate to home.”
- Ensure uniqueness: Whenever possible, ensure that each aria-label is unique across the page to avoid ambiguity in your tests.
- Combine locators: For more accuracy, combine getByAriaLabel with other attributes, such as role, id, or data-test attributes.
Common Mistakes That Make Label-Based Locators Fail
Label-based locators are usually straightforward but a few choices can make them unreliable as your application grows.
- Using the wrong locator method: Playwright does not provide getByAriaLabel(). Use getByLabel() when you want to locate an element through its accessible label.
- Using the same label for multiple controls: If several elements share the same accessible name, Playwright may return multiple matches and trigger a strict mode violation. Use more descriptive labels or scope the locator to the relevant section.
- Assuming every element needs an aria-label: Many elements already get their accessible name from visible text or an associated <label>. Avoid adding aria-label only to make a test easier to write.
- Using getByText() as a direct fallback: The right alternative depends on the element. For a button, getByRole(‘button’, { name: ‘Submit’ }) may be more appropriate. For a form field, getByLabel() is usually the better fit.
The main thing is to choose a locator based on how the element is exposed to users rather than forcing every element into the same locator strategy.
Integrating getByAriaLabel into your Automation Pipeline
Once you’ve mastered using getByAriaLabel, it’s time to integrate this method into your larger automation pipeline.
Running Playwright tests at scale
When running Playwright tests at scale, especially across multiple devices and browsers, it’s crucial to have a stable testing environment. BrowserStack Automate allows you to run Playwright tests on real devices and browsers at scale, ensuring comprehensive coverage.
BrowserStack Automate offers cloud-based execution for Playwright tests, allowing teams to test across different environments. This service supports parallel execution, ensuring that you can run tests on a variety of devices and browsers, helping you scale your testing efforts quickly.
Keeping Your Locators Easy to Maintain
As your application changes, the labels and elements your tests rely on may change too. Instead of updating the same locator across several test files, keep commonly used locators in one place.
For example, you can define them inside a Page Object:
class LoginPage {
constructor(page) {
this.page = page;
this.emailInput = page.getByLabel('Email address');
this.passwordInput = page.getByLabel('Password');
this.loginButton = page.getByRole('button', { name: 'Log in' });
}
}If a label changes later, you only need to update the relevant locator in the Page Object rather than searching through every test that uses it.
It is also worth reviewing locators when the UI changes. If an accessible label has been updated to better describe a control, your test should follow that change rather than holding on to an outdated label just to keep the test passing.
Conclusion
Good locators should make your tests easier to understand and not give you more work every time the UI changes. Accessible labels can be a useful way to find elements because they describe controls in terms that users can understand.
Use getByLabel() where it makes sense and choose other built-in locators when they are a better fit. The goal is not to use one locator everywhere but to pick the one that keeps each test clear and reliable.