From e3a5c211fe007736d98a16d69995318c2c651f2d Mon Sep 17 00:00:00 2001 From: Steven Lambert <2433219+straker@users.noreply.github.com> Date: Fri, 24 Mar 2023 08:47:24 -0600 Subject: [PATCH 1/7] fix(scrollable-region-focusable): change impact to serious (#3959) * fix(scrollable-region-focusable): change impact to serious * forgot check --- doc/rule-descriptions.md | 2 +- lib/checks/keyboard/focusable-content.json | 2 +- lib/checks/keyboard/focusable-element.json | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/doc/rule-descriptions.md b/doc/rule-descriptions.md index b5fa1a1b37..88757d9ebe 100644 --- a/doc/rule-descriptions.md +++ b/doc/rule-descriptions.md @@ -63,7 +63,7 @@ | [no-autoplay-audio](https://dequeuniversity.com/rules/axe/4.6/no-autoplay-audio?application=RuleDescription) | Ensures <video> or <audio> elements do not autoplay audio for more than 3 seconds without a control mechanism to stop or mute the audio | Moderate | cat.time-and-media, wcag2a, wcag142, ACT | needs review | [80f0bf](https://act-rules.github.io/rules/80f0bf) | | [object-alt](https://dequeuniversity.com/rules/axe/4.6/object-alt?application=RuleDescription) | Ensures <object> elements have alternate text | Serious | cat.text-alternatives, wcag2a, wcag111, section508, section508.22.a | failure, needs review | [8fc3b6](https://act-rules.github.io/rules/8fc3b6) | | [role-img-alt](https://dequeuniversity.com/rules/axe/4.6/role-img-alt?application=RuleDescription) | Ensures [role='img'] elements have alternate text | Serious | cat.text-alternatives, wcag2a, wcag111, section508, section508.22.a, ACT | failure, needs review | [23a2a8](https://act-rules.github.io/rules/23a2a8) | -| [scrollable-region-focusable](https://dequeuniversity.com/rules/axe/4.6/scrollable-region-focusable?application=RuleDescription) | Ensure elements that have scrollable content are accessible by keyboard | Moderate | cat.keyboard, wcag2a, wcag211 | failure | [0ssw9k](https://act-rules.github.io/rules/0ssw9k) | +| [scrollable-region-focusable](https://dequeuniversity.com/rules/axe/4.6/scrollable-region-focusable?application=RuleDescription) | Ensure elements that have scrollable content are accessible by keyboard | Serious | cat.keyboard, wcag2a, wcag211 | failure | [0ssw9k](https://act-rules.github.io/rules/0ssw9k) | | [select-name](https://dequeuniversity.com/rules/axe/4.6/select-name?application=RuleDescription) | Ensures select element has an accessible name | Minor, Critical | cat.forms, wcag2a, wcag412, section508, section508.22.n, ACT | failure, needs review | [e086e5](https://act-rules.github.io/rules/e086e5) | | [server-side-image-map](https://dequeuniversity.com/rules/axe/4.6/server-side-image-map?application=RuleDescription) | Ensures that server-side image maps are not used | Minor | cat.text-alternatives, wcag2a, wcag211, section508, section508.22.f | needs review | | | [svg-img-alt](https://dequeuniversity.com/rules/axe/4.6/svg-img-alt?application=RuleDescription) | Ensures <svg> elements with an img, graphics-document or graphics-symbol role have an accessible text | Serious | cat.text-alternatives, wcag2a, wcag111, section508, section508.22.a, ACT | failure, needs review | [7d6734](https://act-rules.github.io/rules/7d6734) | diff --git a/lib/checks/keyboard/focusable-content.json b/lib/checks/keyboard/focusable-content.json index 9a91fff842..11db612fb3 100644 --- a/lib/checks/keyboard/focusable-content.json +++ b/lib/checks/keyboard/focusable-content.json @@ -2,7 +2,7 @@ "id": "focusable-content", "evaluate": "focusable-content-evaluate", "metadata": { - "impact": "moderate", + "impact": "serious", "messages": { "pass": "Element contains focusable elements", "fail": "Element should have focusable content" diff --git a/lib/checks/keyboard/focusable-element.json b/lib/checks/keyboard/focusable-element.json index 9045e78f92..da108b768d 100644 --- a/lib/checks/keyboard/focusable-element.json +++ b/lib/checks/keyboard/focusable-element.json @@ -2,7 +2,7 @@ "id": "focusable-element", "evaluate": "focusable-element-evaluate", "metadata": { - "impact": "moderate", + "impact": "serious", "messages": { "pass": "Element is focusable", "fail": "Element should be focusable" From 2842395f9a8990f670e7025749ff8301b68a15ae Mon Sep 17 00:00:00 2001 From: Steven Lambert <2433219+straker@users.noreply.github.com> Date: Fri, 24 Mar 2023 08:47:35 -0600 Subject: [PATCH 2/7] fix(aria-allowed-attrs): allow aria-description and aria-braille* attrs (#3956) * fix(aria-allowed-attrs): allow aria-description and aria-braille* attrs * fix test --- lib/standards/aria-attrs.js | 13 ++ .../standards/get-global-aria-attrs.js | 3 + .../rules/aria-allowed-attr/passes.html | 201 ++++++++++++++++++ 3 files changed, 217 insertions(+) diff --git a/lib/standards/aria-attrs.js b/lib/standards/aria-attrs.js index 85bf547e74..1143ca1fc7 100644 --- a/lib/standards/aria-attrs.js +++ b/lib/standards/aria-attrs.js @@ -12,6 +12,14 @@ const ariaAttrs = { type: 'nmtoken', values: ['inline', 'list', 'both', 'none'] }, + 'aria-braillelabel': { + type: 'string', + global: true + }, + 'aria-brailleroledescription': { + type: 'string', + global: true + }, 'aria-busy': { type: 'boolean', global: true @@ -48,6 +56,11 @@ const ariaAttrs = { allowEmpty: true, global: true }, + 'aria-description': { + type: 'string', + allowEmpty: true, + global: true + }, 'aria-details': { type: 'idref', allowEmpty: true, diff --git a/test/commons/standards/get-global-aria-attrs.js b/test/commons/standards/get-global-aria-attrs.js index a1bbf28408..0141f255a3 100644 --- a/test/commons/standards/get-global-aria-attrs.js +++ b/test/commons/standards/get-global-aria-attrs.js @@ -14,10 +14,13 @@ describe('standards.getGlobalAriaAttrs', function () { var globalAttrs = getGlobalAriaAttrs(); assert.deepEqual(globalAttrs, [ 'aria-atomic', + 'aria-braillelabel', + 'aria-brailleroledescription', 'aria-busy', 'aria-controls', 'aria-current', 'aria-describedby', + 'aria-description', 'aria-details', 'aria-disabled', 'aria-dropeffect', diff --git a/test/integration/rules/aria-allowed-attr/passes.html b/test/integration/rules/aria-allowed-attr/passes.html index fe562556bc..9bee42b07c 100644 --- a/test/integration/rules/aria-allowed-attr/passes.html +++ b/test/integration/rules/aria-allowed-attr/passes.html @@ -7,9 +7,12 @@ id="pass1" aria-expanded="value" aria-atomic="value" + aria-braillelabel="value" + aria-brailleroledescription="value" aria-busy="value" aria-controls="value" aria-describedby="value" + aria-description="value" aria-details="value" aria-disabled="value" aria-dropeffect="value" @@ -33,9 +36,12 @@ id="pass2" aria-expanded="value" aria-atomic="value" + aria-braillelabel="value" + aria-brailleroledescription="value" aria-busy="value" aria-controls="value" aria-describedby="value" + aria-description="value" aria-details="value" aria-disabled="value" aria-dropeffect="value" @@ -61,9 +67,12 @@ aria-activedescendant="value" aria-expanded="value" aria-atomic="value" + aria-braillelabel="value" + aria-brailleroledescription="value" aria-busy="value" aria-controls="value" aria-describedby="value" + aria-description="value" aria-details="value" aria-disabled="value" aria-dropeffect="value" @@ -89,9 +98,12 @@ aria-posinset="value" aria-setsize="value" aria-atomic="value" + aria-braillelabel="value" + aria-brailleroledescription="value" aria-busy="value" aria-controls="value" aria-describedby="value" + aria-description="value" aria-details="value" aria-disabled="value" aria-dropeffect="value" @@ -115,9 +127,12 @@ id="pass5" aria-expanded="value" aria-atomic="value" + aria-braillelabel="value" + aria-brailleroledescription="value" aria-busy="value" aria-controls="value" aria-describedby="value" + aria-description="value" aria-details="value" aria-disabled="value" aria-dropeffect="value" @@ -142,9 +157,12 @@ aria-expanded="value" aria-pressed="value" aria-atomic="value" + aria-braillelabel="value" + aria-brailleroledescription="value" aria-busy="value" aria-controls="value" aria-describedby="value" + aria-description="value" aria-details="value" aria-disabled="value" aria-dropeffect="value" @@ -168,9 +186,12 @@ id="pass7" aria-checked="value" aria-atomic="value" + aria-braillelabel="value" + aria-brailleroledescription="value" aria-busy="value" aria-controls="value" aria-describedby="value" + aria-description="value" aria-details="value" aria-disabled="value" aria-dropeffect="value" @@ -203,9 +224,12 @@ aria-selected="value" aria-required="value" aria-atomic="value" + aria-braillelabel="value" + aria-brailleroledescription="value" aria-busy="value" aria-controls="value" aria-describedby="value" + aria-description="value" aria-details="value" aria-disabled="value" aria-dropeffect="value" @@ -233,9 +257,12 @@ aria-expanded="value" aria-orientation="value" aria-atomic="value" + aria-braillelabel="value" + aria-brailleroledescription="value" aria-busy="value" aria-controls="value" aria-describedby="value" + aria-description="value" aria-details="value" aria-disabled="value" aria-dropeffect="value" @@ -259,9 +286,12 @@ id="pass10" aria-expanded="value" aria-atomic="value" + aria-braillelabel="value" + aria-brailleroledescription="value" aria-busy="value" aria-controls="value" aria-describedby="value" + aria-description="value" aria-details="value" aria-disabled="value" aria-dropeffect="value" @@ -285,9 +315,12 @@ id="pass11" aria-expanded="value" aria-atomic="value" + aria-braillelabel="value" + aria-brailleroledescription="value" aria-busy="value" aria-controls="value" aria-describedby="value" + aria-description="value" aria-details="value" aria-disabled="value" aria-dropeffect="value" @@ -311,9 +344,12 @@ id="pass12" aria-expanded="value" aria-atomic="value" + aria-braillelabel="value" + aria-brailleroledescription="value" aria-busy="value" aria-controls="value" aria-describedby="value" + aria-description="value" aria-details="value" aria-disabled="value" aria-dropeffect="value" @@ -337,9 +373,12 @@ id="pass13" aria-expanded="value" aria-atomic="value" + aria-braillelabel="value" + aria-brailleroledescription="value" aria-busy="value" aria-controls="value" aria-describedby="value" + aria-description="value" aria-details="value" aria-disabled="value" aria-dropeffect="value" @@ -364,9 +403,12 @@ id="pass14" aria-expanded="value" aria-atomic="value" + aria-braillelabel="value" + aria-brailleroledescription="value" aria-busy="value" aria-controls="value" aria-describedby="value" + aria-description="value" aria-details="value" aria-disabled="value" aria-dropeffect="value" @@ -390,9 +432,12 @@ id="pass15" aria-expanded="value" aria-atomic="value" + aria-braillelabel="value" + aria-brailleroledescription="value" aria-busy="value" aria-controls="value" aria-describedby="value" + aria-description="value" aria-details="value" aria-disabled="value" aria-dropeffect="value" @@ -416,9 +461,12 @@ id="pass16" aria-expanded="value" aria-atomic="value" + aria-braillelabel="value" + aria-brailleroledescription="value" aria-busy="value" aria-controls="value" aria-describedby="value" + aria-description="value" aria-details="value" aria-disabled="value" aria-dropeffect="value" @@ -442,9 +490,12 @@ id="pass17" aria-expanded="value" aria-atomic="value" + aria-braillelabel="value" + aria-brailleroledescription="value" aria-busy="value" aria-controls="value" aria-describedby="value" + aria-description="value" aria-details="value" aria-disabled="value" aria-dropeffect="value" @@ -472,9 +523,12 @@ aria-activedescendant="value" aria-expanded="value" aria-atomic="value" + aria-braillelabel="value" + aria-brailleroledescription="value" aria-busy="value" aria-controls="value" aria-describedby="value" + aria-description="value" aria-details="value" aria-disabled="value" aria-dropeffect="value" @@ -507,9 +561,12 @@ aria-expanded="value" aria-required="value" aria-atomic="value" + aria-braillelabel="value" + aria-brailleroledescription="value" aria-busy="value" aria-controls="value" aria-describedby="value" + aria-description="value" aria-details="value" aria-disabled="value" aria-dropeffect="value" @@ -534,9 +591,12 @@ aria-activedescendant="value" aria-expanded="value" aria-atomic="value" + aria-braillelabel="value" + aria-brailleroledescription="value" aria-busy="value" aria-controls="value" aria-describedby="value" + aria-description="value" aria-details="value" aria-disabled="value" aria-dropeffect="value" @@ -560,9 +620,12 @@ id="pass21" aria-expanded="value" aria-atomic="value" + aria-braillelabel="value" + aria-brailleroledescription="value" aria-busy="value" aria-controls="value" aria-describedby="value" + aria-description="value" aria-details="value" aria-disabled="value" aria-dropeffect="value" @@ -586,9 +649,12 @@ id="pass22" aria-expanded="value" aria-atomic="value" + aria-braillelabel="value" + aria-brailleroledescription="value" aria-busy="value" aria-controls="value" aria-describedby="value" + aria-description="value" aria-details="value" aria-disabled="value" aria-dropeffect="value" @@ -612,9 +678,12 @@ id="pass23" aria-expanded="value" aria-atomic="value" + aria-braillelabel="value" + aria-brailleroledescription="value" aria-busy="value" aria-controls="value" aria-describedby="value" + aria-description="value" aria-details="value" aria-disabled="value" aria-dropeffect="value" @@ -638,9 +707,12 @@ id="pass24" aria-expanded="value" aria-atomic="value" + aria-braillelabel="value" + aria-brailleroledescription="value" aria-busy="value" aria-controls="value" aria-describedby="value" + aria-description="value" aria-details="value" aria-disabled="value" aria-dropeffect="value" @@ -668,9 +740,12 @@ aria-expanded="value" aria-orientation="value" aria-atomic="value" + aria-braillelabel="value" + aria-brailleroledescription="value" aria-busy="value" aria-controls="value" aria-describedby="value" + aria-description="value" aria-details="value" aria-disabled="value" aria-dropeffect="value" @@ -698,9 +773,12 @@ aria-setsize="value" aria-expanded="value" aria-atomic="value" + aria-braillelabel="value" + aria-brailleroledescription="value" aria-busy="value" aria-controls="value" aria-describedby="value" + aria-description="value" aria-details="value" aria-disabled="value" aria-dropeffect="value" @@ -724,9 +802,12 @@ id="pass27" aria-expanded="value" aria-atomic="value" + aria-braillelabel="value" + aria-brailleroledescription="value" aria-busy="value" aria-controls="value" aria-describedby="value" + aria-description="value" aria-details="value" aria-disabled="value" aria-dropeffect="value" @@ -750,9 +831,12 @@ id="pass28" aria-expanded="value" aria-atomic="value" + aria-braillelabel="value" + aria-brailleroledescription="value" aria-busy="value" aria-controls="value" aria-describedby="value" + aria-description="value" aria-details="value" aria-disabled="value" aria-dropeffect="value" @@ -776,9 +860,12 @@ id="pass29" aria-expanded="value" aria-atomic="value" + aria-braillelabel="value" + aria-brailleroledescription="value" aria-busy="value" aria-controls="value" aria-describedby="value" + aria-description="value" aria-details="value" aria-disabled="value" aria-dropeffect="value" @@ -802,9 +889,12 @@ id="pass30" aria-expanded="value" aria-atomic="value" + aria-braillelabel="value" + aria-brailleroledescription="value" aria-busy="value" aria-controls="value" aria-describedby="value" + aria-description="value" aria-details="value" aria-disabled="value" aria-dropeffect="value" @@ -830,9 +920,12 @@ aria-expanded="value" aria-orientation="value" aria-atomic="value" + aria-braillelabel="value" + aria-brailleroledescription="value" aria-busy="value" aria-controls="value" aria-describedby="value" + aria-description="value" aria-details="value" aria-disabled="value" aria-dropeffect="value" @@ -858,9 +951,12 @@ aria-expanded="value" aria-orientation="value" aria-atomic="value" + aria-braillelabel="value" + aria-brailleroledescription="value" aria-busy="value" aria-controls="value" aria-describedby="value" + aria-description="value" aria-details="value" aria-disabled="value" aria-dropeffect="value" @@ -886,9 +982,12 @@ aria-expanded="value" aria-setsize="value" aria-atomic="value" + aria-braillelabel="value" + aria-brailleroledescription="value" aria-busy="value" aria-controls="value" aria-describedby="value" + aria-description="value" aria-details="value" aria-disabled="value" aria-dropeffect="value" @@ -914,9 +1013,12 @@ aria-posinset="value" aria-setsize="value" aria-atomic="value" + aria-braillelabel="value" + aria-brailleroledescription="value" aria-busy="value" aria-controls="value" aria-describedby="value" + aria-description="value" aria-details="value" aria-disabled="value" aria-dropeffect="value" @@ -942,9 +1044,12 @@ aria-setsize="value" aria-checked="value" aria-atomic="value" + aria-braillelabel="value" + aria-brailleroledescription="value" aria-busy="value" aria-controls="value" aria-describedby="value" + aria-description="value" aria-details="value" aria-disabled="value" aria-dropeffect="value" @@ -968,9 +1073,12 @@ id="pass36" aria-expanded="value" aria-atomic="value" + aria-braillelabel="value" + aria-brailleroledescription="value" aria-busy="value" aria-controls="value" aria-describedby="value" + aria-description="value" aria-details="value" aria-disabled="value" aria-dropeffect="value" @@ -994,9 +1102,12 @@ id="pass37" aria-expanded="value" aria-atomic="value" + aria-braillelabel="value" + aria-brailleroledescription="value" aria-busy="value" aria-controls="value" aria-describedby="value" + aria-description="value" aria-details="value" aria-disabled="value" aria-dropeffect="value" @@ -1023,9 +1134,12 @@ aria-setsize="value" aria-checked="value" aria-atomic="value" + aria-braillelabel="value" + aria-brailleroledescription="value" aria-busy="value" aria-controls="value" aria-describedby="value" + aria-description="value" aria-details="value" aria-disabled="value" aria-dropeffect="value" @@ -1052,9 +1166,12 @@ aria-valuemax="value" aria-valuemin="value" aria-atomic="value" + aria-braillelabel="value" + aria-brailleroledescription="value" aria-busy="value" aria-controls="value" aria-describedby="value" + aria-description="value" aria-details="value" aria-disabled="value" aria-dropeffect="value" @@ -1081,9 +1198,12 @@ aria-setsize="value" aria-checked="value" aria-atomic="value" + aria-braillelabel="value" + aria-brailleroledescription="value" aria-busy="value" aria-controls="value" aria-describedby="value" + aria-description="value" aria-details="value" aria-disabled="value" aria-dropeffect="value" @@ -1109,9 +1229,12 @@ aria-required="value" aria-expanded="value" aria-atomic="value" + aria-braillelabel="value" + aria-brailleroledescription="value" aria-busy="value" aria-controls="value" aria-describedby="value" + aria-description="value" aria-details="value" aria-disabled="value" aria-dropeffect="value" @@ -1136,9 +1259,12 @@ id="pass42" aria-expanded="value" aria-atomic="value" + aria-braillelabel="value" + aria-brailleroledescription="value" aria-busy="value" aria-controls="value" aria-describedby="value" + aria-description="value" aria-details="value" aria-disabled="value" aria-dropeffect="value" @@ -1167,9 +1293,12 @@ aria-activedescendant="value" aria-expanded="value" aria-atomic="value" + aria-braillelabel="value" + aria-brailleroledescription="value" aria-busy="value" aria-controls="value" aria-describedby="value" + aria-description="value" aria-details="value" aria-disabled="value" aria-dropeffect="value" @@ -1192,9 +1321,12 @@ role="rowgroup" id="pass44" aria-atomic="value" + aria-braillelabel="value" + aria-brailleroledescription="value" aria-busy="value" aria-controls="value" aria-describedby="value" + aria-description="value" aria-details="value" aria-disabled="value" aria-dropeffect="value" @@ -1226,9 +1358,12 @@ aria-expanded="value" aria-selected="value" aria-atomic="value" + aria-braillelabel="value" + aria-brailleroledescription="value" aria-busy="value" aria-controls="value" aria-describedby="value" + aria-description="value" aria-details="value" aria-disabled="value" aria-dropeffect="value" @@ -1257,8 +1392,11 @@ aria-valuemax="value" aria-valuemin="value" aria-atomic="value" + aria-braillelabel="value" + aria-brailleroledescription="value" aria-busy="value" aria-describedby="value" + aria-description="value" aria-details="value" aria-disabled="value" aria-dropeffect="value" @@ -1282,9 +1420,12 @@ id="pass47" aria-expanded="value" aria-atomic="value" + aria-braillelabel="value" + aria-brailleroledescription="value" aria-busy="value" aria-controls="value" aria-describedby="value" + aria-description="value" aria-details="value" aria-disabled="value" aria-dropeffect="value" @@ -1308,9 +1449,12 @@ id="pass48" aria-orientation="value" aria-atomic="value" + aria-braillelabel="value" + aria-brailleroledescription="value" aria-busy="value" aria-controls="value" aria-describedby="value" + aria-description="value" aria-details="value" aria-disabled="value" aria-dropeffect="value" @@ -1342,9 +1486,12 @@ aria-valuemax="value" aria-valuemin="value" aria-atomic="value" + aria-braillelabel="value" + aria-brailleroledescription="value" aria-busy="value" aria-controls="value" aria-describedby="value" + aria-description="value" aria-details="value" aria-disabled="value" aria-dropeffect="value" @@ -1373,9 +1520,12 @@ aria-valuemax="value" aria-valuemin="value" aria-atomic="value" + aria-braillelabel="value" + aria-brailleroledescription="value" aria-busy="value" aria-controls="value" aria-describedby="value" + aria-description="value" aria-details="value" aria-disabled="value" aria-dropeffect="value" @@ -1400,9 +1550,12 @@ id="pass51" aria-expanded="value" aria-atomic="value" + aria-braillelabel="value" + aria-brailleroledescription="value" aria-busy="value" aria-controls="value" aria-describedby="value" + aria-description="value" aria-details="value" aria-disabled="value" aria-dropeffect="value" @@ -1429,9 +1582,12 @@ aria-posinset="value" aria-setsize="value" aria-atomic="value" + aria-braillelabel="value" + aria-brailleroledescription="value" aria-busy="value" aria-controls="value" aria-describedby="value" + aria-description="value" aria-details="value" aria-disabled="value" aria-dropeffect="value" @@ -1459,9 +1615,12 @@ aria-multiselectable="value" aria-orientation="value" aria-atomic="value" + aria-braillelabel="value" + aria-brailleroledescription="value" aria-busy="value" aria-controls="value" aria-describedby="value" + aria-description="value" aria-details="value" aria-disabled="value" aria-dropeffect="value" @@ -1485,9 +1644,12 @@ id="pass54" aria-expanded="value" aria-atomic="value" + aria-braillelabel="value" + aria-brailleroledescription="value" aria-busy="value" aria-controls="value" aria-describedby="value" + aria-description="value" aria-details="value" aria-disabled="value" aria-dropeffect="value" @@ -1515,9 +1677,12 @@ aria-readonly="value" aria-required="value" aria-atomic="value" + aria-braillelabel="value" + aria-brailleroledescription="value" aria-busy="value" aria-controls="value" aria-describedby="value" + aria-description="value" aria-details="value" aria-disabled="value" aria-dropeffect="value" @@ -1542,9 +1707,12 @@ id="pass56" aria-expanded="value" aria-atomic="value" + aria-braillelabel="value" + aria-brailleroledescription="value" aria-busy="value" aria-controls="value" aria-describedby="value" + aria-description="value" aria-details="value" aria-disabled="value" aria-dropeffect="value" @@ -1569,9 +1737,12 @@ aria-activedescendant="value" aria-expanded="value" aria-atomic="value" + aria-braillelabel="value" + aria-brailleroledescription="value" aria-busy="value" aria-controls="value" aria-describedby="value" + aria-description="value" aria-details="value" aria-disabled="value" aria-dropeffect="value" @@ -1596,9 +1767,12 @@ id="pass58" aria-expanded="value" aria-atomic="value" + aria-braillelabel="value" + aria-brailleroledescription="value" aria-busy="value" aria-controls="value" aria-describedby="value" + aria-description="value" aria-details="value" aria-disabled="value" aria-dropeffect="value" @@ -1626,9 +1800,12 @@ aria-expanded="value" aria-orientation="value" aria-atomic="value" + aria-braillelabel="value" + aria-brailleroledescription="value" aria-busy="value" aria-controls="value" aria-describedby="value" + aria-description="value" aria-details="value" aria-disabled="value" aria-dropeffect="value" @@ -1660,9 +1837,12 @@ aria-required="value" aria-rowcount="value" aria-atomic="value" + aria-braillelabel="value" + aria-brailleroledescription="value" aria-busy="value" aria-controls="value" aria-describedby="value" + aria-description="value" aria-details="value" aria-disabled="value" aria-dropeffect="value" @@ -1691,9 +1871,12 @@ aria-posinset="value" aria-setsize="value" aria-atomic="value" + aria-braillelabel="value" + aria-brailleroledescription="value" aria-busy="value" aria-controls="value" aria-describedby="value" + aria-description="value" aria-details="value" aria-disabled="value" aria-dropeffect="value" @@ -1717,9 +1900,12 @@ id="pass62" aria-checked="value" aria-atomic="value" + aria-braillelabel="value" + aria-brailleroledescription="value" aria-busy="value" aria-controls="value" aria-describedby="value" + aria-description="value" aria-details="value" aria-disabled="value" aria-dropeffect="value" @@ -1746,9 +1932,12 @@ aria-rowindex="value" aria-rowspan="value" aria-atomic="value" + aria-braillelabel="value" + aria-brailleroledescription="value" aria-busy="value" aria-controls="value" aria-describedby="value" + aria-description="value" aria-details="value" aria-disabled="value" aria-dropeffect="value" @@ -1776,9 +1965,12 @@ aria-readonly="value" aria-required="value" aria-atomic="value" + aria-braillelabel="value" + aria-brailleroledescription="value" aria-busy="value" aria-controls="value" aria-describedby="value" + aria-description="value" aria-details="value" aria-disabled="value" aria-dropeffect="value" @@ -1803,9 +1995,12 @@ id="pass65" aria-expanded="value" aria-atomic="value" + aria-braillelabel="value" + aria-brailleroledescription="value" aria-busy="value" aria-controls="value" aria-describedby="value" + aria-description="value" aria-details="value" aria-disabled="value" aria-dropeffect="value" @@ -1828,9 +2023,12 @@ role="text" id="pass66" aria-atomic="value" + aria-braillelabel="value" + aria-brailleroledescription="value" aria-busy="value" aria-controls="value" aria-describedby="value" + aria-description="value" aria-details="value" aria-disabled="value" aria-dropeffect="value" @@ -1855,9 +2053,12 @@ aria-colcount="value" aria-rowcount="value" aria-atomic="value" + aria-braillelabel="value" + aria-brailleroledescription="value" aria-busy="value" aria-controls="value" aria-describedby="value" + aria-description="value" aria-details="value" aria-disabled="value" aria-dropeffect="value" From cce75869be032006dc505a2af853886943973319 Mon Sep 17 00:00:00 2001 From: Steven Lambert <2433219+straker@users.noreply.github.com> Date: Fri, 24 Mar 2023 08:47:48 -0600 Subject: [PATCH 3/7] fix(aria-required-children): list elements that are not allowed (#3951) * fix(aria-required-children): list elements that are not allowed * jsdoc * fix tests * remove dups --- .../aria/aria-required-children-evaluate.js | 145 ++++++++++++------ lib/checks/aria/aria-required-children.json | 2 +- locales/_template.json | 2 +- test/checks/aria/required-children.js | 35 ++++- 4 files changed, 129 insertions(+), 55 deletions(-) diff --git a/lib/checks/aria/aria-required-children-evaluate.js b/lib/checks/aria/aria-required-children-evaluate.js index 205ef1c970..940c824b62 100644 --- a/lib/checks/aria/aria-required-children-evaluate.js +++ b/lib/checks/aria/aria-required-children-evaluate.js @@ -12,6 +12,71 @@ import { isVisibleToScreenReaders } from '../../commons/dom'; +/** + * Check that an element owns all required children for its explicit role. + * + * Required roles are taken from the `ariaRoles` standards object from the roles `requiredOwned` property. + * + * @memberof checks + * @param {Boolean} options.reviewEmpty List of ARIA roles that should be flagged as "Needs Review" rather than a violation if the element has no owned children. + * @data {String[]} List of all missing owned roles. + * @returns {Mixed} True if the element owns all required roles. Undefined if `options.reviewEmpty=true` and the element has no owned children. False otherwise. + */ +export default function ariaRequiredChildrenEvaluate( + node, + options, + virtualNode +) { + const reviewEmpty = + options && Array.isArray(options.reviewEmpty) ? options.reviewEmpty : []; + const role = getExplicitRole(virtualNode, { dpub: true }); + const required = requiredOwned(role); + if (required === null) { + return true; + } + + const ownedRoles = getOwnedRoles(virtualNode, required); + const unallowed = ownedRoles.filter(({ role }) => !required.includes(role)); + + if (unallowed.length) { + this.relatedNodes(unallowed.map(({ ownedElement }) => ownedElement)); + this.data({ + messageKey: 'unallowed', + values: unallowed + .map(({ ownedElement, attr }) => + getUnallowedSelector(ownedElement, attr) + ) + .filter((selector, index, array) => array.indexOf(selector) === index) + .join(', ') + }); + return false; + } + + const missing = missingRequiredChildren( + virtualNode, + role, + required, + ownedRoles + ); + if (!missing) { + return true; + } + + this.data(missing); + + // Only review empty nodes when a node is both empty and does not have an aria-owns relationship + if ( + reviewEmpty.includes(role) && + !hasContentVirtual(virtualNode, false, true) && + !ownedRoles.length && + (!virtualNode.hasAttr('aria-owns') || !idrefs(node, 'aria-owns').length) + ) { + return undefined; + } + + return false; +} + /** * Get all owned roles of an element */ @@ -26,10 +91,9 @@ function getOwnedRoles(virtualNode, required) { const role = getRole(ownedElement, { noPresentational: true }); - const hasGlobalAria = getGlobalAriaAttrs().some(attr => - ownedElement.hasAttr(attr) - ); - const hasGlobalAriaOrFocusable = hasGlobalAria || isFocusable(ownedElement); + const globalAriaAttr = getGlobalAriaAttr(ownedElement); + const hasGlobalAriaOrFocusable = + !!globalAriaAttr || isFocusable(ownedElement); // if owned node has no role or is presentational, or if role // allows group or rowgroup, we keep parsing the descendant tree. @@ -43,7 +107,11 @@ function getOwnedRoles(virtualNode, required) { ) { ownedElements.push(...ownedElement.children); } else if (role || hasGlobalAriaOrFocusable) { - ownedRoles.push({ role, ownedElement }); + ownedRoles.push({ + role, + attr: globalAriaAttr || 'tabindex', + ownedElement + }); } } @@ -71,58 +139,35 @@ function missingRequiredChildren(virtualNode, role, required, ownedRoles) { } /** - * Check that an element owns all required children for its explicit role. - * - * Required roles are taken from the `ariaRoles` standards object from the roles `requiredOwned` property. - * - * @memberof checks - * @param {Boolean} options.reviewEmpty List of ARIA roles that should be flagged as "Needs Review" rather than a violation if the element has no owned children. - * @data {String[]} List of all missing owned roles. - * @returns {Mixed} True if the element owns all required roles. Undefined if `options.reviewEmpty=true` and the element has no owned children. False otherwise. + * Get the first global ARIA attribute the element has. + * @param {VirtualNode} vNode + * @return {String|null} */ -function ariaRequiredChildrenEvaluate(node, options, virtualNode) { - const reviewEmpty = - options && Array.isArray(options.reviewEmpty) ? options.reviewEmpty : []; - const role = getExplicitRole(virtualNode, { dpub: true }); - const required = requiredOwned(role); - if (required === null) { - return true; - } +function getGlobalAriaAttr(vNode) { + return getGlobalAriaAttrs().find(attr => vNode.hasAttr(attr)); +} - const ownedRoles = getOwnedRoles(virtualNode, required); - const unallowed = ownedRoles.filter(({ role }) => !required.includes(role)); +/** + * Return a simple selector for an unallowed element. + * @param {VirtualNode} vNode + * @param {String} [attr] - Optional attribute which made the element unallowed + * @return {String} + */ +function getUnallowedSelector(vNode, attr) { + const { nodeName, nodeType } = vNode.props; - if (unallowed.length) { - this.relatedNodes(unallowed.map(({ ownedElement }) => ownedElement)); - this.data({ - messageKey: 'unallowed' - }); - return false; + if (nodeType === 3) { + return `#text`; } - const missing = missingRequiredChildren( - virtualNode, - role, - required, - ownedRoles - ); - if (!missing) { - return true; + const role = getExplicitRole(vNode, { dpub: true }); + if (role) { + return `[role=${role}]`; } - this.data(missing); - - // Only review empty nodes when a node is both empty and does not have an aria-owns relationship - if ( - reviewEmpty.includes(role) && - !hasContentVirtual(virtualNode, false, true) && - !ownedRoles.length && - (!virtualNode.hasAttr('aria-owns') || !idrefs(node, 'aria-owns').length) - ) { - return undefined; + if (attr) { + return nodeName + `[${attr}]`; } - return false; + return nodeName; } - -export default ariaRequiredChildrenEvaluate; diff --git a/lib/checks/aria/aria-required-children.json b/lib/checks/aria/aria-required-children.json index 38618dbc19..db1e2bf630 100644 --- a/lib/checks/aria/aria-required-children.json +++ b/lib/checks/aria/aria-required-children.json @@ -24,7 +24,7 @@ "fail": { "singular": "Required ARIA child role not present: ${data.values}", "plural": "Required ARIA children role not present: ${data.values}", - "unallowed": "Element has children which are not allowed (see related nodes)" + "unallowed": "Element has children which are not allowed: ${data.values}" }, "incomplete": { "singular": "Expecting ARIA child role to be added: ${data.values}", diff --git a/locales/_template.json b/locales/_template.json index 7ac37e6d57..e41a1b4514 100644 --- a/locales/_template.json +++ b/locales/_template.json @@ -477,7 +477,7 @@ "fail": { "singular": "Required ARIA child role not present: ${data.values}", "plural": "Required ARIA children role not present: ${data.values}", - "unallowed": "Element has children which are not allowed (see related nodes)" + "unallowed": "Element has children which are not allowed: ${data.values}" }, "incomplete": { "singular": "Expecting ARIA child role to be added: ${data.values}", diff --git a/test/checks/aria/required-children.js b/test/checks/aria/required-children.js index 34c5c312c4..47191efb09 100644 --- a/test/checks/aria/required-children.js +++ b/test/checks/aria/required-children.js @@ -153,7 +153,10 @@ describe('aria-required-children', () => { axe._tree, '[role="tabpanel"]' )[0]; - assert.deepEqual(checkContext._data, { messageKey: 'unallowed' }); + assert.deepEqual(checkContext._data, { + messageKey: 'unallowed', + values: '[role=tabpanel]' + }); assert.deepEqual(checkContext._relatedNodes, [unallowed]); }); @@ -171,7 +174,10 @@ describe('aria-required-children', () => { axe._tree, '[aria-live="polite"]' )[0]; - assert.deepEqual(checkContext._data, { messageKey: 'unallowed' }); + assert.deepEqual(checkContext._data, { + messageKey: 'unallowed', + values: 'div[aria-live]' + }); assert.deepEqual(checkContext._relatedNodes, [unallowed]); }); @@ -189,10 +195,33 @@ describe('aria-required-children', () => { axe._tree, '[tabindex="0"]' )[0]; - assert.deepEqual(checkContext._data, { messageKey: 'unallowed' }); + assert.deepEqual(checkContext._data, { + messageKey: 'unallowed', + values: 'div[tabindex]' + }); assert.deepEqual(checkContext._relatedNodes, [unallowed]); }); + it('should remove duplicate unallowed selectors', () => { + const params = checkSetup(` +