diff --git a/lib/commons/text/accessible-text-virtual.js b/lib/commons/text/accessible-text-virtual.js index c1ce96f69e..597f07ee70 100644 --- a/lib/commons/text/accessible-text-virtual.js +++ b/lib/commons/text/accessible-text-virtual.js @@ -7,6 +7,7 @@ import titleText from './title-text'; import sanitize from './sanitize'; import isVisibleToScreenReaders from '../dom/is-visible-to-screenreader'; import isIconLigature from '../text/is-icon-ligature'; +import { nativelyHidden } from '../dom/visibility-methods'; /** * Finds virtual node and calls accessibleTextVirtual() @@ -84,11 +85,14 @@ function shouldIgnoreHidden(virtualNode, context) { return false; } + // When traversing aria-labelledby references, include hidden nodes except natively hidden elements + if (context.includeHidden && !nativelyHidden(virtualNode)) { + return false; + } + if ( // If the parent isn't ignored, the text node should not be either - virtualNode.props.nodeType !== 1 || - // If the target of aria-labelledby is hidden, ignore all descendents - context.includeHidden + virtualNode.props.nodeType !== 1 ) { return false; } diff --git a/test/commons/text/accessible-text.js b/test/commons/text/accessible-text.js index fd0552f0cd..2dca9f026f 100644 --- a/test/commons/text/accessible-text.js +++ b/test/commons/text/accessible-text.js @@ -1649,6 +1649,47 @@ describe('text.accessibleTextVirtual', () => { }); }); + describe('natively hidden elements', () => { + const tags = ['style', 'script', 'noscript', 'template']; + + it('should not use content as accessible name when directly referenced by aria-labelledby', () => { + tags.forEach(tag => { + fixture.innerHTML = `
<${tag} id="el-id">content${tag}>`; + axe.testUtils.flatTreeSetup(fixture); + const target = axe.utils.querySelectorAll(axe._tree, '#t1')[0]; + assert.equal(axe.commons.text.accessibleTextVirtual(target), '', tag); + }); + }); + + it('should not use content when inside a hidden container referenced by aria-labelledby', () => { + tags.forEach(tag => { + fixture.innerHTML = ` + + + `; + axe.testUtils.flatTreeSetup(fixture); + const target = axe.utils.querySelectorAll(axe._tree, '#t1')[0]; + assert.equal( + axe.commons.text.accessibleTextVirtual(target), + 'Expected label', + tag + ); + }); + }); + + it('should ignore aria-label as accessible name when directly referenced by aria-labelledby', () => { + tags.forEach(tag => { + fixture.innerHTML = `<${tag} id="el-id" aria-label="aria-label">${tag}>`; + axe.testUtils.flatTreeSetup(fixture); + const target = axe.utils.querySelectorAll(axe._tree, '#t1')[0]; + assert.equal(axe.commons.text.accessibleTextVirtual(target), '', tag); + }); + }); + }); + describe('text.accessibleText acceptance tests', () => { 'use strict'; // Tests borrowed from the AccName 1.1 testing docs