TPAC 2019
ARIA & WebDriver
Promoting accessibility by incentivizing web developers with tools that simplify testing accessible applications
ARIA & WebDriver
WAI-ARIA and WebDriver are distinct web
standards with highly similar goals: they both aim to enable
machine-mediated interaction with web pages. In the case of ARIA, the
machine is some Assistive Technology (e.g. a screen reader or a braille
display), and it enables a person with a disability to effectively browse
the web. In the case of WebDriver, the machine is a script written by a web
developer, and it enables the developer to verify the correctness of their
work.
.--------------.
| Application |
+----------. |
Developer -------------> WebDriver -------->| HTML | |
+------. | |
User --------> Assistive Technology -------->| ARIA | | |
'------+---+---'
Depiction of "paths" used to interact with web applications, comparing the
path of the web developer with the path of the user.
The differences in the paths used by developers and users to access web
applications cause a number of problems. Web developers have little insight
into the correctness of their application from the perspective of a visitor
using Assistive Technology. Additionally there is information in the accessibility
tree that more faithfully represents objects that the user would interact with.
Web developers are today recreating that same information when writing tests without
utilizing the a11y tree.
.--------------.
| Application |
+----------. |
Developer ---> ARIA-aware WebDriver --. | HTML | |
\ +------. | |
User --------> Assistive Technology -------->| ARIA | | |
'------+---+---'
Depiction of "paths" used to interact with web applications, where the
path of the web developer converges with the path of the user.
WebDriver could be extended with new commands which interact through the accessibility tree.
This way the web developer using WebDriver and the user using assistive
technology share a more similar understanding of the application.
Developer incentives
Less test code
Improved test stability
Improved test resiliency
Accessibility verified
Developer incentives
Less test code
const radios = await webdriver.findElements(
By.css('[role="radio"]')
);
for (const radio of radios) {
if (await radio.getText() === 'Thin crust') {
await radio.click();
}
}
Interacting with some widgets requires multiple commands and sometimes
involves non-trivial control flow.
Developer incentives
Less test code (continued)
function accessibleName(el) { /* ... */ }
function focus(el) { /* ... */ }
const radios = await webdriver.findElements(
By.css('[role="radio"]')
);
for (const radio of radios) {
if (await accessibleName(radio) === 'Thin crust') {
await focus(radio);
await radio.sendKeys(Key.ENTER);
}
}
webdriver.setRadio('Thin crust');
Developers who are familiar with best practices need to maintain even
more code to operate on accessibility primitives using WebDriver's
low-level API.
Today, developers frequently encapsulate code like this using a
pattern called "page
objects ". This reduces maintenance costs to some extent, but it does
not eliminate them.
A single WebDriver command like "Set Radio" would reduce the amount of
code developers have to maintain, and and it would make tests more
declarative. For applications which are composed of conventional widgets,
ARIA-aware WebDriver commands could remove the need for this practice.
Developer incentives
Improved test stability
const opener = await webdriver.findElement(
By.css('[aria-haspopup]')
);
await opener.click();
await webdriver.findElement('[role="menu"] button');
^ NoSuchElementError: An element could not
be located on the page
using the given search
parameters.
await webdriver.openPopup();
await webdriver.findElement('[role="menu"] button');
Developer incentives
Improved test resiliency
const closeBtn = await webdriver.findElement(
By.css('#modal button.close')
);
await closeBtn.click();
webdriver.closeModal();
It's all too easy for developers to write brittle tests. When writing in
terms of DOM elements, less experienced testers will use a "whatever works"
strategy to get a test running.
Code like this depends on implementation details that are subject to
change with any refactoring. Maintaining that is a tiresome distraction for
many developers.
An application's accessibility tree is far more stable. Tests written
against the accessibility tree are naturally more resilient. The widgets
defined in the APG specify even more stable structure.
This isn't to say tests written like this won't need maintenance--if the
modal is removed, the test will have to change--but they won't have
developers chasing down new CSS selectors.
Developer incentives
Accessibility verified
element.pushButton();
^ Error: Accessible name of toggle button
inappropriately changed following push
Just as end users don't need to know ARIA to use the widgets, developers
won't need to know ARIA to use these commands. However, the commands can
teach developers by reporting errors when the application under test
violates some expectation.
For push buttons, ARIA requires that the accessible name is not changed
as a result of changing the state of a push button. This can be checked
by the pushButton()
command.
Discussion
Stale element references
"Preferred input mode"
Guideline stability
Publication
Stale element references can happen, this proposal doesn't change that.
However, the existing WebDriver commands just do some interaction and then resolve.
The pushButton()
command does some interaction and then verifies accessible name,
which assumes that the element reference is not stale. This is a new problem.
Preferred input mode: only testing the code path dedicated to assistive technology misses the corresponding code path for mouse users.
The new commands can test both code paths by running a test twice in the two different modes.
Guidelines stability: The examples in APG might still change, which would require WebDriver commands
that rely on them to also change. This could break existing tests.
Publication: where should the spec live? WebDriver or APG?