From d44c82c6fce8f1687b806edd7146437581245177 Mon Sep 17 00:00:00 2001 From: Wilco Fiers Date: Fri, 28 Jul 2023 14:28:00 +0200 Subject: [PATCH 1/4] feat(new-rule): aria-braille-equivalent finds incorrect uses of aria-braille attributes --- doc/rule-descriptions.md | 1 + .../aria/braille-label-equivalent-evaluate.js | 18 +++++ lib/checks/aria/braille-label-equivalent.json | 11 +++ ...lle-roledescription-equivalent-evaluate.js | 27 +++++++ .../braille-roledescription-equivalent.json | 14 ++++ lib/rules/aria-braille-equivalent.json | 12 +++ locales/_template.json | 15 ++++ test/checks/aria/braille-label-equivalent.js | 51 ++++++++++++ .../braille-roledescription-equivalent.js | 80 +++++++++++++++++++ .../aria-braille-equivalent.html | 27 +++++++ .../aria-braille-equivalent.json | 6 ++ 11 files changed, 262 insertions(+) create mode 100644 lib/checks/aria/braille-label-equivalent-evaluate.js create mode 100644 lib/checks/aria/braille-label-equivalent.json create mode 100644 lib/checks/aria/braille-roledescription-equivalent-evaluate.js create mode 100644 lib/checks/aria/braille-roledescription-equivalent.json create mode 100644 lib/rules/aria-braille-equivalent.json create mode 100644 test/checks/aria/braille-label-equivalent.js create mode 100644 test/checks/aria/braille-roledescription-equivalent.js create mode 100644 test/integration/rules/aria-braille-equivalent/aria-braille-equivalent.html create mode 100644 test/integration/rules/aria-braille-equivalent/aria-braille-equivalent.json diff --git a/doc/rule-descriptions.md b/doc/rule-descriptions.md index 6822972cbe..fdee514f62 100644 --- a/doc/rule-descriptions.md +++ b/doc/rule-descriptions.md @@ -16,6 +16,7 @@ | :------------------------------------------------------------------------------------------------------------------------------- | :---------------------------------------------------------------------------------------------------------------------------------------------------- | :---------------- | :--------------------------------------------------------------------------------------------------------------------------------- | :------------------------- | :----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | [area-alt](https://dequeuniversity.com/rules/axe/4.7/area-alt?application=RuleDescription) | Ensures <area> elements of image maps have alternate text | Critical | cat.text-alternatives, wcag2a, wcag244, wcag412, section508, section508.22.a, TTv5, TT6.a, EN-301-549, EN-9.2.4.4, EN-9.4.1.2, ACT | failure, needs review | [c487ae](https://act-rules.github.io/rules/c487ae) | | [aria-allowed-attr](https://dequeuniversity.com/rules/axe/4.7/aria-allowed-attr?application=RuleDescription) | Ensures an element's role supports its ARIA attributes | Serious, Critical | cat.aria, wcag2a, wcag412, EN-301-549, EN-9.4.1.2 | failure, needs review | [5c01ea](https://act-rules.github.io/rules/5c01ea) | +| [aria-braille-equivalent](https://dequeuniversity.com/rules/axe/4.7/aria-braille-equivalent?application=RuleDescription) | Ensure aria-braillelabel and aria-brailleroledescription have a non-braille equivalent | Serious | cat.aria, wcag2a, wcag412, EN-301-549, EN-9.4.1.2 | failure | | | [aria-command-name](https://dequeuniversity.com/rules/axe/4.7/aria-command-name?application=RuleDescription) | Ensures every ARIA button, link and menuitem has an accessible name | Serious | cat.aria, wcag2a, wcag412, TTv5, TT6.a, EN-301-549, EN-9.4.1.2, ACT | failure, needs review | [97a4e1](https://act-rules.github.io/rules/97a4e1) | | [aria-deprecated-role](https://dequeuniversity.com/rules/axe/4.7/aria-deprecated-role?application=RuleDescription) | Ensures elements do not use deprecated roles | Minor | cat.aria, wcag2a, wcag412, EN-301-549, EN-9.4.1.2 | failure | [674b10](https://act-rules.github.io/rules/674b10) | | [aria-hidden-body](https://dequeuniversity.com/rules/axe/4.7/aria-hidden-body?application=RuleDescription) | Ensures aria-hidden='true' is not present on the document body. | Critical | cat.aria, wcag2a, wcag412, EN-301-549, EN-9.4.1.2 | failure | | diff --git a/lib/checks/aria/braille-label-equivalent-evaluate.js b/lib/checks/aria/braille-label-equivalent-evaluate.js new file mode 100644 index 0000000000..8fc848ebc3 --- /dev/null +++ b/lib/checks/aria/braille-label-equivalent-evaluate.js @@ -0,0 +1,18 @@ +import { accessibleTextVirtual } from '../../commons/text'; + +/** + * Check that if aria-braillelabel is not empty, the element has an accessible text + * @memberof checks + * @return {Boolean} + */ +export default function brailleLabelEquivalentEvaluate( + node, + options, + virtualNode +) { + const brailleLabel = virtualNode.attr('aria-braillelabel') ?? ''; + if (!brailleLabel.trim()) { + return true; + } + return accessibleTextVirtual(virtualNode) !== ''; +} diff --git a/lib/checks/aria/braille-label-equivalent.json b/lib/checks/aria/braille-label-equivalent.json new file mode 100644 index 0000000000..6a2c0dcf91 --- /dev/null +++ b/lib/checks/aria/braille-label-equivalent.json @@ -0,0 +1,11 @@ +{ + "id": "braille-label-equivalent", + "evaluate": "braille-label-equivalent-evaluate", + "metadata": { + "impact": "serious", + "messages": { + "pass": "aria-braillelabel is not used on an element with no accessible text", + "fail": "aria-braillelabel is used on an element with no accessible text" + } + } +} diff --git a/lib/checks/aria/braille-roledescription-equivalent-evaluate.js b/lib/checks/aria/braille-roledescription-equivalent-evaluate.js new file mode 100644 index 0000000000..97c4c4b241 --- /dev/null +++ b/lib/checks/aria/braille-roledescription-equivalent-evaluate.js @@ -0,0 +1,27 @@ +/** + * Check that if aria-brailleroledescription is not empty, + * the element has a non-empty aria-roledescription + * @memberof checks + * @return {Boolean} + */ +export default function brailleRoleDescriptionEquivalentEvaluate( + node, + options, + virtualNode +) { + const brailleRoleDesc = virtualNode.attr('aria-brailleroledescription') ?? ''; + if (!brailleRoleDesc.trim()) { + return true; + } + const roleDesc = virtualNode.attr('aria-roledescription'); + if (typeof roleDesc !== 'string') { + this.data({ messageKey: 'noRoleDescription' }); + return false; + } + + if (roleDesc.trim() === '') { + this.data({ messageKey: 'emptyRoleDescription' }); + return false; + } + return true; +} diff --git a/lib/checks/aria/braille-roledescription-equivalent.json b/lib/checks/aria/braille-roledescription-equivalent.json new file mode 100644 index 0000000000..f7df5ca9dd --- /dev/null +++ b/lib/checks/aria/braille-roledescription-equivalent.json @@ -0,0 +1,14 @@ +{ + "id": "braille-roledescription-equivalent", + "evaluate": "braille-roledescription-equivalent-evaluate", + "metadata": { + "impact": "serious", + "messages": { + "pass": "aria-brailleroledescription is not used on an element with no accessible text", + "fail": { + "noRoleDescription": "aria-brailleroledescription is used on an element with no aria-roledescription", + "emptyRoleDescription": "aria-brailleroledescription is used on an element with an empty aria-roledescription" + } + } + } +} diff --git a/lib/rules/aria-braille-equivalent.json b/lib/rules/aria-braille-equivalent.json new file mode 100644 index 0000000000..c8509c93e7 --- /dev/null +++ b/lib/rules/aria-braille-equivalent.json @@ -0,0 +1,12 @@ +{ + "id": "aria-braille-equivalent", + "selector": "[aria-brailleroledescription], [aria-braillelabel]", + "tags": ["cat.aria", "wcag2a", "wcag412", "EN-301-549", "EN-9.4.1.2"], + "metadata": { + "description": "Ensure aria-braillelabel and aria-brailleroledescription have a non-braille equivalent", + "help": "aria-braille attributes must have a non-braille equivalent" + }, + "all": ["braille-roledescription-equivalent", "braille-label-equivalent"], + "any": [], + "none": [] +} diff --git a/locales/_template.json b/locales/_template.json index c294c41502..8cefeb206e 100644 --- a/locales/_template.json +++ b/locales/_template.json @@ -17,6 +17,10 @@ "description": "Ensures role attribute has an appropriate value for the element", "help": "ARIA role should be appropriate for the element" }, + "aria-braille-equivalent": { + "description": "Ensure aria-braillelabel and aria-brailleroledescription have a non-braille equivalent", + "help": "aria-braille attributes must have a non-braille equivalent" + }, "aria-command-name": { "description": "Ensures every ARIA button, link and menuitem has an accessible name", "help": "ARIA commands must have an accessible name" @@ -537,6 +541,17 @@ "plural": "Invalid ARIA attribute names: ${data.values}" } }, + "braille-label-equivalent": { + "pass": "aria-braillelabel is not used on an element with no accessible text", + "fail": "aria-braillelabel is used on an element with no accessible text" + }, + "braille-roledescription-equivalent": { + "pass": "aria-brailleroledescription is not used on an element with no accessible text", + "fail": { + "noRoleDescription": "aria-brailleroledescription is used on an element with no aria-roledescription", + "emptyRoleDescription": "aria-brailleroledescription is used on an element with an empty aria-roledescription" + } + }, "deprecatedrole": { "pass": "ARIA role is not deprecated", "fail": "The role used is deprecated: ${data}" diff --git a/test/checks/aria/braille-label-equivalent.js b/test/checks/aria/braille-label-equivalent.js new file mode 100644 index 0000000000..b98439bc28 --- /dev/null +++ b/test/checks/aria/braille-label-equivalent.js @@ -0,0 +1,51 @@ +describe('braille-label-equivalent tests', () => { + const { checkSetup, getCheckEvaluate } = axe.testUtils; + const checkContext = axe.testUtils.MockCheckContext(); + const checkEvaluate = getCheckEvaluate('braille-label-equivalent'); + + afterEach(() => { + checkContext.reset(); + }); + + it('returns true without aria-braillelabel', () => { + const params = checkSetup(''); + assert.isTrue(checkEvaluate.apply(checkContext, params)); + }); + + it('returns true when aria-braillelabel is empty', () => { + const params = checkSetup( + '' + ); + assert.isTrue(checkEvaluate.apply(checkContext, params)); + }); + + it('returns true when aria-braillelabel is whitespace-only', () => { + const params = checkSetup( + '' + ); + assert.isTrue(checkEvaluate.apply(checkContext, params)); + }); + + describe('when aria-braillelabel has text', () => { + it('returns false when the accessible name is empty', () => { + const params = checkSetup(` + + `); + assert.isFalse(checkEvaluate.apply(checkContext, params)); + }); + + it('returns false when the accessible name has only whitespace', () => { + const params = checkSetup(` +  \r\t\n + `); + assert.isFalse(checkEvaluate.apply(checkContext, params)); + }); + + it('returns true when the accessible name is not empty', () => { + const params = checkSetup(` + foo + `); + assert.isTrue(checkEvaluate.apply(checkContext, params)); + }); + }); +}); diff --git a/test/checks/aria/braille-roledescription-equivalent.js b/test/checks/aria/braille-roledescription-equivalent.js new file mode 100644 index 0000000000..3dda24c32d --- /dev/null +++ b/test/checks/aria/braille-roledescription-equivalent.js @@ -0,0 +1,80 @@ +describe('braille-roledescription-equivalent tests', () => { + const { checkSetup, getCheckEvaluate } = axe.testUtils; + const checkContext = axe.testUtils.MockCheckContext(); + const checkEvaluate = getCheckEvaluate('braille-roledescription-equivalent'); + + afterEach(() => { + checkContext.reset(); + }); + + it('returns true without aria-brailleroledescription', () => { + const params = checkSetup('
'); + assert.isTrue(checkEvaluate.apply(checkContext, params)); + }); + + it('returns true when aria-brailleroledecription is empty', () => { + const params = checkSetup( + '
' + ); + assert.isTrue(checkEvaluate.apply(checkContext, params)); + }); + + it('returns true when aria-brailleroledecription is whitespace-only', () => { + const params = checkSetup( + '
' + ); + assert.isTrue(checkEvaluate.apply(checkContext, params)); + }); + + describe('when aria-brailleroledescription has text', () => { + it('returns false without aria-roledescription', () => { + const params = checkSetup(` +
+ `); + assert.isFalse(checkEvaluate.apply(checkContext, params)); + assert.deepEqual(checkContext._data, { messageKey: 'noRoleDescription' }); + }); + + it('returns false when aria-roledescription is empty', () => { + const params = checkSetup(` +
+ `); + assert.isFalse(checkEvaluate.apply(checkContext, params)); + assert.deepEqual(checkContext._data, { + messageKey: 'emptyRoleDescription' + }); + }); + + it('returns false when aria-roledescription has only whitespace', () => { + const params = checkSetup(` +
+ `); + assert.isFalse(checkEvaluate.apply(checkContext, params)); + assert.deepEqual(checkContext._data, { + messageKey: 'emptyRoleDescription' + }); + }); + + it('returns true when aria-roledescription is not empty', () => { + const params = checkSetup(` +
+ `); + assert.isTrue(checkEvaluate.apply(checkContext, params)); + }); + }); +}); diff --git a/test/integration/rules/aria-braille-equivalent/aria-braille-equivalent.html b/test/integration/rules/aria-braille-equivalent/aria-braille-equivalent.html new file mode 100644 index 0000000000..55b9874d70 --- /dev/null +++ b/test/integration/rules/aria-braille-equivalent/aria-braille-equivalent.html @@ -0,0 +1,27 @@ + + + + + + + + + + + diff --git a/test/integration/rules/aria-braille-equivalent/aria-braille-equivalent.json b/test/integration/rules/aria-braille-equivalent/aria-braille-equivalent.json new file mode 100644 index 0000000000..725223482e --- /dev/null +++ b/test/integration/rules/aria-braille-equivalent/aria-braille-equivalent.json @@ -0,0 +1,6 @@ +{ + "description": "aria-braille-equivalent tests", + "rule": "aria-braille-equivalent", + "passes": [["#pass1"], ["#pass2"], ["#pass3"], ["#pass4"], ["#pass5"]], + "violations": [["#fail1"], ["#fail2"]] +} From 8ae0e6f9f5da5eae1421a1c15d1271679fa7304f Mon Sep 17 00:00:00 2001 From: Wilco Fiers Date: Fri, 28 Jul 2023 14:39:34 +0200 Subject: [PATCH 2/4] Fix test --- test/integration/full/isolated-env/isolated-env.html | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/integration/full/isolated-env/isolated-env.html b/test/integration/full/isolated-env/isolated-env.html index ddf770cfd6..e1d9d751e6 100644 --- a/test/integration/full/isolated-env/isolated-env.html +++ b/test/integration/full/isolated-env/isolated-env.html @@ -68,7 +68,7 @@

Ok

- + Date: Fri, 28 Jul 2023 14:52:07 +0200 Subject: [PATCH 3/4] More tests --- .../integration/full/all-rules/all-rules.html | 2 +- .../virtual-rules/aria-braille-equivalent.js | 61 +++++++++++++++++++ 2 files changed, 62 insertions(+), 1 deletion(-) create mode 100644 test/integration/virtual-rules/aria-braille-equivalent.js diff --git a/test/integration/full/all-rules/all-rules.html b/test/integration/full/all-rules/all-rules.html index ec5a5af5c1..631b2d2e32 100644 --- a/test/integration/full/all-rules/all-rules.html +++ b/test/integration/full/all-rules/all-rules.html @@ -68,7 +68,7 @@

Ok

- + { + afterEach(() => { + axe.reset(); + }); + + it('passes when aria-braillelabel is not empty', () => { + const results = axe.runVirtualRule('aria-braille-equivalent', { + nodeName: 'img', + attributes: { + alt: 'Hello world', + 'aria-braillelabel': 'Hello world' + } + }); + + assert.lengthOf(results.passes, 1); + assert.lengthOf(results.violations, 0); + assert.lengthOf(results.incomplete, 0); + }); + + it('fails when accessible text is empty but braille label is not', () => { + const results = axe.runVirtualRule('aria-braille-equivalent', { + nodeName: 'img', + attributes: { + alt: '', + 'aria-braillelabel': 'hello world' + } + }); + + assert.lengthOf(results.passes, 0); + assert.lengthOf(results.violations, 1); + assert.lengthOf(results.incomplete, 0); + }); + + it('passes when roledescription and brailleroledescription are not empty', () => { + const results = axe.runVirtualRule('aria-braille-equivalent', { + nodeName: 'div', + attributes: { + 'aria-roledescription': 'Hello world', + 'aria-brailleroledescription': 'Hello world' + } + }); + + assert.lengthOf(results.passes, 1); + assert.lengthOf(results.violations, 0); + assert.lengthOf(results.incomplete, 0); + }); + + it('fails when roledescription is empty but brailleroledescription is not', () => { + const results = axe.runVirtualRule('aria-braille-equivalent', { + nodeName: 'div', + attributes: { + 'aria-roledescription': '', + 'aria-brailleroledescription': 'Hello world' + } + }); + + assert.lengthOf(results.passes, 0); + assert.lengthOf(results.violations, 1); + assert.lengthOf(results.incomplete, 0); + }); +}); From c839ea69d0cee760c54685f4ca117d2b0ef88688 Mon Sep 17 00:00:00 2001 From: Wilco Fiers Date: Mon, 31 Jul 2023 12:32:52 +0200 Subject: [PATCH 4/4] Resolve feedback --- doc/rule-descriptions.md | 2 +- .../aria/braille-label-equivalent-evaluate.js | 8 ++++++-- lib/checks/aria/braille-label-equivalent.json | 5 +++-- .../braille-roledescription-equivalent-evaluate.js | 6 ++++-- locales/_template.json | 5 +++-- .../virtual-rules/aria-braille-equivalent.js | 13 +++++++++++++ 6 files changed, 30 insertions(+), 9 deletions(-) diff --git a/doc/rule-descriptions.md b/doc/rule-descriptions.md index fdee514f62..f2b9f7cde2 100644 --- a/doc/rule-descriptions.md +++ b/doc/rule-descriptions.md @@ -16,7 +16,7 @@ | :------------------------------------------------------------------------------------------------------------------------------- | :---------------------------------------------------------------------------------------------------------------------------------------------------- | :---------------- | :--------------------------------------------------------------------------------------------------------------------------------- | :------------------------- | :----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | [area-alt](https://dequeuniversity.com/rules/axe/4.7/area-alt?application=RuleDescription) | Ensures <area> elements of image maps have alternate text | Critical | cat.text-alternatives, wcag2a, wcag244, wcag412, section508, section508.22.a, TTv5, TT6.a, EN-301-549, EN-9.2.4.4, EN-9.4.1.2, ACT | failure, needs review | [c487ae](https://act-rules.github.io/rules/c487ae) | | [aria-allowed-attr](https://dequeuniversity.com/rules/axe/4.7/aria-allowed-attr?application=RuleDescription) | Ensures an element's role supports its ARIA attributes | Serious, Critical | cat.aria, wcag2a, wcag412, EN-301-549, EN-9.4.1.2 | failure, needs review | [5c01ea](https://act-rules.github.io/rules/5c01ea) | -| [aria-braille-equivalent](https://dequeuniversity.com/rules/axe/4.7/aria-braille-equivalent?application=RuleDescription) | Ensure aria-braillelabel and aria-brailleroledescription have a non-braille equivalent | Serious | cat.aria, wcag2a, wcag412, EN-301-549, EN-9.4.1.2 | failure | | +| [aria-braille-equivalent](https://dequeuniversity.com/rules/axe/4.7/aria-braille-equivalent?application=RuleDescription) | Ensure aria-braillelabel and aria-brailleroledescription have a non-braille equivalent | Serious | cat.aria, wcag2a, wcag412, EN-301-549, EN-9.4.1.2 | failure, needs review | | | [aria-command-name](https://dequeuniversity.com/rules/axe/4.7/aria-command-name?application=RuleDescription) | Ensures every ARIA button, link and menuitem has an accessible name | Serious | cat.aria, wcag2a, wcag412, TTv5, TT6.a, EN-301-549, EN-9.4.1.2, ACT | failure, needs review | [97a4e1](https://act-rules.github.io/rules/97a4e1) | | [aria-deprecated-role](https://dequeuniversity.com/rules/axe/4.7/aria-deprecated-role?application=RuleDescription) | Ensures elements do not use deprecated roles | Minor | cat.aria, wcag2a, wcag412, EN-301-549, EN-9.4.1.2 | failure | [674b10](https://act-rules.github.io/rules/674b10) | | [aria-hidden-body](https://dequeuniversity.com/rules/axe/4.7/aria-hidden-body?application=RuleDescription) | Ensures aria-hidden='true' is not present on the document body. | Critical | cat.aria, wcag2a, wcag412, EN-301-549, EN-9.4.1.2 | failure | | diff --git a/lib/checks/aria/braille-label-equivalent-evaluate.js b/lib/checks/aria/braille-label-equivalent-evaluate.js index 8fc848ebc3..ce301f684b 100644 --- a/lib/checks/aria/braille-label-equivalent-evaluate.js +++ b/lib/checks/aria/braille-label-equivalent-evaluate.js @@ -1,4 +1,4 @@ -import { accessibleTextVirtual } from '../../commons/text'; +import { sanitize, accessibleTextVirtual } from '../../commons/text'; /** * Check that if aria-braillelabel is not empty, the element has an accessible text @@ -14,5 +14,9 @@ export default function brailleLabelEquivalentEvaluate( if (!brailleLabel.trim()) { return true; } - return accessibleTextVirtual(virtualNode) !== ''; + try { + return sanitize(accessibleTextVirtual(virtualNode)) !== ''; + } catch { + return undefined; + } } diff --git a/lib/checks/aria/braille-label-equivalent.json b/lib/checks/aria/braille-label-equivalent.json index 6a2c0dcf91..a4d4dd0c1d 100644 --- a/lib/checks/aria/braille-label-equivalent.json +++ b/lib/checks/aria/braille-label-equivalent.json @@ -4,8 +4,9 @@ "metadata": { "impact": "serious", "messages": { - "pass": "aria-braillelabel is not used on an element with no accessible text", - "fail": "aria-braillelabel is used on an element with no accessible text" + "pass": "aria-braillelabel is used on an element with accessible text", + "fail": "aria-braillelabel is used on an element with no accessible text", + "incomplete": "Unable to compute accessible text" } } } diff --git a/lib/checks/aria/braille-roledescription-equivalent-evaluate.js b/lib/checks/aria/braille-roledescription-equivalent-evaluate.js index 97c4c4b241..5e03af7fac 100644 --- a/lib/checks/aria/braille-roledescription-equivalent-evaluate.js +++ b/lib/checks/aria/braille-roledescription-equivalent-evaluate.js @@ -1,3 +1,5 @@ +import { sanitize } from '../../commons/text'; + /** * Check that if aria-brailleroledescription is not empty, * the element has a non-empty aria-roledescription @@ -10,7 +12,7 @@ export default function brailleRoleDescriptionEquivalentEvaluate( virtualNode ) { const brailleRoleDesc = virtualNode.attr('aria-brailleroledescription') ?? ''; - if (!brailleRoleDesc.trim()) { + if (sanitize(brailleRoleDesc) === '') { return true; } const roleDesc = virtualNode.attr('aria-roledescription'); @@ -19,7 +21,7 @@ export default function brailleRoleDescriptionEquivalentEvaluate( return false; } - if (roleDesc.trim() === '') { + if (sanitize(roleDesc) === '') { this.data({ messageKey: 'emptyRoleDescription' }); return false; } diff --git a/locales/_template.json b/locales/_template.json index 8cefeb206e..2a58c22418 100644 --- a/locales/_template.json +++ b/locales/_template.json @@ -542,8 +542,9 @@ } }, "braille-label-equivalent": { - "pass": "aria-braillelabel is not used on an element with no accessible text", - "fail": "aria-braillelabel is used on an element with no accessible text" + "pass": "aria-braillelabel is used on an element with accessible text", + "fail": "aria-braillelabel is used on an element with no accessible text", + "incomplete": "Unable to compute accessible text" }, "braille-roledescription-equivalent": { "pass": "aria-brailleroledescription is not used on an element with no accessible text", diff --git a/test/integration/virtual-rules/aria-braille-equivalent.js b/test/integration/virtual-rules/aria-braille-equivalent.js index d86031f802..481697f0e9 100644 --- a/test/integration/virtual-rules/aria-braille-equivalent.js +++ b/test/integration/virtual-rules/aria-braille-equivalent.js @@ -58,4 +58,17 @@ describe('aria-braille-equivalent virtual-rule', () => { assert.lengthOf(results.violations, 1); assert.lengthOf(results.incomplete, 0); }); + + it('incompletes if the subtree fails to compute with aria-braillelabel', () => { + const results = axe.runVirtualRule('aria-braille-equivalent', { + nodeName: 'button', + attributes: { + 'aria-braillelabel': 'Hello world' + } + }); + + assert.lengthOf(results.passes, 0); + assert.lengthOf(results.violations, 0); + assert.lengthOf(results.incomplete, 1); + }); });