Keep Your Apps Accessible and Your e2e Tests Stable With WebdriverIOs New Accessibility Selector
Fetching elements within e2e tests can sometimes be very hard. Complex CSS paths or arbitrary test ids make them either less readable or prone to failures. The disappointment we experience when our test fail is by far not comparable to a the bad experience people have when they need to use assistent devices like screen readers on applications build without accessibility in mind.
With the accessibility selector introduced in version v7.24.0
WebdriverIO now provides a powerful way to fetch various of elements containing a certain accessibility name. Rather than applying arbitrary data-testId
properties to elements which won't be recognised by assistent devices, developers or QA engineers can now either apply a correct accessibility name to the element themselves or ask the development team to improve the accessibility so that writing tests becomes easier.
WebdriverIO internally uses a chain of xPath selector conditions to fetch the correct element. While the framework has no access to the accessibility tree of the browser, it can only guess the correct name here. As accessibility names are computed based on author supplied names and content names, WebdriverIO fetches an element based in a certain order:
- First we try to find an element that has an
aria-labelledBy
oraria-describedBy
property pointing to an element containing a valid id, e.g.:So we can fetch a certain link within our navigation via:<h2 id="social">Social Media</h2>
<nav aria-labelledBy="social">...</nav>await $('aria/Social Media').$('a=API').click()
- Then we look for elements with a certain
aria-label
, e.g.:Rather than using<button aria-label="close button">X</button>
X
to fetch the element or applying a test id property we can just do:await $('aria/close button').click()
- Well defined HTML forms provide a label to every input element, e.g.:
Setting the value of the input can now be done via:
<label for="username">Username</label>
<input id="username" type="text" />await $('aria/Username').setValue('foobar')
- Less ideal but still working are
placeholder
oraria-placeholder
properties:Which can now be used to fetch elements as well:<input placeholder="Your Username" type="text" />
await $('aria/Your Username').setValue('foobar')
- Furthermore if an image tag provides a certain alternative text, this can be used to query that element as well, e.g.:
Such an image can be now fetched via:
<img alt="A warm sommer night" src="..." />
await $('aria/A warm sommer night').getTagName() // outputs "img"
- Lastly, if no proper accessibility name can be derived, it is computed by its accumulated text, e.g.:
Such a heading tag can be now fetched via:
<h1>Welcome!</h1>
await $('aria/Welcome!').getTagName() // outputs "h1"
As you can see, there are a variety of ways to define the accessibility name of an element. Many of the browser debugging tools provide handy accessibility features that help you to find the proper name of the element:
For more information check out the Chrome DevTools or Firefox Accessibility Inspector docs.
Accessibility is not only a powerful tool to create an inclusive web, it can also help you write stable and readable tests. While you should not go ahead and give every element an aria-label
, this new selector can help you build web applications with accessibility in mind so that writing e2e tests for it later on will become much easier.
Thanks for reading!