diff --git a/lib/checks/lists/dlitem.js b/lib/checks/lists/dlitem.js index 96ec9e65b1..80a6608fc7 100644 --- a/lib/checks/lists/dlitem.js +++ b/lib/checks/lists/dlitem.js @@ -1,2 +1,2 @@ -return node.parentNode.tagName === 'DL'; - +var parent = axe.commons.dom.getComposedParent(node); +return parent.nodeName.toUpperCase() === 'DL'; diff --git a/lib/checks/lists/has-listitem.js b/lib/checks/lists/has-listitem.js index d38f7bd805..05aff66304 100644 --- a/lib/checks/lists/has-listitem.js +++ b/lib/checks/lists/has-listitem.js @@ -1,9 +1,2 @@ -var children = node.children; -if (children.length === 0) { return true; } - -for (var i = 0; i < children.length; i++) { - if (children[i].nodeName.toUpperCase() === 'LI') { return false; } -} - -return true; - +return virtualNode.children.every(({ actualNode }) => + actualNode.nodeName.toUpperCase() !== 'LI'); diff --git a/lib/checks/lists/listitem.js b/lib/checks/lists/listitem.js index 16e396b878..1a7abcb40d 100644 --- a/lib/checks/lists/listitem.js +++ b/lib/checks/lists/listitem.js @@ -1,6 +1,4 @@ - -if (['UL', 'OL'].indexOf(node.parentNode.nodeName.toUpperCase()) !== -1) { - return true; -} - -return node.parentNode.getAttribute('role') === 'list'; +var parent = axe.commons.dom.getComposedParent(node); +return (['UL', 'OL'].includes(parent.nodeName.toUpperCase()) || + (parent.getAttribute('role') || '').toLowerCase() === 'list'); + \ No newline at end of file diff --git a/lib/checks/lists/only-dlitems.js b/lib/checks/lists/only-dlitems.js index a003f8dbee..ff3a20d62d 100644 --- a/lib/checks/lists/only-dlitems.js +++ b/lib/checks/lists/only-dlitems.js @@ -1,19 +1,16 @@ -var child, - nodeName, - bad = [], - children = node.childNodes, +var bad = [], permitted = ['STYLE', 'META', 'LINK', 'MAP', 'AREA', 'SCRIPT', 'DATALIST', 'TEMPLATE'], hasNonEmptyTextNode = false; -for (var i = 0; i < children.length; i++) { - child = children[i]; - var nodeName = child.nodeName.toUpperCase(); - if (child.nodeType === 1 && nodeName !== 'DT' && nodeName !== 'DD' && permitted.indexOf(nodeName) === -1) { - bad.push(child); - } else if (child.nodeType === 3 && child.nodeValue.trim() !== '') { +virtualNode.children.forEach(({ actualNode }) => { + var nodeName = actualNode.nodeName.toUpperCase(); + if (actualNode.nodeType === 1 && nodeName !== 'DT' && nodeName !== 'DD' && permitted.indexOf(nodeName) === -1) { + bad.push(actualNode); + } else if (actualNode.nodeType === 3 && actualNode.nodeValue.trim() !== '') { hasNonEmptyTextNode = true; } -} +}); + if (bad.length) { this.relatedNodes(bad); } diff --git a/lib/checks/lists/only-listitems.js b/lib/checks/lists/only-listitems.js index 547fe79652..bdb53064e5 100644 --- a/lib/checks/lists/only-listitems.js +++ b/lib/checks/lists/only-listitems.js @@ -1,19 +1,16 @@ -var child, - nodeName, - bad = [], - children = node.childNodes, +var bad = [], permitted = ['STYLE', 'META', 'LINK', 'MAP', 'AREA', 'SCRIPT', 'DATALIST', 'TEMPLATE'], hasNonEmptyTextNode = false; -for (var i = 0; i < children.length; i++) { - child = children[i]; - nodeName = child.nodeName.toUpperCase(); - if (child.nodeType === 1 && nodeName !== 'LI' && permitted.indexOf(nodeName) === -1) { - bad.push(child); - } else if (child.nodeType === 3 && child.nodeValue.trim() !== '') { +virtualNode.children.forEach(({ actualNode }) => { + var nodeName = actualNode.nodeName.toUpperCase(); + if (actualNode.nodeType === 1 && nodeName !== 'LI' && permitted.indexOf(nodeName) === -1) { + bad.push(actualNode); + } else if (actualNode.nodeType === 3 && actualNode.nodeValue.trim() !== '') { hasNonEmptyTextNode = true; } -} +}); + if (bad.length) { this.relatedNodes(bad); } diff --git a/lib/checks/lists/structured-dlitems.js b/lib/checks/lists/structured-dlitems.js index b8578dffb1..7654da061d 100644 --- a/lib/checks/lists/structured-dlitems.js +++ b/lib/checks/lists/structured-dlitems.js @@ -1,9 +1,9 @@ -var children = node.children; +var children = virtualNode.children; if ( !children || !children.length) { return false; } var hasDt = false, hasDd = false, nodeName; for (var i = 0; i < children.length; i++) { - nodeName = children[i].nodeName.toUpperCase(); + nodeName = children[i].actualNode.nodeName.toUpperCase(); if (nodeName === 'DT') { hasDt = true; } if (hasDt && nodeName === 'DD') { return false; } if (nodeName === 'DD') { hasDd = true; } diff --git a/lib/commons/dom/get-composed-parent.js b/lib/commons/dom/get-composed-parent.js index c5cfc74339..fdec0a4b18 100644 --- a/lib/commons/dom/get-composed-parent.js +++ b/lib/commons/dom/get-composed-parent.js @@ -6,7 +6,10 @@ */ dom.getComposedParent = function getComposedParent (element) { if (element.assignedSlot) { - return element.assignedSlot; // content of a shadow DOM slot + // NOTE: If the display of a slot element isn't 'contents', + // the slot shouldn't be ignored. Chrome does not support this (yet) so, + // we'll skip this part for now. + return getComposedParent(element.assignedSlot); // content of a shadow DOM slot } else if (element.parentNode) { var parentNode = element.parentNode; if (parentNode.nodeType === 1) { diff --git a/test/checks/lists/dlitem.js b/test/checks/lists/dlitem.js index f8d50778c8..827e6a6405 100644 --- a/test/checks/lists/dlitem.js +++ b/test/checks/lists/dlitem.js @@ -2,26 +2,42 @@ describe('dlitem', function () { 'use strict'; var fixture = document.getElementById('fixture'); + var checkSetup = axe.testUtils.checkSetup; + var shadowSupport = axe.testUtils.shadowSupport; afterEach(function () { fixture.innerHTML = ''; }); it('should pass if the dlitem has a parent
', function () { - fixture.innerHTML = '
My list item
'; - var node = fixture.querySelector('#target'); + var checkArgs = checkSetup('
My list item
'); - assert.isTrue(checks.dlitem.evaluate(node)); + assert.isTrue(checks.dlitem.evaluate.apply(null, checkArgs)); + }); + it('should fail if the dlitem has an incorrect parent', function () { + var checkArgs = checkSetup('
'; - var node = fixture.querySelector('#target'); - assert.isFalse(checks['only-dlitems'].evaluate.call(checkContext, node)); + var checkArgs = checkSetup('
A list
'); + + assert.isFalse(checks['only-dlitems'].evaluate.apply(checkContext, checkArgs)); }); it('should return false if
A list
'; - var node = fixture.querySelector('#target'); - assert.isFalse(checks['only-dlitems'].evaluate.call(checkContext, node)); + var checkArgs = checkSetup('
A list
'); + + assert.isFalse(checks['only-dlitems'].evaluate.apply(checkContext, checkArgs)); }); it('should return false if