From cd0dbf2550451a3b492dfd99c3b858c725a6214a Mon Sep 17 00:00:00 2001 From: Ali Unwala Date: Mon, 24 Jan 2022 16:20:14 -0600 Subject: [PATCH 01/21] Initial commit for the rule. A couple changes to accessible name computation as well here to include legends and the for attribute in the computation. --- .../src/v2/aria/ARIAMapper.ts | 16 +++- .../v2/checker/accessibility/help/index.ts | 8 ++ .../src/v2/checker/accessibility/nls/index.ts | 9 +++ .../rules/rpt-ariaLabeling-rules.ts | 74 +++++++++++++++++-- .../checker/accessibility/rulesets/index.ts | 15 ++++ .../test_mixed_1.html | 67 +++++++++++++++++ 6 files changed, 180 insertions(+), 9 deletions(-) create mode 100644 accessibility-checker-engine/test/v2/checker/accessibility/rules/group_withInputs_hasName_ruleunit/test_mixed_1.html diff --git a/accessibility-checker-engine/src/v2/aria/ARIAMapper.ts b/accessibility-checker-engine/src/v2/aria/ARIAMapper.ts index a3a3741c3..37b69e7a9 100644 --- a/accessibility-checker-engine/src/v2/aria/ARIAMapper.ts +++ b/accessibility-checker-engine/src/v2/aria/ARIAMapper.ts @@ -409,9 +409,23 @@ export class ARIAMapper extends CommonMapper { if (cur.nodeName.toLowerCase() === "input" && elem.hasAttribute("id") && elem.getAttribute("id").length > 0) { let label = elem.ownerDocument.querySelector("label[for='"+elem.getAttribute("id")+"']"); if (label) { - return this.computeNameHelp(walkId, label, false, false); + if (label.hasAttribute("aria-label") || label.hasAttribute("aria-labelledby")) { + return this.computeNameHelp(walkId, label, false, false); + } else { + return label.textContent; + } + } + } + if (cur.nodeName.toLowerCase() === "fieldset") { + if( (cur).querySelector("legend")){ + let legend = (cur).querySelector("legend"); + return legend.innerText; + }else{ + return this.computeNameHelp(walkId, cur, false, false); } + } + } // 2e. diff --git a/accessibility-checker-engine/src/v2/checker/accessibility/help/index.ts b/accessibility-checker-engine/src/v2/checker/accessibility/help/index.ts index 97f31b5c2..fc072f519 100644 --- a/accessibility-checker-engine/src/v2/checker/accessibility/help/index.ts +++ b/accessibility-checker-engine/src/v2/checker/accessibility/help/index.ts @@ -862,6 +862,14 @@ let a11yHelp = { "Pass_0": `${Config.helpRoot}/Rpt_Aria_ArticleRoleLabel_Implicit`, "Fail_1": `${Config.helpRoot}/Rpt_Aria_ArticleRoleLabel_Implicit` }, + // ALI - TODO + "group_withInputs_hasName": { + 0: `${Config.helpRoot}/group_withInputs_hasName`, + "Pass_0": `${Config.helpRoot}/group_withInputs_hasName`, + "Pass_1": `${Config.helpRoot}/group_withInputs_hasName`, + "Fail_0": `${Config.helpRoot}/group_withInputs_hasName`, + "Fail_1": `${Config.helpRoot}/group_withInputs_hasName` + }, // JCH - DONE "Rpt_Aria_MultipleGroupRoles_Implicit": { 0: `${Config.helpRoot}/Rpt_Aria_MultipleGroupRoles_Implicit`, diff --git a/accessibility-checker-engine/src/v2/checker/accessibility/nls/index.ts b/accessibility-checker-engine/src/v2/checker/accessibility/nls/index.ts index 4b160e1b0..e1c82721a 100644 --- a/accessibility-checker-engine/src/v2/checker/accessibility/nls/index.ts +++ b/accessibility-checker-engine/src/v2/checker/accessibility/nls/index.ts @@ -855,6 +855,15 @@ let a11yNls = { "Pass_0": "Rule Passed", "Fail_1": "The element with \"article\" role does not have a label" }, + + // ALI - TODO + "group_withInputs_hasName": { + 0: "All groups with nested inputs must have aria-label or aria-labelledby", + "Pass_0": "Input group with name {0} passes", + "Pass_1": "Fieldset with Legend {0} passes", + "Fail_0": "Group does not have an accessible name", + "Fail_1": "Fieldset does not have a legend" + }, // JCH - DONE "Rpt_Aria_MultipleGroupRoles_Implicit": { 0: "Each element with \"group\" role must have a unique label that describes its purpose", diff --git a/accessibility-checker-engine/src/v2/checker/accessibility/rules/rpt-ariaLabeling-rules.ts b/accessibility-checker-engine/src/v2/checker/accessibility/rules/rpt-ariaLabeling-rules.ts index 29049bfac..53f66e2d4 100644 --- a/accessibility-checker-engine/src/v2/checker/accessibility/rules/rpt-ariaLabeling-rules.ts +++ b/accessibility-checker-engine/src/v2/checker/accessibility/rules/rpt-ariaLabeling-rules.ts @@ -96,7 +96,7 @@ let a11yRulesLabeling: Rule[] = [ // We do not want to compare against ourselfs continue } - + // This if statement focus on the case where the parent landmark is null if ((navigationNodesParents[i] === null) && (navigationNodesParents[j] === null)) { // We are looking at two root nodes, so we should compare them. @@ -105,9 +105,9 @@ let a11yRulesLabeling: Rule[] = [ if ((navigationNodesComputedLabels[i] === navigationNodesComputedLabels[j])) { // both have the same (computed) aria-label/aria-labelledby // if (navigationNodesComputedLabels[i] === "") { - navigationNodesMatchFound.push("Fail_0"); // Fail 0 - matchFound = true - break + navigationNodesMatchFound.push("Fail_0"); // Fail 0 + matchFound = true + break // } } else { // Same parents && same node roles BUT different computed aria-label/aria-labelledby @@ -117,7 +117,7 @@ let a11yRulesLabeling: Rule[] = [ } else { // Same parents but different node roles // Not applicable } - }else if ((navigationNodesParents[i] === null) || (navigationNodesParents[j] === null)) { + } else if ((navigationNodesParents[i] === null) || (navigationNodesParents[j] === null)) { // We are looking at a single root node continue } @@ -130,9 +130,9 @@ let a11yRulesLabeling: Rule[] = [ if ((navigationNodesComputedLabels[i] === navigationNodesComputedLabels[j])) { // both have the same (computed) aria-label/aria-labelledby // if (navigationNodesComputedLabels[i] === "") { - navigationNodesMatchFound.push("Fail_0"); // Fail 0 - matchFound = true - break + navigationNodesMatchFound.push("Fail_0"); // Fail 0 + matchFound = true + break // } } else { // Same parents && same node roles BUT different computed aria-label/aria-labelledby @@ -834,6 +834,64 @@ let a11yRulesLabeling: Rule[] = [ } }, + { + /** + * Description: Triggers if multiple group roles are present and they don't have unique labels + * Also, consider
element which has implicit 'group' role + * Origin: CI162 Web checklist checkpoint 2.4a + */ + id: "group_withInputs_hasName", + context: "aria:group", + run: (context: RuleContext, options?: {}): RuleResult | RuleResult[] => { + const ruleContext = context["dom"].node as Element; + // console.log(ruleContext.tagName) + + if (ruleContext.tagName == "FIELDSET") { + if(ruleContext.querySelector("legend")){ + // We have both a fieldset and a legend. + console.log("We have both a fieldset and a legend.") + console.log(ARIAMapper.computeName(ruleContext)) + }else{ + // We have a fieldset withouot a legend. Bad case??? TODO + console.log("We have a fieldset withouot a legend.") + console.log(ARIAMapper.computeName(ruleContext)) + } + } + return RulePass("Pass_0"); + + + // console.log(ruleContext) + // if(ruleContext.querySelector("input")){ + // console.log(ARIAMapper.computeName(ruleContext.querySelector("input"))) + // }else{ + // return + // } + // return RulePass("Pass_0"); + + // // Consider the Check Hidden Content setting that is set by the rules + // // Also, consider Implicit role checking. + // let landmarks = RPTUtil.getElementsByRoleHidden(ruleContext.ownerDocument, "group", true, true); + // if (landmarks.length === 0 || landmarks.length === 1) { + // return null; + // } + + // let dupes = RPTUtil.getCache(ruleContext.ownerDocument, "Rpt_Aria_MultipleGroupRoles_Implicit", null); + // if (!dupes) { + // dupes = RPTUtil.findAriaLabelDupes(landmarks); + // RPTUtil.setCache(ruleContext.ownerDocument, "Rpt_Aria_MultipleGroupRoles_Implicit", dupes); + // } + // let myLabel = RPTUtil.getAriaLabel(ruleContext); + // let passed = myLabel === "" || !(myLabel in dupes) || dupes[myLabel] <= 1; + + // //return new ValidationResult(passed, ruleContext, '', '', [ myLabel ]); + // if (!passed) { + // return RuleFail("Fail_1", [myLabel]); + // } else { + // return RulePass("Pass_0"); + // } + } + }, + { /** * Description: Triggers if multiple group roles are present and they don't have unique labels diff --git a/accessibility-checker-engine/src/v2/checker/accessibility/rulesets/index.ts b/accessibility-checker-engine/src/v2/checker/accessibility/rulesets/index.ts index eb608288e..acca089f3 100644 --- a/accessibility-checker-engine/src/v2/checker/accessibility/rulesets/index.ts +++ b/accessibility-checker-engine/src/v2/checker/accessibility/rulesets/index.ts @@ -756,6 +756,11 @@ let a11yRulesets: Ruleset[] = [ level: eRulePolicy.VIOLATION, toolkitLevel: eToolkitLevel.LEVEL_THREE }, + { + id: "group_withInputs_hasName", + level: eRulePolicy.VIOLATION, + toolkitLevel: eToolkitLevel.LEVEL_THREE + }, { id: "Rpt_Aria_MultipleGroupRoles_Implicit", level: eRulePolicy.VIOLATION, @@ -1945,6 +1950,11 @@ let a11yRulesets: Ruleset[] = [ level: eRulePolicy.VIOLATION, toolkitLevel: eToolkitLevel.LEVEL_THREE }, + { + id: "group_withInputs_hasName", + level: eRulePolicy.VIOLATION, + toolkitLevel: eToolkitLevel.LEVEL_THREE + }, { id: "Rpt_Aria_MultipleGroupRoles_Implicit", level: eRulePolicy.VIOLATION, @@ -3080,6 +3090,11 @@ let a11yRulesets: Ruleset[] = [ level: eRulePolicy.VIOLATION, toolkitLevel: eToolkitLevel.LEVEL_THREE }, + { + id: "group_withInputs_hasName", + level: eRulePolicy.VIOLATION, + toolkitLevel: eToolkitLevel.LEVEL_THREE + }, { id: "Rpt_Aria_MultipleGroupRoles_Implicit", level: eRulePolicy.VIOLATION, diff --git a/accessibility-checker-engine/test/v2/checker/accessibility/rules/group_withInputs_hasName_ruleunit/test_mixed_1.html b/accessibility-checker-engine/test/v2/checker/accessibility/rules/group_withInputs_hasName_ruleunit/test_mixed_1.html new file mode 100644 index 000000000..c7d8ac08f --- /dev/null +++ b/accessibility-checker-engine/test/v2/checker/accessibility/rules/group_withInputs_hasName_ruleunit/test_mixed_1.html @@ -0,0 +1,67 @@ + + + + + + + + + +
+
+ Choose your favorite monster +
SOME RANDOM TEXT
+ +
+ + +
+ + + +
+
+ + + + + + + + \ No newline at end of file From 59d42c777168e996f9789e9389d3ee0d9b4af056 Mon Sep 17 00:00:00 2001 From: Ali Unwala Date: Mon, 24 Jan 2022 17:37:03 -0600 Subject: [PATCH 02/21] adding mdx --- .../help/group_withInputs_hasName.mdx | 115 ++++++++++++++++++ 1 file changed, 115 insertions(+) create mode 100644 accessibility-checker-engine/help/group_withInputs_hasName.mdx diff --git a/accessibility-checker-engine/help/group_withInputs_hasName.mdx b/accessibility-checker-engine/help/group_withInputs_hasName.mdx new file mode 100644 index 000000000..b49825a8c --- /dev/null +++ b/accessibility-checker-engine/help/group_withInputs_hasName.mdx @@ -0,0 +1,115 @@ +--- +title: "a_rule_help_template - Accessibility Checker Rule Help" +--- +import "../../../styles/ToolHelp.scss" +import { CodeSnippet, Tag } from "carbon-components-react"; + +
+ + + +### The active message goes here _without tokens_ but with `'backticks for formating code'` and tokens __cannot__ be used in mdx + + + + +
+ + + +This is the passive message that will show up in reports, with `backticks for formating code` but tokens **cannot** be used in mdx + + + + + +
+
+ + + + +### Why is this important? + +PLACEHOLDER TEXT HERE SHOULD BE REPLACED BEFORE MERGE TO MASTER ... such as This example text with `role="combobox"`, an `` with values of `"listbox"`, `"tree"`, `"grid"`, or `"dialog"`. +If the value for the `'aria-haspopup'` attribute does not match the value for the popup element's `'role'` +attribute, people who use assistive technologies may see unexpected behavior and will not know how +to interact with the content. + + +
+ + +### What to do + +* PLACEHOLDER TEXT HERE SHOULD BE REPLACED BEFORE MERGE TO MASTER ... such as Set the value of the `'aria-haspopup'` attribute of the `` element to match the value of the `'role'` attribute of the implemented popup. +* Allowed `` element with `'role'` attribute values of `"listbox"`, `"tree"`, `"grid"`, or `"dialog"`. +* **Or**, and another explanation of what to do. + +Alert: MORE TEXT HERE IF APPROPRIATE. The recommended code example is: + + <label for="tag_combo">Tag</label> + <input type="text" id="tag_combo" + role="combobox" aria-autocomplete="list" + aria-haspopup="listbox" aria-expanded="true" + aria-controls="popup_listbox" aria-activedescendant="selected_option"> + <ul role="listbox" id="popup_listbox"> + <li role="option">Zebra</li> + <li role="option" id="selected_option">Zoom</li> + </ul> + +Note: OPTIONAL NOTE TEXT GOES HERE ... such as Derived from [W3C, Accessible Rich Internet Applications (ARIA) Best Practices latest editor's draft](https://w3c.github.io/aria-practices/#combobox). Copyright © [2018-2021] W3C® (MIT, ERCIM, Keio, Beihang). + +
+ + +### About this requirement + + + +* [IBM 1.3.1 Info and relationships](https://www.ibm.com/able/requirements/requirements/#1_3_1) +* [WCAG technique ARIA11](https://www.w3.org/WAI/WCAG21/Techniques/aria/ARIA11) +* [WCAG technique ARIA13](https://www.w3.org/WAI/WCAG21/Techniques/aria/ARIA13) + +### Who does this affect? + + + +* People using a screen reader, including blind, low vision and neurodivergent people +* People with low vision who use screen magnification +* People with visual impairment using color contrast enhancement +* People with moderately low vision who do not use a contrast-enhancing technology +* People who cannot see color, have limited color vision or have color blindness +* People who personalize their display colors for easier reading +* People using text-based browsers (e.g., Lynx) or audio interfaces +* People who use alternate backgrounds to increase legibility +* People using text only, monochrome or braille displays +* People who rely on keyboard control +* People who are deaf or hard of hearing +* People with physical disabilities +* People with dexterity impairment +* People with dexterity impairment using voice control +* People who physically cannot use a pointing device +* People with tremor or other movement disorders +* People with flash-induced seizures +* Many older adults +* Neurodivergent people +* People who turn off image-loading on their web browsers +* People with reading disabilities +* People with cognitive differences who view interfaces using an adapted layout +* People with cognitive limitations +* People with memory limitations +* People with learning disabilities +* People with attention deficit disorders + + +
+
+ +export default ({ children, _frontmatter }) => ({children}) \ No newline at end of file From 962725b241571828f83b14f167d49c60864b99e1 Mon Sep 17 00:00:00 2001 From: Ali Unwala Date: Mon, 24 Jan 2022 17:44:07 -0600 Subject: [PATCH 03/21] Some updates before passing it for rule help work --- .../src/v2/checker/accessibility/help/index.ts | 5 ++--- .../src/v2/checker/accessibility/nls/index.ts | 9 ++++----- .../group_withInputs_hasName_ruleunit/test_mixed_1.html | 2 +- 3 files changed, 7 insertions(+), 9 deletions(-) diff --git a/accessibility-checker-engine/src/v2/checker/accessibility/help/index.ts b/accessibility-checker-engine/src/v2/checker/accessibility/help/index.ts index fc072f519..1cfc90d42 100644 --- a/accessibility-checker-engine/src/v2/checker/accessibility/help/index.ts +++ b/accessibility-checker-engine/src/v2/checker/accessibility/help/index.ts @@ -865,10 +865,9 @@ let a11yHelp = { // ALI - TODO "group_withInputs_hasName": { 0: `${Config.helpRoot}/group_withInputs_hasName`, - "Pass_0": `${Config.helpRoot}/group_withInputs_hasName`, "Pass_1": `${Config.helpRoot}/group_withInputs_hasName`, - "Fail_0": `${Config.helpRoot}/group_withInputs_hasName`, - "Fail_1": `${Config.helpRoot}/group_withInputs_hasName` + "Fail_1": `${Config.helpRoot}/group_withInputs_hasName`, + "Fail_2": `${Config.helpRoot}/group_withInputs_hasName` }, // JCH - DONE "Rpt_Aria_MultipleGroupRoles_Implicit": { diff --git a/accessibility-checker-engine/src/v2/checker/accessibility/nls/index.ts b/accessibility-checker-engine/src/v2/checker/accessibility/nls/index.ts index e1c82721a..68a5dc471 100644 --- a/accessibility-checker-engine/src/v2/checker/accessibility/nls/index.ts +++ b/accessibility-checker-engine/src/v2/checker/accessibility/nls/index.ts @@ -858,11 +858,10 @@ let a11yNls = { // ALI - TODO "group_withInputs_hasName": { - 0: "All groups with nested inputs must have aria-label or aria-labelledby", - "Pass_0": "Input group with name {0} passes", - "Pass_1": "Fieldset with Legend {0} passes", - "Fail_0": "Group does not have an accessible name", - "Fail_1": "Fieldset does not have a legend" + 0: "Groups with nested inputs must have unique accessible name", + "Pass_1": "Group/Fieldset {0} with an input has a unique name", + "Fail_1": "Group/Fieldset does not have an accessible name", + "Fail_2": "Group/Fieldset {0} has a duplicate name to another group" }, // JCH - DONE "Rpt_Aria_MultipleGroupRoles_Implicit": { diff --git a/accessibility-checker-engine/test/v2/checker/accessibility/rules/group_withInputs_hasName_ruleunit/test_mixed_1.html b/accessibility-checker-engine/test/v2/checker/accessibility/rules/group_withInputs_hasName_ruleunit/test_mixed_1.html index c7d8ac08f..36abd1720 100644 --- a/accessibility-checker-engine/test/v2/checker/accessibility/rules/group_withInputs_hasName_ruleunit/test_mixed_1.html +++ b/accessibility-checker-engine/test/v2/checker/accessibility/rules/group_withInputs_hasName_ruleunit/test_mixed_1.html @@ -55,7 +55,7 @@