diff --git a/lib/checks/label/duplicate-img-label.js b/lib/checks/label/duplicate-img-label.js index d184c572c2..6dec209a8f 100644 --- a/lib/checks/label/duplicate-img-label.js +++ b/lib/checks/label/duplicate-img-label.js @@ -1,18 +1,16 @@ -var imgs = node.querySelectorAll('img'); -var text = axe.commons.text.visible(virtualNode, true).toLowerCase(); - +const text = axe.commons.text.visible(virtualNode, true).toLowerCase(); if (text === '') { return false; } -for (var i = 0, len = imgs.length; i < len; i++) { - var img = imgs[i]; - var imgAlt = axe.commons.text.accessibleText(img).toLowerCase(); - if (imgAlt === text && - img.getAttribute('role') !== 'presentation' && - axe.commons.dom.isVisible(img)) { - return true; - } -} +// Get all visible images in the composed tree of the current node +const images = axe.utils.querySelectorAll(virtualNode, 'img') + // Ignore hidden or role=none/presentation images + .filter(({ actualNode }) => (axe.commons.dom.isVisible(actualNode) && + !['none', 'presentation'].includes(actualNode.getAttribute('role')) + )); -return false; +// See if any of the images duplicate the node's text +return images.some(img => + text === axe.commons.text.accessibleText(img).toLowerCase() +); diff --git a/test/checks/label/duplicate-img-label.js b/test/checks/label/duplicate-img-label.js index 737bdc0122..57a4ee8f90 100644 --- a/test/checks/label/duplicate-img-label.js +++ b/test/checks/label/duplicate-img-label.js @@ -2,6 +2,8 @@ describe('duplicate-img-label', function () { 'use strict'; var fixture = document.getElementById('fixture'); + var checkSetup = axe.testUtils.checkSetup; + var shadowSupport = axe.testUtils.shadowSupport; afterEach(function () { fixture.innerHTML = ''; @@ -64,4 +66,38 @@ describe('duplicate-img-label', function () { var tree = axe._tree = axe.utils.getFlattenedTree(fixture); assert.isFalse(checks['duplicate-img-label'].evaluate(node, undefined, axe.utils.getNodeFromTree(tree[0], node))); }); + + (shadowSupport.v1 ? it : xit)('should return true if the img is part of a shadow tree', function () { + var button = document.createElement('div'); + button.setAttribute('role', 'button'); + button.innerHTML = 'My button'; + var shadow = button.attachShadow({ mode: 'open' }); + shadow.innerHTML = 'My button'; + var checkArgs = checkSetup(button); + + assert.isTrue(checks['duplicate-img-label'].evaluate.apply(null, checkArgs)); + }); + + (shadowSupport.v1 ? it : xit)('should return true if the img is a slotted element', function () { + var button = document.createElement('div'); + button.setAttribute('role', 'button'); + button.innerHTML = 'My button'; + var shadow = button.attachShadow({ mode: 'open' }); + shadow.innerHTML = 'My button '; + var checkArgs = checkSetup(button); + + assert.isTrue(checks['duplicate-img-label'].evaluate.apply(null, checkArgs)); + }); + + (shadowSupport.v1 ? it : xit)('should return false if the shadow img has a different text', function () { + var button = document.createElement('div'); + button.setAttribute('role', 'button'); + button.innerHTML = 'My button'; + var shadow = button.attachShadow({ mode: 'open' }); + shadow.innerHTML = 'My image'; + var checkArgs = checkSetup(button); + + assert.isFalse(checks['duplicate-img-label'].evaluate.apply(null, checkArgs)); + }); + }); diff --git a/test/testutils.js b/test/testutils.js index 07508a5b33..ab8cfc811c 100644 --- a/test/testutils.js +++ b/test/testutils.js @@ -42,8 +42,18 @@ testUtils.checkSetup = function (content, options, target) { target = options; options = {}; } + // Normalize target, allow it to be the inserted node or '#target' + target = target || (content instanceof Node ? content : '#target'); testUtils.fixtureSetup(content); - var node = axe.utils.querySelectorAll(axe._tree[0], target || '#target')[0]; + + var node; + if (typeof target === 'string') { + node = axe.utils.querySelectorAll(axe._tree[0], target)[0]; + } else if (target instanceof Node) { + node = axe.utils.getNodeFromTree(axe._tree[0], target); + } else { + node = target; + } return [node.actualNode, options, node]; };