From 522865cabbe1f4815b1f3e980018e24c062c8e5e Mon Sep 17 00:00:00 2001 From: Steven Lambert <2433219+straker@users.noreply.github.com> Date: Fri, 28 Aug 2020 11:39:14 -0600 Subject: [PATCH] fix(required-parent): fail if intermediate role is not the required parent (#2494) * fix(required-parent): fail if intermediate role is not the required parent * allow presentational intermediate roles * typo --- .../aria/aria-required-parent-evaluate.js | 5 +++ test/checks/aria/required-parent.js | 44 +++++++++++++++++++ .../aria-required-parent.html | 24 ++++++++++ .../aria-required-parent.json | 14 +++++- 4 files changed, 85 insertions(+), 2 deletions(-) diff --git a/lib/checks/aria/aria-required-parent-evaluate.js b/lib/checks/aria/aria-required-parent-evaluate.js index 310a5772ac..e0694572a7 100644 --- a/lib/checks/aria/aria-required-parent-evaluate.js +++ b/lib/checks/aria/aria-required-parent-evaluate.js @@ -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; diff --git a/test/checks/aria/required-parent.js b/test/checks/aria/required-parent.js index e082aa8b1c..10281731bf 100644 --- a/test/checks/aria/required-parent.js +++ b/test/checks/aria/required-parent.js @@ -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( + '

Nothing here.

' + ); + assert.isFalse( + axe.testUtils + .getCheckEvaluate('aria-required-parent') + .apply(checkContext, params) + ); + }); + + it('should pass when intermediate node is role=presentation', function() { + var params = checkSetup( + '

Nothing here.

' + ); + assert.isTrue( + axe.testUtils + .getCheckEvaluate('aria-required-parent') + .apply(checkContext, params) + ); + }); + + it('should pass when intermediate node is role=none', function() { + var params = checkSetup( + '

Nothing here.

' + ); + 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( + '

Nothing here.

' + ); + 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() { diff --git a/test/integration/rules/aria-required-parent/aria-required-parent.html b/test/integration/rules/aria-required-parent/aria-required-parent.html index 5815dcf72d..36736ecf65 100644 --- a/test/integration/rules/aria-required-parent/aria-required-parent.html +++ b/test/integration/rules/aria-required-parent/aria-required-parent.html @@ -14,3 +14,27 @@
Item 1
+ +
+
+
Item 1
+
+
+ +
+ +
+ +
+ +
+ +
+
+
Item 1
+
+
diff --git a/test/integration/rules/aria-required-parent/aria-required-parent.json b/test/integration/rules/aria-required-parent/aria-required-parent.json index 91d50f2cfe..5bd7532210 100644 --- a/test/integration/rules/aria-required-parent/aria-required-parent.json +++ b/test/integration/rules/aria-required-parent/aria-required-parent.json @@ -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"], @@ -16,6 +16,16 @@ ["#pass11"], ["#pass12"], ["#pass13"], - ["#pass14"] + ["#pass14"], + ["#pass15"], + ["#pass16"], + ["#pass17"], + ["#pass18"], + ["#pass19"], + ["#pass20"], + ["#pass21"], + ["#pass22"], + ["#pass23"], + ["#pass24"] ] }