diff --git a/lib/checks/aria/aria-errormessage-evaluate.js b/lib/checks/aria/aria-errormessage-evaluate.js index 6986efdb78..bacb1c9c7c 100644 --- a/lib/checks/aria/aria-errormessage-evaluate.js +++ b/lib/checks/aria/aria-errormessage-evaluate.js @@ -1,7 +1,7 @@ import standards from '../../standards'; import { idrefs } from '../../commons/dom'; import { tokenList } from '../../core/utils'; - +import { isVisible } from '../../commons/dom'; /** * Check if `aria-errormessage` references an element that also uses a technique to announce the message (aria-live, aria-describedby, etc.). * @@ -55,6 +55,13 @@ function ariaErrormessageEvaluate(node, options, virtualNode) { } if (idref) { + if (!isVisible(idref, true)) { + this.data({ + messageKey: 'hidden', + values: tokenList(attr) + }); + return false; + } return ( idref.getAttribute('role') === 'alert' || idref.getAttribute('aria-live') === 'assertive' || @@ -62,6 +69,7 @@ function ariaErrormessageEvaluate(node, options, virtualNode) { tokenList(virtualNode.attr('aria-describedby')).indexOf(attr) > -1 ); } + return; } diff --git a/lib/checks/aria/aria-errormessage.json b/lib/checks/aria/aria-errormessage.json index ce672a591c..84901729af 100644 --- a/lib/checks/aria/aria-errormessage.json +++ b/lib/checks/aria/aria-errormessage.json @@ -7,7 +7,8 @@ "pass": "aria-errormessage exists and references elements visible to screen readers that use a supported aria-errormessage technique", "fail": { "singular": "aria-errormessage value `${data.values}` must use a technique to announce the message (e.g., aria-live, aria-describedby, role=alert, etc.)", - "plural": "aria-errormessage values `${data.values}` must use a technique to announce the message (e.g., aria-live, aria-describedby, role=alert, etc.)" + "plural": "aria-errormessage values `${data.values}` must use a technique to announce the message (e.g., aria-live, aria-describedby, role=alert, etc.)", + "hidden": "aria-errormessage value `${data.values}` cannot reference a hidden element" }, "incomplete": { "singular": "ensure aria-errormessage value `${data.values}` references an existing element", diff --git a/test/checks/aria/errormessage.js b/test/checks/aria/errormessage.js index 1fc42bcb92..e54f44ffed 100644 --- a/test/checks/aria/errormessage.js +++ b/test/checks/aria/errormessage.js @@ -144,6 +144,94 @@ describe('aria-errormessage', function() { ); }); + it('should return false when hidden attribute is used', function() { + var vNode = queryFixture( + '' + + '' + ); + assert.isFalse( + axe.testUtils + .getCheckEvaluate('aria-errormessage') + .call(checkContext, null, null, vNode) + ); + assert.deepEqual(checkContext._data, { + messageKey: 'hidden', + values: ['id-message-1'] + }); + }); + + it('should return false when display: "none" is used', function() { + var vNode = queryFixture( + '' + + '' + ); + assert.isFalse( + axe.testUtils + .getCheckEvaluate('aria-errormessage') + .call(checkContext, null, null, vNode) + ); + assert.deepEqual(checkContext._data, { + messageKey: 'hidden', + values: ['id-message-1'] + }); + }); + + it('should return false when visibility: "hidden" is used', function() { + var vNode = queryFixture( + '' + + '' + ); + assert.isFalse( + axe.testUtils + .getCheckEvaluate('aria-errormessage') + .call(checkContext, null, null, vNode) + ); + assert.deepEqual(checkContext._data, { + messageKey: 'hidden', + values: ['id-message-1'] + }); + }); + + it('should return false when aria-hidden=true is used', function() { + var vNode = queryFixture( + '' + + '' + ); + assert.isFalse( + axe.testUtils + .getCheckEvaluate('aria-errormessage') + .call(checkContext, null, null, vNode) + ); + assert.deepEqual(checkContext._data, { + messageKey: 'hidden', + values: ['id-message-1'] + }); + }); + + it('should return true when aria-hidden=false is used', function() { + var vNode = queryFixture( + '' + + '
Error message 1
' + ); + assert.isTrue( + axe.testUtils + .getCheckEvaluate('aria-errormessage') + .call(checkContext, null, null, vNode) + ); + }); + + it('should return true when no hidden functionality is used', function() { + var vNode = queryFixture( + '' + + '
Error message 1
' + ); + assert.isTrue( + axe.testUtils + .getCheckEvaluate('aria-errormessage') + .call(checkContext, null, null, vNode) + ); + }); + (shadowSupported ? it : xit)( 'should return undefined if aria-errormessage value crosses shadow boundary', function() { diff --git a/test/integration/rules/aria-valid-attr-value/aria-valid-attr-value.html b/test/integration/rules/aria-valid-attr-value/aria-valid-attr-value.html index 52448862ff..e34c9d38dc 100644 --- a/test/integration/rules/aria-valid-attr-value/aria-valid-attr-value.html +++ b/test/integration/rules/aria-valid-attr-value/aria-valid-attr-value.html @@ -51,6 +51,46 @@

Violations

hi
hi
+ +
+ + +
+ +
+ + +
+ +
+ + +
+ +
+ + +

Possible False Positives

@@ -276,6 +316,35 @@

Possible False Positives

hi
hi
+
+ +
+ +
hi
+ +
+ +
+ +
+ +
+
Hi
Hi2
diff --git a/test/integration/rules/aria-valid-attr-value/aria-valid-attr-value.json b/test/integration/rules/aria-valid-attr-value/aria-valid-attr-value.json index 6abcb9708b..e6e23e5ec4 100644 --- a/test/integration/rules/aria-valid-attr-value/aria-valid-attr-value.json +++ b/test/integration/rules/aria-valid-attr-value/aria-valid-attr-value.json @@ -41,7 +41,11 @@ ["#violation40"], ["#violation41"], ["#violation42"], - ["#violation43"] + ["#violation43"], + ["#violation44"], + ["#violation45"], + ["#violation46"], + ["#violation47"] ], "passes": [ ["#pass1"], @@ -220,7 +224,11 @@ ["#pass183"], ["#pass184"], ["#pass185"], - ["#pass186"] + ["#pass186"], + ["#pass187"], + ["#pass188"], + ["#pass189"], + ["#pass190"] ], "incomplete": [ ["#incomplete1"],