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 = '';
+ 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 = '';
+ 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 = '';
+ 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];
};