diff --git a/lib/checks/navigation/region.js b/lib/checks/navigation/region.js index 8af2c17ebc..e273ba4116 100644 --- a/lib/checks/navigation/region.js +++ b/lib/checks/navigation/region.js @@ -25,27 +25,32 @@ function isSkipLink(vNode) { } // Check if the current element is a landmark -function isLandmark(virtualNode) { - var node = virtualNode.actualNode; - var explictRole = (node.getAttribute('role') || '').trim().toLowerCase(); +function isRegion(virtualNode) { + const node = virtualNode.actualNode; + const explicitRole = axe.commons.aria.getRole(node, { noImplicit: true }); + const ariaLive = (node.getAttribute('aria-live') || '').toLowerCase().trim(); - if (explictRole) { - return landmarkRoles.includes(explictRole); - } else { - // Check if the node matches any of the CSS selectors of implicit landmarks - return implicitLandmarks.some(implicitSelector => { - let matches = axe.utils.matchesSelector(node, implicitSelector); - if (node.tagName.toLowerCase() === 'form') { - let titleAttr = node.getAttribute('title'); - let title = - titleAttr && titleAttr.trim() !== '' - ? axe.commons.text.sanitize(titleAttr) - : null; - return matches && (!!aria.labelVirtual(virtualNode) || !!title); - } - return matches; - }); + if (explicitRole) { + return explicitRole === 'dialog' || landmarkRoles.includes(explicitRole); } + // Ignore content inside of aria-live + if (['assertive', 'polite'].includes(ariaLive)) { + return true; + } + + // Check if the node matches any of the CSS selectors of implicit landmarks + return implicitLandmarks.some(implicitSelector => { + let matches = axe.utils.matchesSelector(node, implicitSelector); + if (node.tagName.toLowerCase() === 'form') { + let titleAttr = node.getAttribute('title'); + let title = + titleAttr && titleAttr.trim() !== '' + ? axe.commons.text.sanitize(titleAttr) + : null; + return matches && (!!aria.labelVirtual(virtualNode) || !!title); + } + return matches; + }); } /** @@ -55,7 +60,7 @@ function findRegionlessElms(virtualNode) { const node = virtualNode.actualNode; // End recursion if the element is a landmark, skiplink, or hidden content if ( - isLandmark(virtualNode) || + isRegion(virtualNode) || isSkipLink(virtualNode) || !dom.isVisible(node, true) ) { diff --git a/test/checks/navigation/region.js b/test/checks/navigation/region.js index ee0af39281..8162ff8a3c 100644 --- a/test/checks/navigation/region.js +++ b/test/checks/navigation/region.js @@ -211,6 +211,35 @@ describe('region', function() { assert.isTrue(checks.region.evaluate.apply(checkContext, checkArgs)); }); + it('allows content in aria-live=assertive', function() { + var checkArgs = checkSetup( + '
This is random content.
This is random content.
This is random content.
This is random content.