diff --git a/lib/checks/lists/dlitem.js b/lib/checks/lists/dlitem.js
index a750334627..55bde622f0 100644
--- a/lib/checks/lists/dlitem.js
+++ b/lib/checks/lists/dlitem.js
@@ -1,17 +1,22 @@
-const parent = axe.commons.dom.getComposedParent(node);
-const parentTagName = parent.nodeName.toUpperCase();
+let parent = axe.commons.dom.getComposedParent(node);
+let parentTagName = parent.nodeName.toUpperCase();
+let parentRole = axe.commons.aria.getRole(parent, { noImplicit: true });
+
+if (
+ parentTagName === 'DIV' &&
+ ['presentation', 'none', null].includes(parentRole)
+) {
+ parent = axe.commons.dom.getComposedParent(parent);
+ parentTagName = parent.nodeName.toUpperCase();
+ parentRole = axe.commons.aria.getRole(parent, { noImplicit: true });
+}
// Unlike with UL|OL+LI, DT|DD must be in a DL
if (parentTagName !== 'DL') {
return false;
}
-const parentRole = (parent.getAttribute('role') || '').toLowerCase();
-if (!parentRole || !axe.commons.aria.isValidRole(parentRole)) {
- return true;
-}
-
-if (parentRole === 'list') {
+if (!parentRole || parentRole === 'list') {
return true;
}
diff --git a/test/checks/lists/dlitem.js b/test/checks/lists/dlitem.js
index 615df2f2c5..38a3ccceb0 100644
--- a/test/checks/lists/dlitem.js
+++ b/test/checks/lists/dlitem.js
@@ -10,60 +10,116 @@ describe('dlitem', function() {
});
it('should pass if the dlitem has a parent
', function() {
- var checkArgs = checkSetup('- My list item
');
+ var checkArgs = checkSetup('- My list item
');
assert.isTrue(checks.dlitem.evaluate.apply(null, checkArgs));
});
it('should fail if the dt element has an incorrect parent', function() {
- var checkArgs = checkSetup('');
+ var checkArgs = checkSetup(
+ ''
+ );
assert.isFalse(checks.dlitem.evaluate.apply(null, checkArgs));
});
it('should pass if the dt element has a parent with role="list"', function() {
var checkArgs = checkSetup(
- '- My list item
'
+ '- My list item
'
);
assert.isTrue(checks.dlitem.evaluate.apply(null, checkArgs));
});
it('should fail if the dt element has a parent with role="presentation"', function() {
var checkArgs = checkSetup(
- '- My list item
'
+ '- My list item
'
);
assert.isFalse(checks.dlitem.evaluate.apply(null, checkArgs));
});
it('should fail if the dt element has a parent with a changed role', function() {
var checkArgs = checkSetup(
- '- My list item
'
+ '- My list item<
/dl>'
);
assert.isFalse(checks.dlitem.evaluate.apply(null, checkArgs));
});
it('should pass if the dt element has a parent with an abstract role', function() {
var checkArgs = checkSetup(
- '- My list item
'
+ '- My list item
'
);
assert.isTrue(checks.dlitem.evaluate.apply(null, checkArgs));
});
it('should pass if the dt element has a parent with an invalid role', function() {
var checkArgs = checkSetup(
- '- My list item
'
+ '- My list item
'
);
assert.isTrue(checks.dlitem.evaluate.apply(null, checkArgs));
});
it('should fail if the dt element has a parent with a changed role', function() {
var checkArgs = checkSetup(
- '- My list item
'
+ '- My list item
'
);
assert.isFalse(checks.dlitem.evaluate.apply(null, checkArgs));
});
- (shadowSupport.v1 ? it : xit)(
+ it('returns true if the dd/dt is in a div with a dl as grandparent', function() {
+ const nodeNames = ['dd', 'dt'];
+ nodeNames.forEach(function(nodeName) {
+ var checkArgs = checkSetup(
+ '<' +
+ nodeName +
+ ' id="target">My list item' +
+ nodeName +
+ '>
'
+ );
+ assert.isTrue(checks.dlitem.evaluate.apply(null, checkArgs));
+ });
+ });
+
+ it('returns false if the dd/dt is in a div with a role with a dl as grandparent with a list role', function() {
+ const nodeNames = ['dd', 'dt'];
+ nodeNames.forEach(function(nodeName) {
+ var checkArgs = checkSetup(
+ '<' +
+ nodeName +
+ ' id="target">My list item' +
+ nodeName +
+ '>
'
+ );
+ assert.isFalse(checks.dlitem.evaluate.apply(null, checkArgs));
+ });
+ });
+
+ it('returns false if the dd/dt is in a div[role=presentation] with a dl as grandparent', function() {
+ const nodeNames = ['dd', 'dt'];
+ nodeNames.forEach(function(nodeName) {
+ var checkArgs = checkSetup(
+ '<' +
+ nodeName +
+ ' id="target">My list item' +
+ nodeName +
+ '>
'
+ );
+ assert.isTrue(checks.dlitem.evaluate.apply(null, checkArgs));
+ });
+ });
+
+ it('returns false if the dd/dt is in a div[role=none] with a dl as grandparent', function() {
+ const nodeNames = ['dd', 'dt'];
+ nodeNames.forEach(function(nodeName) {
+ var checkArgs = checkSetup(
+ '<' +
+ nodeName +
+ ' id="target">My list item' +
+ nodeName +
+ '>
'
+ );
+ assert.isTrue(checks.dlitem.evaluate.apply(null, checkArgs));
+ });
+ })(shadowSupport.v1 ? it : xit)(
'should return true in a shadow DOM pass',
function() {
var node = document.createElement('div');
@@ -88,4 +144,17 @@ describe('dlitem', function() {
assert.isFalse(checks.dlitem.evaluate.apply(null, checkArgs));
}
);
+
+ (shadowSupport.v1 ? it : xit)(
+ 'should return true when the item is grouped in dl > div in a shadow DOM',
+ function() {
+ var node = document.createElement('div');
+ node.innerHTML = '- My list item
';
+ var shadow = node.attachShadow({ mode: 'open' });
+ shadow.innerHTML = '
';
+
+ var checkArgs = checkSetup(node, 'dt');
+ assert.isTrue(checks.dlitem.evaluate.apply(null, checkArgs));
+ }
+ );
});
diff --git a/test/integration/rules/dlitem/dlitem.html b/test/integration/rules/dlitem/dlitem.html
index 3c92602827..429bfa0d6b 100644
--- a/test/integration/rules/dlitem/dlitem.html
+++ b/test/integration/rules/dlitem/dlitem.html
@@ -3,8 +3,16 @@
- Does belong to a list.
- Also belongs to a list.
+
+
- Grouped in a div.
+ - Also grouped in a div.
+
+
+
- Grouped in a div with role.
+ - Also grouped in a div with role.
+
- Not part of a list.
- Also not part of a list.
-
\ No newline at end of file
+
diff --git a/test/integration/rules/dlitem/dlitem.json b/test/integration/rules/dlitem/dlitem.json
index 072c342503..d7f5c7ce6d 100644
--- a/test/integration/rules/dlitem/dlitem.json
+++ b/test/integration/rules/dlitem/dlitem.json
@@ -5,7 +5,9 @@
["#uncontained"],
["#alsouncontained"],
["#uncontainedbyrole"],
- ["#alsouncontainedbyrole"]
+ ["#alsouncontainedbyrole"],
+ ["#incorrectlygrouped"],
+ ["#alsoincorrectlygrouped"]
],
- "passes": [["#contained"], ["#alsocontained"]]
+ "passes": [["#contained"], ["#alsocontained"], ["#grouped"], ["#alsogrouped"]]
}