Test the leading edge of accessibility with axe Coconut and axe-core 3.0-alpha

Editors note: The axe Coconut extension is no longer available.

The axe-core team at Deque has been working hard on a set of updates to the axe ecosystem of accessibility testing tools. Let’s go over the latest developments so you can decide which tools work best for you!

Introducing axe Coconut

To make it easy for everyone to test the leading edge of axe-core, we’ve introduced a new free Chrome extension, called axe Coconut. It includes our latest code changes for Shadow DOM (more on that below), with experimental rules also enabled.

The axe Coconut extension, created in the same vein as a Chrome Canary or Firefox Nightly, will allow you to try out our latest APIs and rules before they are released to more stable channels, such as our regular axe Chrome Extension.

You can download axe Coconut for free from the Chrome Store and try it out on all sites, including those with Shadow DOM. You can even use it alongside our regular axe Chrome extension: you’ll notice a different devtools tab, logo, and browser action popup window to differentiate the two. We’d love your feedback as you start testing with it, so we can make any necessary changes to our APIs before releasing the code to everyone.

axe Coconut Extension

axe-core 3.0 alpha

We’ve made significant changes to the axe-core JavaScript engine for version 3.0.0, including support for Shadow DOM and Web Components! This branch also provides the same improvements as 2.4, including ARIA 1.1 support and Japanese localization. For the entire list of updates, check out our Changelog.

To give you an opportunity to provide feedback on our new Shadow DOM APIs and test results before they land in 3.0.0 stable, we’ve begun pre-releasing a series of 3x “alphas” under the tag, @next.

To install the latest axe-core pre-release version using npm:

npm install axe-core@next

This will allow you to test for accessibility inside of and across Shadow DOM subtrees, commonly used in Web Components including the Polymer library. It requires custom APIs that walk the entire flattened DOM tree instead of DOM APIs such as document.querySelector. We handle this for you internally, so you can use the familiar axe-core API to test the entire page.

NOTE: in order to test your shadow DOM and components from third parties, please be sure to never use the closed shadow DOM option as this will prevent axe-core and aXe extensions from being able to look inside the shadow DOM.

What the heck is Shadow DOM?

In a nutshell: Shadow DOM, part of the recent HTML standards movement towards Web Components, is a way to encapsulate portions of HTML pages using JavaScript. The encapsulation eliminates conflicts due to CSS styles, Javascript globals, and element IDs. This new standard makes it easier to reuse third-party components. If you’ve ever tried including an overzealous jQuery UI widget, you may have experienced the pain that Shadow DOM intends to solve.

Other examples of Shadow DOM you may have experienced include HTML5 video tags and inputs, which contain multiple controls inside of a single element: embed a

Inspecting the shadow root of an HTML5 video element in Chrome developer tools

Shadow DOM as a standard provides developers with the same mechanism for encapsulation browsers have internally relied upon for years. But we can now create our own shadow trees for any HTML element, such as plain DIVs, canvas, or custom elements to name a few.

When you attach custom Shadow DOM to an element (called the host), it creates a boundary at the top of which is a ShadowRoot. The encapsulation of shadow roots means that DOM APIs such as document.querySelector have limited capabilities to pierce the boundary (there is the shadow piercing combinator >>> but it has limitations on specificity). So, we had to write our own.

Luckily there was prior art for this technique in Google’s Accessibility Developer Tools Library and we got a lot of help from the folks over at Google like Rob Dobson and Alice Boxhall. They are also now using axe-core in their Lighthouse tool and will be using the shadow DOM version when this is released.

Shadow DOM and frame selectors in axe-core results

The most obvious difference when consuming axe-core 3x is in selector targets returned for nodes in accessibility test results, when the element in question is inside a shadow root. The format is a JavaScript Array of either strings (normal DOM with or without iframes), or Arrays of strings (shadow DOM with or without iframes).

// CSS Selector in a simple document without iframes
['#myCoolNode']

// CSS Selector inside an iframe
[
  'frame.someIframe', '#myCoolNode'
]

// Element inside the shadow DOM of a simple document without an iframe.
// Note the extra brackets []
[
  [
    '#hostNode, '.someElementInShadowTree'
  ]
]

In plain text, from our API documentation for the axe-core results object:

nodes[n].target: Array of either strings or Arrays of strings. If the item in the array is a string, then it is a CSS selector. If there are multiple items in the array each item corresponds to one level of iframe or frame. If there is one iframe or frame, there should be two entries in target. If there are three iframe levels, there should be four entries in target.

If the item in the Array is an Array of strings, then it points to an element in a shadow DOM and each item (except the n-1th) in this array is a selector to a DOM element with a shadow DOM. The last element in the array points to the final shadow DOM node.

Core Shadow DOM APIs and Test Utilities

Developing and testing the internal engine for axe-core 3x means using some of our latest APIs and test utilities. Unless you’re hacking on the core library, this shouldn’t affect you much. But if you want to contribute to it, you should read our updated developer guide to become familiar with the changes.

To handle Shadow DOM, we introduced API support for “virtual nodes”. A virtualNode in axe-core is a custom JavaScript object representing a DOM node, which can either be inside of a Shadow boundary, or not. This node is organized into a flattened tree that represents the hierarchy that is exposed to accessibility APIs.

A virtualNode object contains the actual HTML node, e.g. a DIV element; an array of any child virtual DOM nodes; and a shadowId, indicating which shadow root the node belongs to. If this is undefined, then the node is just a regular DOM node.

// VirtualNode
{
  actualNode: div,
  children: [virtualNodes],
  shadowId: undefined
}
?

We now pass the virtualNode and the regular DOM node into rule matches functions and the check evaluate functions. There are a couple of new APIs for querying the flattened (composed) tree and plucking a node from the tree, which we use internally where the accessibility tree hierarchy is important.

For writing tests for utilities, checks and rules that need to know about virtualNodes, we created a few test utilities to smooth out the experience. There is a utility for checking for Shadow DOM support, which we use to skip tests on platforms that don’t support shadow DOM, like PhantomJS. There are also utilities for mocking a checkContext and setting up fixtures with Shadow DOM.

For more details, check out the 3x developer guide and our automated test suite.

axe-core 2.4

In version 2.4 of the axe-core JavaScript engine, we released a number of updates to accessibility rules, including: baseline ARIA 1.1 support, fixes for combobox and color contrast, and more. These updates are available in both the 2x and 3x branches, so you can take advantage of them with or without experimental Shadow DOM support.

Thanks to our partner Mitsue-Links, we added Japanese localization to our infrastructure in addition to Dutch. We’ve also written new documentation for rules and debugging CI.

The entire list of updates in 2.4 can be found in the axe-core Changelog, and the developer guide for the 2x branch on Github.

ARIA 1.1 attributes

Here’s a list of the ARIA 1.1 attributes we determined were widely-enough supported by assistive technologies to be included in axe-core at this time:

New

  • aria-modal, with values: ['true', 'false']
  • aria-keyshortcuts: [string]
  • aria-placeholder: [string]
  • role=feed
  • role=term
  • aria-colindex, aria-colspan, aria-rowindex, aria-rowspan
  • aria-colcount, aria-rowcount
  • aria-posinset, aria-setsize
  • aria-orientation

Changed

  • aria-haspopup now allows these values: ['true', 'false', 'menu', 'listbox', 'tree', 'grid', 'dialog']

To provide any feedback or questions about aXe Coconut, axe-core 3x, or even axe-core 2x, get in touch with us at axe@deque.com, on our Github repo, or on the axe-core Gitter channel.

 

 

 

Photo of Marcy Sutton

About Marcy Sutton

Marcy is a Developer Advocate at Deque Systems. She's also an #axeCore team member, @a11ySea meetup organizer & mountain enthusiast.
update selasa

Comments 3 responses

  1. All axe coconut ext links are leading to 404.
    Is this extension or planned extension not available anymore?

Leave a Reply

Your email address will not be published. Required fields are marked *