diff --git a/lib/checks/aria/valid-attr-value.js b/lib/checks/aria/valid-attr-value.js index 05e0715c15..5acb9ff62e 100644 --- a/lib/checks/aria/valid-attr-value.js +++ b/lib/checks/aria/valid-attr-value.js @@ -1,15 +1,16 @@ options = Array.isArray(options) ? options : []; +const needsReview = []; const invalid = []; const aria = /^aria-/; const attrs = axe.utils.getNodeAttributes(node); const skipAttrs = ['aria-errormessage']; -// aria-controls should only check if element exists if the element -// doesn't have aria-expanded=false or aria-selected=false (tabs) -// @see https://github.com/dequelabs/axe-core/issues/1463 const preChecks = { + // aria-controls should only check if element exists if the element + // doesn't have aria-expanded=false or aria-selected=false (tabs) + // @see https://github.com/dequelabs/axe-core/issues/1463 'aria-controls': function() { return ( node.getAttribute('aria-expanded') !== 'false' && @@ -21,6 +22,18 @@ const preChecks = { // @see https://github.com/dequelabs/axe-core/issues/1524 'aria-owns': function() { return node.getAttribute('aria-expanded') !== 'false'; + }, + // aria-describedby should not mark missing element as violation but + // instead as needs review + // @see https://github.com/dequelabs/axe-core/issues/1151 + 'aria-describedby': function() { + if (!axe.commons.aria.validateAttrValue(node, 'aria-describedby')) { + needsReview.push( + `aria-describedby="${node.getAttribute('aria-describedby')}"` + ); + } + + return; } }; @@ -39,6 +52,11 @@ for (let i = 0, l = attrs.length; i < l; i++) { } } +if (needsReview.length) { + this.data(needsReview); + return undefined; +} + if (invalid.length) { this.data(invalid); return false; diff --git a/lib/checks/aria/valid-attr-value.json b/lib/checks/aria/valid-attr-value.json index 02a77bbda2..965e5b4fce 100644 --- a/lib/checks/aria/valid-attr-value.json +++ b/lib/checks/aria/valid-attr-value.json @@ -6,7 +6,8 @@ "impact": "critical", "messages": { "pass": "ARIA attribute values are valid", - "fail": "Invalid ARIA attribute value{{=it.data && it.data.length > 1 ? 's' : ''}}:{{~it.data:value}} {{=value}}{{~}}" + "fail": "Invalid ARIA attribute value{{=it.data && it.data.length > 1 ? 's' : ''}}:{{~it.data:value}} {{=value}}{{~}}", + "incomplete": "ARIA attribute{=it.data && it.data.length > 1 ? 's' : ''}} element ID does not exist on the page:{{~it.data:value}} {{=value}}{{~}}" } } } diff --git a/test/checks/aria/valid-attr-value.js b/test/checks/aria/valid-attr-value.js index d62a25695e..0393473cfa 100644 --- a/test/checks/aria/valid-attr-value.js +++ b/test/checks/aria/valid-attr-value.js @@ -205,6 +205,14 @@ describe('aria-valid-attr-value', function() { ); }); + it('should return undefined on aria-describedby when the element is not in the DOM', function() { + fixtureSetup(''); + var undefined1 = fixture.querySelector('button'); + assert.isUndefined( + checks['aria-valid-attr-value'].evaluate.call(checkContext, undefined1) + ); + }); + describe('options', function() { it('should exclude supplied attributes', function() { fixture.innerHTML = 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 bc3c11d82f..4cbacf9cc3 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 @@ -12,7 +12,6 @@

Violations

hi
hi
hi
-
hi
hi
hi
hi
@@ -269,4 +268,6 @@

Possible False Positives

Hi
Hi2
+ +
hi
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 969bc190f7..662ada6764 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 @@ -10,7 +10,6 @@ ["#violation6"], ["#violation7"], ["#violation8"], - ["#violation9"], ["#violation10"], ["#violation11"], ["#violation12"], @@ -224,5 +223,6 @@ ["#pass182"], ["#pass183"], ["#pass184"] - ] + ], + "incomplete": [["#incomplete1"]] }