diff --git a/lib/checks/aria/required-children.js b/lib/checks/aria/required-children.js index 0ae3aada6a..afbf76f822 100644 --- a/lib/checks/aria/required-children.js +++ b/lib/checks/aria/required-children.js @@ -39,20 +39,23 @@ function ariaOwns(nodes, role) { } function missingRequiredChildren(node, childRoles, all, role) { - var i, - l = childRoles.length, + var index, + length = childRoles.length, missing = [], ownedElements = idrefs(node, 'aria-owns'); - for (i = 0; i < l; i++) { - var r = childRoles[i]; - if (owns(node, virtualNode, r) || ariaOwns(ownedElements, r)) { + for (index = 0; index < length; index++) { + var childRole = childRoles[index]; + if ( + owns(node, virtualNode, childRole) || + ariaOwns(ownedElements, childRole) + ) { if (!all) { return null; } } else { if (all) { - missing.push(r); + missing.push(childRole); } } } @@ -109,7 +112,12 @@ if (!missing) { this.data(missing); -if (reviewEmpty.includes(role)) { +// Only review empty nodes when a node is both empty and does not have an aria-owns relationship +if ( + reviewEmpty.includes(role) && + node.children.length === 0 && + idrefs(node, 'aria-owns').length === 0 +) { return undefined; } else { return false; diff --git a/lib/checks/aria/required-children.json b/lib/checks/aria/required-children.json index 4ad80cdf12..6f4fd8a8fa 100644 --- a/lib/checks/aria/required-children.json +++ b/lib/checks/aria/required-children.json @@ -2,7 +2,18 @@ "id": "aria-required-children", "evaluate": "required-children.js", "options": { - "reviewEmpty": ["listbox"] + "reviewEmpty": [ + "doc-bibliography", + "doc-endnotes", + "grid", + "list", + "listbox", + "table", + "tablist", + "tree", + "treegrid", + "rowgroup" + ] }, "metadata": { "impact": "critical", diff --git a/lib/commons/aria/index.js b/lib/commons/aria/index.js index ab3fa350b2..f97e4829ac 100644 --- a/lib/commons/aria/index.js +++ b/lib/commons/aria/index.js @@ -624,7 +624,9 @@ lookupTable.role = { attributes: { allowed: ['aria-expanded', 'aria-errormessage'] }, - owned: null, + owned: { + one: ['doc-biblioentry'] + }, nameFrom: ['author'], context: null, unsupported: false, @@ -746,7 +748,9 @@ lookupTable.role = { attributes: { allowed: ['aria-expanded', 'aria-errormessage'] }, - owned: ['doc-endnote'], + owned: { + one: ['doc-endnote'] + }, namefrom: ['author'], context: null, unsupported: false, @@ -1280,7 +1284,9 @@ lookupTable.role = { 'aria-errormessage' ] }, - owned: null, + owned: { + one: ['menuitem', 'menuitemradio', 'menuitemcheckbox'] + }, nameFrom: ['author'], context: null, unsupported: false, diff --git a/test/checks/aria/required-children.js b/test/checks/aria/required-children.js index 7ebb0dbefc..cc6bfe00ad 100644 --- a/test/checks/aria/required-children.js +++ b/test/checks/aria/required-children.js @@ -103,6 +103,35 @@ describe('aria-required-children', function() { ); }); + it('should return undefined when element is empty and is in reviewEmpty options', function() { + var params = checkSetup('
', { + reviewEmpty: ['list'] + }); + assert.isUndefined( + checks['aria-required-children'].evaluate.apply(checkContext, params) + ); + }); + + it('should return false when children do not have correct role and is in reviewEmpty options', function() { + var params = checkSetup( + '