Skip to content

Commit

Permalink
fix(required-parent): fail if intermediate role is not the required p…
Browse files Browse the repository at this point in the history
…arent (#2494)

* fix(required-parent): fail if intermediate role is not the required parent

* allow presentational intermediate roles

* typo
  • Loading branch information
straker committed Sep 8, 2020
1 parent 0b151a3 commit 522865c
Show file tree
Hide file tree
Showing 4 changed files with 85 additions and 2 deletions.
5 changes: 5 additions & 0 deletions lib/checks/aria/aria-required-parent-evaluate.js
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,13 @@ function getMissingContext(virtualNode, reqContext, includeElement) {
let vNode = includeElement ? virtualNode : virtualNode.parent;
while (vNode) {
const parentRole = getRole(vNode);

// if parent node has a role that is not the required role and not
// presentational we will fail the check
if (reqContext.includes(parentRole)) {
return null;
} else if (parentRole && !['presentation', 'none'].includes(parentRole)) {
return reqContext;
}

vNode = vNode.parent;
Expand Down
44 changes: 44 additions & 0 deletions test/checks/aria/required-parent.js
Original file line number Diff line number Diff line change
Expand Up @@ -106,6 +106,50 @@ describe('aria-required-parent', function() {
);
});

it('should fail when there is an intermediate role between the child and parent', function() {
var params = checkSetup(
'<div role="list"><div role="tabpanel"><p role="listitem" id="target">Nothing here.</p></div></div>'
);
assert.isFalse(
axe.testUtils
.getCheckEvaluate('aria-required-parent')
.apply(checkContext, params)
);
});

it('should pass when intermediate node is role=presentation', function() {
var params = checkSetup(
'<div role="list"><div role="presentation"><p role="listitem" id="target">Nothing here.</p></div></div>'
);
assert.isTrue(
axe.testUtils
.getCheckEvaluate('aria-required-parent')
.apply(checkContext, params)
);
});

it('should pass when intermediate node is role=none', function() {
var params = checkSetup(
'<div role="list"><div role="none"><p role="listitem" id="target">Nothing here.</p></div></div>'
);
assert.isTrue(
axe.testUtils
.getCheckEvaluate('aria-required-parent')
.apply(checkContext, params)
);
});

it('should pass when intermediate node is not owned by parent', function() {
var params = checkSetup(
'<div role="list" aria-owns="target"><div role="navigation"><p role="listitem" id="target">Nothing here.</p></div></div>'
);
assert.isTrue(
axe.testUtils
.getCheckEvaluate('aria-required-parent')
.apply(checkContext, params)
);
});

(shadowSupported ? it : xit)(
'should pass when required parent is present across shadow boundary',
function() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,3 +14,27 @@
<div role="treegrid" id="pass13">
<div role="rowgroup" id="pass14">Item 1</div>
</div>

<div role="treegrid" id="pass15">
<div role="listitem" id="fail4">
<div role="rowgroup" id="fail5">Item 1</div>
</div>
</div>

<div role="treegrid" id="pass16">
<div role="presentation" id="pass17">
<div role="rowgroup" id="pass18">Item 1</div>
</div>
</div>

<div role="treegrid" id="pass19">
<div role="presentation" id="pass20">
<div role="rowgroup" id="pass21">Item 1</div>
</div>
</div>

<div role="treegrid" id="pass22" aria-owns="pass24">
<div role="list" id="pass23">
<div role="rowgroup" id="pass24">Item 1</div>
</div>
</div>
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"description": "aria-required-parent test",
"rule": "aria-required-parent",
"violations": [["#fail1"], ["#fail2"], ["#fail3"]],
"violations": [["#fail1"], ["#fail2"], ["#fail3"], ["#fail4"], ["#fail5"]],
"passes": [
["#pass1"],
["#pass2"],
Expand All @@ -16,6 +16,16 @@
["#pass11"],
["#pass12"],
["#pass13"],
["#pass14"]
["#pass14"],
["#pass15"],
["#pass16"],
["#pass17"],
["#pass18"],
["#pass19"],
["#pass20"],
["#pass21"],
["#pass22"],
["#pass23"],
["#pass24"]
]
}

0 comments on commit 522865c

Please sign in to comment.