From 7f43ca8503f36aa4e4fb7da7dc73b44616a5e11e Mon Sep 17 00:00:00 2001 From: Shunguo Yan Date: Thu, 6 Apr 2023 15:48:39 -0500 Subject: [PATCH 01/24] update the color logic #1202 --- .../src/v2/dom/ColorUtil.ts | 26 ++++++++++--------- .../v4/rules/IBMA_Color_Contrast_WCAG2AA.ts | 8 +++--- 2 files changed, 18 insertions(+), 16 deletions(-) diff --git a/accessibility-checker-engine/src/v2/dom/ColorUtil.ts b/accessibility-checker-engine/src/v2/dom/ColorUtil.ts index a0fbb5189..d067a8675 100644 --- a/accessibility-checker-engine/src/v2/dom/ColorUtil.ts +++ b/accessibility-checker-engine/src/v2/dom/ColorUtil.ts @@ -231,13 +231,13 @@ export class ColorUtil { // start var cStyle = win.getComputedStyle(ruleContext); - var compStyleColor = cStyle.color; + var compStyleColor = cStyle.color; console.log("node=" + ruleContext.nodeName + ", id=" + ruleContext.getAttribute('id')+ ", compStyleColor==" + JSON.stringify(compStyleColor)+ ", backgroundColor=" + JSON.stringify(cStyle.backgroundColor)+ ", backgroundImage=" + JSON.stringify(cStyle.backgroundImage)); if (!compStyleColor) compStyleColor = "black"; var fg = ColorUtil.Color(compStyleColor); var reColor = /transparent|rgba?\([^)]+\)/gi; var guessGradColor = function (gradList, bgColor, fgColor) { - try { + try {console.log("guessGradColor node=" + ruleContext.nodeName + ", id="+ ruleContext.getAttribute('id') + ", gradList=" + JSON.stringify(gradList)+ ", bgColor=" + JSON.stringify(bgColor)+ ", fgColor=" + JSON.stringify(fgColor)); // If there's only one color, return that if (typeof gradList.length === "undefined") return gradList; @@ -245,8 +245,8 @@ export class ColorUtil { var overallWorst = null; var overallWorstRatio = null; for (var iGrad = 1; iGrad < gradList.length; ++iGrad) { - var worstColor = gradList[iGrad - 1]; - var worstRatio = fgColor.contrastRatio(gradList[iGrad - 1]); + var worstColor = gradList[iGrad - 1]; console.log("guessGradColor node=" + ruleContext.nodeName + ", id="+ ruleContext.getAttribute('id') + ", gradList[i]=" + JSON.stringify(gradList[iGrad - 1])+ ", bgColor=" + JSON.stringify(bgColor)+ ", fgColor=" + JSON.stringify(fgColor)); + var worstRatio = fgColor.contrastRatio(gradList[iGrad - 1]); console.log("guessGradColor ratio node=" + ruleContext.nodeName + ", id="+ ruleContext.getAttribute('id') + ", gradList[i]=" + JSON.stringify(gradList[iGrad - 1])+ ", worstRatio=" + JSON.stringify(worstRatio)); var step = .1; var idx = 0; while (step > .0001) { @@ -285,7 +285,7 @@ export class ColorUtil { // cStyle is the computed style of this layer var cStyle = win.getComputedStyle(procNext); if (cStyle === null) continue; - + console.log("node=" + ruleContext.nodeName + ", id=" + ruleContext.getAttribute('id')+ ", color==" + JSON.stringify(cStyle.color)+ ", backgroundColor=" + JSON.stringify(cStyle.backgroundColor)+ ", backgroundImage=" + JSON.stringify(cStyle.backgroundImage)); // thisBgColor is the color of this layer or null if the layer is transparent var thisBgColor = null; if (cStyle.backgroundColor && cStyle.backgroundColor != "transparent" && cStyle.backgroundColor != "rgba(0, 0, 0, 0)") { @@ -297,16 +297,17 @@ export class ColorUtil { if (gradColors) { let gradColorComp : ColorObj[] = []; for (var i = 0; i < gradColors.length; ++i) { - if (!gradColors[i].length) { + let colorComp = ColorUtil.Color(gradColors[i]);console.log("backgroundImage node=" + ruleContext.nodeName + ", id=" + ruleContext.getAttribute('id')+ ", colorComp==" + JSON.stringify(colorComp) + ", alpha==" + colorComp.alpha +", gradColors[i].length" + gradColors[i].length+ ", fg==" + JSON.stringify(fg) + ", thisStackBG==" + JSON.stringify(thisStackBG)+ ", priorStackBG==" + JSON.stringify(priorStackBG)); + if (!gradColors[i].length || (colorComp.alpha !== undefined && colorComp.alpha < 0.1)) { gradColors.splice(i--, 1); } else { - gradColorComp.push(ColorUtil.Color(gradColors[i])); + gradColorComp.push(colorComp); } - } + } console.log("backgroundImage node=" + ruleContext.nodeName + ", id=" + ruleContext.getAttribute('id')+ ", gradColorComp==" + JSON.stringify(gradColorComp)+ ", fg==" + JSON.stringify(fg) + ", thisStackBG==" + JSON.stringify(thisStackBG)+ ", priorStackBG==" + JSON.stringify(priorStackBG)); thisBgColor = guessGradColor(gradColorComp, thisStackBG || priorStackBG, fg); } } - + console.log("bg node =" + ruleContext.nodeName + ", id=" + ruleContext.getAttribute('id')+ ", thisBgColor==" + JSON.stringify(thisBgColor)); // Handle non-solid opacity if (thisStackOpacity === null || (cStyle.opacity && cStyle.opacity.length > 0 && parseFloat(cStyle.opacity) < 1)) { // New stack, reset @@ -413,10 +414,11 @@ export class ColorObj { contrastRatio(bgColor : ColorObj) { let fgColor: ColorObj = this; - + console.log("contrastRatio bgColor1="+JSON.stringify(bgColor) +", fgColor1="+JSON.stringify(fgColor)); if (typeof (this.alpha) != "undefined") fgColor = this.getOverlayColor(bgColor); - + + console.log("contrastRatio bgColor2="+JSON.stringify(bgColor) +", fgColor2="+JSON.stringify(fgColor)); let lum1 = fgColor.relativeLuminance(); if (!bgColor.relativeLuminance) { let s = ""; @@ -460,7 +462,7 @@ export class ColorObj { } }; - getOverlayColor(bgColor : ColorObj) { + getOverlayColor(bgColor : ColorObj) { console.log("getOverlayColor bgColor11="+JSON.stringify(bgColor) + ", fgColor11="+JSON.stringify(this)); if (typeof (this.alpha) === "undefined" || this.alpha >= 1) { // No mixing required - it's opaque return this; diff --git a/accessibility-checker-engine/src/v4/rules/IBMA_Color_Contrast_WCAG2AA.ts b/accessibility-checker-engine/src/v4/rules/IBMA_Color_Contrast_WCAG2AA.ts index 4686e4001..b0fc0bde8 100644 --- a/accessibility-checker-engine/src/v4/rules/IBMA_Color_Contrast_WCAG2AA.ts +++ b/accessibility-checker-engine/src/v4/rules/IBMA_Color_Contrast_WCAG2AA.ts @@ -97,7 +97,7 @@ export let IBMA_Color_Contrast_WCAG2AA: Rule = { } if (elem === null) return; } - + let style = win.getComputedStyle(elem); // JCH clip INFO: @@ -209,9 +209,9 @@ export let IBMA_Color_Contrast_WCAG2AA: Rule = { // Corner case where item is hidden (accessibility hiding technique) return null; } - + console.log("node=" + nodeName + ", id=" + elem.getAttribute('id') + ', text='+childStr.trim()); // First determine the color contrast ratio - let colorCombo = ColorUtil.ColorCombo(elem); + let colorCombo = ColorUtil.ColorCombo(elem); console.log("node=" + nodeName + ", id=" + elem.getAttribute('id') + ', text='+childStr.trim()+", colorCombo="+JSON.stringify(colorCombo)); if (colorCombo === null) { //some exception occurred, or not able to get color combo for some reason console.log("unable to get color combo for element: " + elem.nodeName); @@ -232,7 +232,7 @@ export let IBMA_Color_Contrast_WCAG2AA: Rule = { isDisabled = RPTUtil.isNodeDisabled(control); } } - + console.log("node=" + nodeName + ", id=" + elem.getAttribute('id') + ', fg='+JSON.stringify(fg)+", bg="+JSON.stringify(bg) +", ratio="+ ratio +", weight="+ weight +", size="+ size +", passed="+ passed +", hasBackground="+ hasBackground +", isDisabled="+ isDisabled); if (!isDisabled && nodeName === 'label' && RPTUtil.isDisabledByFirstChildFormElement(elem)) { isDisabled = true; } From 23792e7aa507df2ad8b91278f19931600c5d71b4 Mon Sep 17 00:00:00 2001 From: Shunguo Yan Date: Tue, 11 Apr 2023 11:19:41 -0500 Subject: [PATCH 02/24] add additional message to the color contrast rule #1202 --- .../src/v4/rules/IBMA_Color_Contrast_WCAG2AA.ts | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/accessibility-checker-engine/src/v4/rules/IBMA_Color_Contrast_WCAG2AA.ts b/accessibility-checker-engine/src/v4/rules/IBMA_Color_Contrast_WCAG2AA.ts index b0fc0bde8..b91c43585 100644 --- a/accessibility-checker-engine/src/v4/rules/IBMA_Color_Contrast_WCAG2AA.ts +++ b/accessibility-checker-engine/src/v4/rules/IBMA_Color_Contrast_WCAG2AA.ts @@ -35,7 +35,8 @@ export let IBMA_Color_Contrast_WCAG2AA: Rule = { "group": "The contrast ratio of text with its background must meet WCAG 2.1 AA requirements", "Pass_0": "Rule Passed", "Fail_1": "Text contrast of {0} with its background is less than the WCAG AA minimum requirements for text of size {1}px and weight of {2}", - "Potential_1": "The foreground text and its background color are both detected as {3}. Verify the text meets the WCAG 2.1 AA requirements for minimum contrast" + "Potential_same_color": "The foreground text and its background color are both detected as {3}. Verify the text meets the WCAG 2.1 AA requirements for minimum contrast", + "Potential_graphic_background": "Verify the contrast ratio of the text against the lightest and the darkest colors of the background meets the WCAG 2.1 AA minimum requirements for text of size {1}px and weight of {2}" } }, rulesets: [{ @@ -261,7 +262,7 @@ export let IBMA_Color_Contrast_WCAG2AA: Rule = { //return new ValidationResult(passed, [ruleContext], '', '', [ratio.toFixed(2), size, weight, fg.toHex(), bg.toHex(), colorCombo.hasBGImage, colorCombo.hasGradient]); if (!passed) { if (fg.toHex() === bg.toHex()) { - return RulePotential("Potential_1", [ratio.toFixed(2), size, weight, fg.toHex(), bg.toHex(), colorCombo.hasBGImage, colorCombo.hasGradient]); + return RulePotential("Potential_same_color", [ratio.toFixed(2), size, weight, fg.toHex(), bg.toHex(), colorCombo.hasBGImage, colorCombo.hasGradient]); } else { return RuleFail("Fail_1", [ratio.toFixed(2), size, weight, fg.toHex(), bg.toHex(), colorCombo.hasBGImage, colorCombo.hasGradient]); } From bbb8233a0f6fc5081ce294756f877d3625af1baf Mon Sep 17 00:00:00 2001 From: Shunguo Yan Date: Tue, 11 Apr 2023 13:53:10 -0500 Subject: [PATCH 03/24] merge two color contrast rules and update test cases #1202 --- .../v4/rules/IBMA_Color_Contrast_WCAG2AA.ts | 20 +++++++-------- .../Color-BG.html | 1 + .../Color-inline-BG.html | 1 + .../Color-usingClass-BG.html | 24 ++++++++++++++++++ .../Color-usingInline-BG.html | 22 ++++++++++++++++ .../act_fail_2.html | 21 +++++++++++++++- .../act_fail_3.html | 21 +++++++++++++++- .../act_fail_7.html | 21 +++++++++++++++- .../act_inapplicable_3.html | 2 +- .../act_pass_2.html | 21 +++++++++++++++- .../act_pass_3.html | 25 ++++++++++++++++++- 11 files changed, 163 insertions(+), 16 deletions(-) diff --git a/accessibility-checker-engine/src/v4/rules/IBMA_Color_Contrast_WCAG2AA.ts b/accessibility-checker-engine/src/v4/rules/IBMA_Color_Contrast_WCAG2AA.ts index b91c43585..e081cb406 100644 --- a/accessibility-checker-engine/src/v4/rules/IBMA_Color_Contrast_WCAG2AA.ts +++ b/accessibility-checker-engine/src/v4/rules/IBMA_Color_Contrast_WCAG2AA.ts @@ -250,22 +250,22 @@ export let IBMA_Color_Contrast_WCAG2AA: Rule = { "hasBackground": hasBackground, "isDisabled": isDisabled }); - if (hasBackground) { - // Allow other color rule to fire if we have a background - return null; - } - + // If element or parent is disabled, this rule does not apply (but may be 3:1 in future) if (!passed && isDisabled) { passed = true; } - //return new ValidationResult(passed, [ruleContext], '', '', [ratio.toFixed(2), size, weight, fg.toHex(), bg.toHex(), colorCombo.hasBGImage, colorCombo.hasGradient]); if (!passed) { - if (fg.toHex() === bg.toHex()) { - return RulePotential("Potential_same_color", [ratio.toFixed(2), size, weight, fg.toHex(), bg.toHex(), colorCombo.hasBGImage, colorCombo.hasGradient]); + if (hasBackground) { + // fire potential since a text on an image or gradient can still viewable, depending on the text location on the gradient or image + return RulePotential("Potential_graphic_background", [ratio.toFixed(2), size, weight]);; } else { - return RuleFail("Fail_1", [ratio.toFixed(2), size, weight, fg.toHex(), bg.toHex(), colorCombo.hasBGImage, colorCombo.hasGradient]); - } + if (fg.toHex() === bg.toHex()) { + return RulePotential("Potential_same_color", [ratio.toFixed(2), size, weight, fg.toHex(), bg.toHex(), colorCombo.hasBGImage, colorCombo.hasGradient]); + } else { + return RuleFail("Fail_1", [ratio.toFixed(2), size, weight, fg.toHex(), bg.toHex(), colorCombo.hasBGImage, colorCombo.hasGradient]); + } + } } else { return RulePass("Pass_0", [ratio.toFixed(2), size, weight, fg.toHex(), bg.toHex(), colorCombo.hasBGImage, colorCombo.hasGradient]); } diff --git a/accessibility-checker-engine/test/v2/checker/accessibility/rules/IBMA_Color_Contrast_WCAG2AA_ruleunit/Color-BG.html b/accessibility-checker-engine/test/v2/checker/accessibility/rules/IBMA_Color_Contrast_WCAG2AA_ruleunit/Color-BG.html index 07627a7ef..caae858ff 100644 --- a/accessibility-checker-engine/test/v2/checker/accessibility/rules/IBMA_Color_Contrast_WCAG2AA_ruleunit/Color-BG.html +++ b/accessibility-checker-engine/test/v2/checker/accessibility/rules/IBMA_Color_Contrast_WCAG2AA_ruleunit/Color-BG.html @@ -55,6 +55,7 @@

Color using Class Tests

passedXpaths: [ ], failedXpaths: [ + "/html[1]/body[1]/div[1]" ] } ]; diff --git a/accessibility-checker-engine/test/v2/checker/accessibility/rules/IBMA_Color_Contrast_WCAG2AA_ruleunit/Color-inline-BG.html b/accessibility-checker-engine/test/v2/checker/accessibility/rules/IBMA_Color_Contrast_WCAG2AA_ruleunit/Color-inline-BG.html index 96d09b40c..c31903f6f 100644 --- a/accessibility-checker-engine/test/v2/checker/accessibility/rules/IBMA_Color_Contrast_WCAG2AA_ruleunit/Color-inline-BG.html +++ b/accessibility-checker-engine/test/v2/checker/accessibility/rules/IBMA_Color_Contrast_WCAG2AA_ruleunit/Color-inline-BG.html @@ -48,6 +48,7 @@

Color using inline code Tests

passedXpaths: [ ], failedXpaths: [ + "/html[1]/body[1]/div[1]" ] } ]; diff --git a/accessibility-checker-engine/test/v2/checker/accessibility/rules/IBMA_Color_Contrast_WCAG2AA_ruleunit/Color-usingClass-BG.html b/accessibility-checker-engine/test/v2/checker/accessibility/rules/IBMA_Color_Contrast_WCAG2AA_ruleunit/Color-usingClass-BG.html index cb0c4a0fd..68b9af5ee 100644 --- a/accessibility-checker-engine/test/v2/checker/accessibility/rules/IBMA_Color_Contrast_WCAG2AA_ruleunit/Color-usingClass-BG.html +++ b/accessibility-checker-engine/test/v2/checker/accessibility/rules/IBMA_Color_Contrast_WCAG2AA_ruleunit/Color-usingClass-BG.html @@ -312,6 +312,8 @@

Color using Class Tests

This text is pass - div[52].
This text is pass - div[53].
This text is pass - div[54].
+ +
This text is pass - div[55].
@@ -325,6 +327,28 @@

Color using Class Tests

passedXpaths: [ ], failedXpaths: [ + "/html/body/div[1]", + "/html/body/div[2]", + "/html/body/div[3]", + "/html/body/div[4]", + "/html/body/div[5]", + "/html/body/div[6]", + "/html/body/div[7]", + "/html/body/div[8]", + "/html/body/div[9]", + "/html/body/div[10]", + "/html/body/div[11]", + "/html/body/div[12]", + "/html/body/div[13]", + "/html/body/div[14]", + "/html/body/div[15]", + "/html/body/div[16]", + "/html/body/div[17]", + "/html/body/div[41]", + "/html/body/div[42]", + "/html/body/div[43]", + "/html/body/div[44]", + "/html/body/div[45]" ] } ]; diff --git a/accessibility-checker-engine/test/v2/checker/accessibility/rules/IBMA_Color_Contrast_WCAG2AA_ruleunit/Color-usingInline-BG.html b/accessibility-checker-engine/test/v2/checker/accessibility/rules/IBMA_Color_Contrast_WCAG2AA_ruleunit/Color-usingInline-BG.html index 2ef2ff500..00f5e8a25 100644 --- a/accessibility-checker-engine/test/v2/checker/accessibility/rules/IBMA_Color_Contrast_WCAG2AA_ruleunit/Color-usingInline-BG.html +++ b/accessibility-checker-engine/test/v2/checker/accessibility/rules/IBMA_Color_Contrast_WCAG2AA_ruleunit/Color-usingInline-BG.html @@ -112,6 +112,28 @@

Color using inline code Tests

passedXpaths: [ ], failedXpaths: [ + "/html/body/div[1]", + "/html/body/div[2]", + "/html/body/div[3]", + "/html/body/div[4]", + "/html/body/div[5]", + "/html/body/div[6]", + "/html/body/div[7]", + "/html/body/div[8]", + "/html/body/div[9]", + "/html/body/div[10]", + "/html/body/div[11]", + "/html/body/div[12]", + "/html/body/div[13]", + "/html/body/div[14]", + "/html/body/div[15]", + "/html/body/div[16]", + "/html/body/div[17]", + "/html/body/div[41]", + "/html/body/div[42]", + "/html/body/div[43]", + "/html/body/div[44]", + "/html/body/div[45]" ] } ]; diff --git a/accessibility-checker-engine/test/v2/checker/accessibility/rules/IBMA_Color_Contrast_WCAG2AA_ruleunit/act_fail_2.html b/accessibility-checker-engine/test/v2/checker/accessibility/rules/IBMA_Color_Contrast_WCAG2AA_ruleunit/act_fail_2.html index 2b5f1e12b..0a10d95be 100644 --- a/accessibility-checker-engine/test/v2/checker/accessibility/rules/IBMA_Color_Contrast_WCAG2AA_ruleunit/act_fail_2.html +++ b/accessibility-checker-engine/test/v2/checker/accessibility/rules/IBMA_Color_Contrast_WCAG2AA_ruleunit/act_fail_2.html @@ -15,7 +15,26 @@ UnitTest = { ruleIds: ["IBMA_Color_Contrast_WCAG2AA"], results: [ - + { + "ruleId": "IBMA_Color_Contrast_WCAG2AA", + "value": [ + "INFORMATION", + "POTENTIAL" + ], + "path": { + "dom": "/html[1]/body[1]/p[1]", + "aria": "/document[1]/paragraph[1]" + }, + "reasonId": "Potential_graphic_background", + "message": "Verify the contrast ratio of the text against the lightest and the darkest colors of the background meets the WCAG 2.1 AA minimum requirements for text of size 16px and weight of 400", + "messageArgs": [ + "1.00", + 16, + 400 + ], + "apiArgs": [], + "category": "Accessibility" + } ] } diff --git a/accessibility-checker-engine/test/v2/checker/accessibility/rules/IBMA_Color_Contrast_WCAG2AA_ruleunit/act_fail_3.html b/accessibility-checker-engine/test/v2/checker/accessibility/rules/IBMA_Color_Contrast_WCAG2AA_ruleunit/act_fail_3.html index 5ce948c60..7b80afc59 100644 --- a/accessibility-checker-engine/test/v2/checker/accessibility/rules/IBMA_Color_Contrast_WCAG2AA_ruleunit/act_fail_3.html +++ b/accessibility-checker-engine/test/v2/checker/accessibility/rules/IBMA_Color_Contrast_WCAG2AA_ruleunit/act_fail_3.html @@ -17,7 +17,26 @@ UnitTest = { ruleIds: ["IBMA_Color_Contrast_WCAG2AA"], results: [ - + { + "ruleId": "IBMA_Color_Contrast_WCAG2AA", + "value": [ + "INFORMATION", + "POTENTIAL" + ], + "path": { + "dom": "/html[1]/body[1]/p[1]", + "aria": "/document[1]/paragraph[1]" + }, + "reasonId": "Potential_graphic_background", + "message": "Verify the contrast ratio of the text against the lightest and the darkest colors of the background meets the WCAG 2.1 AA minimum requirements for text of size 16px and weight of 400", + "messageArgs": [ + "2.82", + 16, + 400 + ], + "apiArgs": [], + "category": "Accessibility" + } ] } diff --git a/accessibility-checker-engine/test/v2/checker/accessibility/rules/IBMA_Color_Contrast_WCAG2AA_ruleunit/act_fail_7.html b/accessibility-checker-engine/test/v2/checker/accessibility/rules/IBMA_Color_Contrast_WCAG2AA_ruleunit/act_fail_7.html index f161a019e..8883edab9 100644 --- a/accessibility-checker-engine/test/v2/checker/accessibility/rules/IBMA_Color_Contrast_WCAG2AA_ruleunit/act_fail_7.html +++ b/accessibility-checker-engine/test/v2/checker/accessibility/rules/IBMA_Color_Contrast_WCAG2AA_ruleunit/act_fail_7.html @@ -23,7 +23,26 @@ UnitTest = { ruleIds: ["IBMA_Color_Contrast_WCAG2AA"], results: [ - + { + "ruleId": "IBMA_Color_Contrast_WCAG2AA", + "value": [ + "INFORMATION", + "POTENTIAL" + ], + "path": { + "dom": "/html[1]/body[1]/span[1]", + "aria": "/document[1]" + }, + "reasonId": "Potential_graphic_background", + "message": "Verify the contrast ratio of the text against the lightest and the darkest colors of the background meets the WCAG 2.1 AA minimum requirements for text of size 16px and weight of 400", + "messageArgs": [ + "2.30", + 16, + 400 + ], + "apiArgs": [], + "category": "Accessibility" + } ] } diff --git a/accessibility-checker-engine/test/v2/checker/accessibility/rules/IBMA_Color_Contrast_WCAG2AA_ruleunit/act_inapplicable_3.html b/accessibility-checker-engine/test/v2/checker/accessibility/rules/IBMA_Color_Contrast_WCAG2AA_ruleunit/act_inapplicable_3.html index 736e0adf2..fae8ed810 100644 --- a/accessibility-checker-engine/test/v2/checker/accessibility/rules/IBMA_Color_Contrast_WCAG2AA_ruleunit/act_inapplicable_3.html +++ b/accessibility-checker-engine/test/v2/checker/accessibility/rules/IBMA_Color_Contrast_WCAG2AA_ruleunit/act_inapplicable_3.html @@ -23,7 +23,7 @@ "dom": "/html[1]/body[1]/p[1]", "aria": "/document[1]/paragraph[1]" }, - "reasonId": "Potential_1", + "reasonId": "Potential_same_color", "message": "The foreground text and its background color are both detected as #ffffff. Verify the text meets the WCAG 2.1 AA requirements for minimum contrast", "messageArgs": [ "1.00", diff --git a/accessibility-checker-engine/test/v2/checker/accessibility/rules/IBMA_Color_Contrast_WCAG2AA_ruleunit/act_pass_2.html b/accessibility-checker-engine/test/v2/checker/accessibility/rules/IBMA_Color_Contrast_WCAG2AA_ruleunit/act_pass_2.html index 3c4aad23a..b1e2eaf29 100644 --- a/accessibility-checker-engine/test/v2/checker/accessibility/rules/IBMA_Color_Contrast_WCAG2AA_ruleunit/act_pass_2.html +++ b/accessibility-checker-engine/test/v2/checker/accessibility/rules/IBMA_Color_Contrast_WCAG2AA_ruleunit/act_pass_2.html @@ -15,7 +15,26 @@ UnitTest = { ruleIds: ["IBMA_Color_Contrast_WCAG2AA"], results: [ - + { + "ruleId": "IBMA_Color_Contrast_WCAG2AA", + "value": [ + "INFORMATION", + "POTENTIAL" + ], + "path": { + "dom": "/html[1]/body[1]/p[1]", + "aria": "/document[1]/paragraph[1]" + }, + "reasonId": "Potential_graphic_background", + "message": "Verify the contrast ratio of the text against the lightest and the darkest colors of the background meets the WCAG 2.1 AA minimum requirements for text of size 16px and weight of 400", + "messageArgs": [ + "1.47", + 16, + 400 + ], + "apiArgs": [], + "category": "Accessibility" + } ] } diff --git a/accessibility-checker-engine/test/v2/checker/accessibility/rules/IBMA_Color_Contrast_WCAG2AA_ruleunit/act_pass_3.html b/accessibility-checker-engine/test/v2/checker/accessibility/rules/IBMA_Color_Contrast_WCAG2AA_ruleunit/act_pass_3.html index 1ed6fd8d4..a5f0660b2 100644 --- a/accessibility-checker-engine/test/v2/checker/accessibility/rules/IBMA_Color_Contrast_WCAG2AA_ruleunit/act_pass_3.html +++ b/accessibility-checker-engine/test/v2/checker/accessibility/rules/IBMA_Color_Contrast_WCAG2AA_ruleunit/act_pass_3.html @@ -22,7 +22,30 @@ UnitTest = { ruleIds: ["IBMA_Color_Contrast_WCAG2AA"], results: [ - + { + "ruleId": "IBMA_Color_Contrast_WCAG2AA", + "value": [ + "INFORMATION", + "PASS" + ], + "path": { + "dom": "/html[1]/body[1]/p[1]", + "aria": "/document[1]/paragraph[1]" + }, + "reasonId": "Pass_0", + "message": "Rule Passed", + "messageArgs": [ + "13.08", + 16, + 400, + "#cccccc", + "#000000", + true, + false + ], + "apiArgs": [], + "category": "Accessibility" + } ] } From 3668b74c00c6f724e2b36a4e124c4c05cf971fcf Mon Sep 17 00:00:00 2001 From: Shunguo Yan Date: Wed, 12 Apr 2023 11:42:49 -0500 Subject: [PATCH 04/24] update color contrast rule #1202 --- .../src/v4/rules/IBMA_Color_Contrast_WCAG2AA.ts | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/accessibility-checker-engine/src/v4/rules/IBMA_Color_Contrast_WCAG2AA.ts b/accessibility-checker-engine/src/v4/rules/IBMA_Color_Contrast_WCAG2AA.ts index e081cb406..fba648bef 100644 --- a/accessibility-checker-engine/src/v4/rules/IBMA_Color_Contrast_WCAG2AA.ts +++ b/accessibility-checker-engine/src/v4/rules/IBMA_Color_Contrast_WCAG2AA.ts @@ -27,7 +27,8 @@ export let IBMA_Color_Contrast_WCAG2AA: Rule = { "group": `IBMA_Color_Contrast_WCAG2AA.html`, "Pass_0": `IBMA_Color_Contrast_WCAG2AA.html`, "Fail_1": `IBMA_Color_Contrast_WCAG2AA.html`, - "Potential_1": `IBMA_Color_Contrast_WCAG2AA.html` + "Potential_same_color": `IBMA_Color_Contrast_WCAG2AA.html`, + "Potential_graphic_background": `IBMA_Color_Contrast_WCAG2AA.html` } }, messages: { @@ -210,9 +211,9 @@ export let IBMA_Color_Contrast_WCAG2AA: Rule = { // Corner case where item is hidden (accessibility hiding technique) return null; } - console.log("node=" + nodeName + ", id=" + elem.getAttribute('id') + ', text='+childStr.trim()); + // First determine the color contrast ratio - let colorCombo = ColorUtil.ColorCombo(elem); console.log("node=" + nodeName + ", id=" + elem.getAttribute('id') + ', text='+childStr.trim()+", colorCombo="+JSON.stringify(colorCombo)); + let colorCombo = ColorUtil.ColorCombo(elem); if (colorCombo === null) { //some exception occurred, or not able to get color combo for some reason console.log("unable to get color combo for element: " + elem.nodeName); @@ -233,7 +234,7 @@ export let IBMA_Color_Contrast_WCAG2AA: Rule = { isDisabled = RPTUtil.isNodeDisabled(control); } } - console.log("node=" + nodeName + ", id=" + elem.getAttribute('id') + ', fg='+JSON.stringify(fg)+", bg="+JSON.stringify(bg) +", ratio="+ ratio +", weight="+ weight +", size="+ size +", passed="+ passed +", hasBackground="+ hasBackground +", isDisabled="+ isDisabled); + if (!isDisabled && nodeName === 'label' && RPTUtil.isDisabledByFirstChildFormElement(elem)) { isDisabled = true; } @@ -242,14 +243,14 @@ export let IBMA_Color_Contrast_WCAG2AA: Rule = { isDisabled = true; } - setCache(ruleContext, "EXT_Color_Contrast_WCAG2AA", { + /**setCache(ruleContext, "EXT_Color_Contrast_WCAG2AA", { "ratio": ratio, "isLargeScale": isLargeScale, "weight": weight, "size": size, "hasBackground": hasBackground, "isDisabled": isDisabled - }); + });*/ // If element or parent is disabled, this rule does not apply (but may be 3:1 in future) if (!passed && isDisabled) { From 1abe93920a85ae95115376a8c9cbe97cf7411e30 Mon Sep 17 00:00:00 2001 From: Shunguo Yan Date: Fri, 14 Apr 2023 13:33:03 -0500 Subject: [PATCH 05/24] update color contrast rule to fix graphic background issue #1202 --- .../src/v2/dom/ColorUtil.ts | 30 ++++--- .../v4/rules/IBMA_Color_Contrast_WCAG2AA.ts | 2 +- .../Color-usingClass-BG.html | 4 +- .../Color-usingInline-BG.html | 4 +- .../act_fail_7.html | 2 +- .../color_gradient_transparent.html | 51 ++++++++++++ .../color_gradient_transparent2.html | 51 ++++++++++++ .../color_gradient_transparent3.html | 83 +++++++++++++++++++ 8 files changed, 208 insertions(+), 19 deletions(-) create mode 100644 accessibility-checker-engine/test/v2/checker/accessibility/rules/IBMA_Color_Contrast_WCAG2AA_ruleunit/color_gradient_transparent.html create mode 100644 accessibility-checker-engine/test/v2/checker/accessibility/rules/IBMA_Color_Contrast_WCAG2AA_ruleunit/color_gradient_transparent2.html create mode 100644 accessibility-checker-engine/test/v2/checker/accessibility/rules/IBMA_Color_Contrast_WCAG2AA_ruleunit/color_gradient_transparent3.html diff --git a/accessibility-checker-engine/src/v2/dom/ColorUtil.ts b/accessibility-checker-engine/src/v2/dom/ColorUtil.ts index d067a8675..caac7a8ba 100644 --- a/accessibility-checker-engine/src/v2/dom/ColorUtil.ts +++ b/accessibility-checker-engine/src/v2/dom/ColorUtil.ts @@ -231,13 +231,13 @@ export class ColorUtil { // start var cStyle = win.getComputedStyle(ruleContext); - var compStyleColor = cStyle.color; console.log("node=" + ruleContext.nodeName + ", id=" + ruleContext.getAttribute('id')+ ", compStyleColor==" + JSON.stringify(compStyleColor)+ ", backgroundColor=" + JSON.stringify(cStyle.backgroundColor)+ ", backgroundImage=" + JSON.stringify(cStyle.backgroundImage)); + var compStyleColor = cStyle.color; if (!compStyleColor) compStyleColor = "black"; var fg = ColorUtil.Color(compStyleColor); var reColor = /transparent|rgba?\([^)]+\)/gi; var guessGradColor = function (gradList, bgColor, fgColor) { - try {console.log("guessGradColor node=" + ruleContext.nodeName + ", id="+ ruleContext.getAttribute('id') + ", gradList=" + JSON.stringify(gradList)+ ", bgColor=" + JSON.stringify(bgColor)+ ", fgColor=" + JSON.stringify(fgColor)); + try { // If there's only one color, return that if (typeof gradList.length === "undefined") return gradList; @@ -245,8 +245,8 @@ export class ColorUtil { var overallWorst = null; var overallWorstRatio = null; for (var iGrad = 1; iGrad < gradList.length; ++iGrad) { - var worstColor = gradList[iGrad - 1]; console.log("guessGradColor node=" + ruleContext.nodeName + ", id="+ ruleContext.getAttribute('id') + ", gradList[i]=" + JSON.stringify(gradList[iGrad - 1])+ ", bgColor=" + JSON.stringify(bgColor)+ ", fgColor=" + JSON.stringify(fgColor)); - var worstRatio = fgColor.contrastRatio(gradList[iGrad - 1]); console.log("guessGradColor ratio node=" + ruleContext.nodeName + ", id="+ ruleContext.getAttribute('id') + ", gradList[i]=" + JSON.stringify(gradList[iGrad - 1])+ ", worstRatio=" + JSON.stringify(worstRatio)); + var worstColor = gradList[iGrad - 1]; + var worstRatio = fgColor.contrastRatio(gradList[iGrad - 1]); var step = .1; var idx = 0; while (step > .0001) { @@ -267,7 +267,7 @@ export class ColorUtil { overallWorst = worstColor; } } - return overallWorst; + return overallWorst; // return the darkest color } catch (e) { console.log(e); } @@ -285,7 +285,7 @@ export class ColorUtil { // cStyle is the computed style of this layer var cStyle = win.getComputedStyle(procNext); if (cStyle === null) continue; - console.log("node=" + ruleContext.nodeName + ", id=" + ruleContext.getAttribute('id')+ ", color==" + JSON.stringify(cStyle.color)+ ", backgroundColor=" + JSON.stringify(cStyle.backgroundColor)+ ", backgroundImage=" + JSON.stringify(cStyle.backgroundImage)); + // thisBgColor is the color of this layer or null if the layer is transparent var thisBgColor = null; if (cStyle.backgroundColor && cStyle.backgroundColor != "transparent" && cStyle.backgroundColor != "rgba(0, 0, 0, 0)") { @@ -297,17 +297,22 @@ export class ColorUtil { if (gradColors) { let gradColorComp : ColorObj[] = []; for (var i = 0; i < gradColors.length; ++i) { - let colorComp = ColorUtil.Color(gradColors[i]);console.log("backgroundImage node=" + ruleContext.nodeName + ", id=" + ruleContext.getAttribute('id')+ ", colorComp==" + JSON.stringify(colorComp) + ", alpha==" + colorComp.alpha +", gradColors[i].length" + gradColors[i].length+ ", fg==" + JSON.stringify(fg) + ", thisStackBG==" + JSON.stringify(thisStackBG)+ ", priorStackBG==" + JSON.stringify(priorStackBG)); - if (!gradColors[i].length || (colorComp.alpha !== undefined && colorComp.alpha < 0.1)) { + if (!gradColors[i].length) { gradColors.splice(i--, 1); } else { + let colorComp = ColorUtil.Color(gradColors[i]); + if (colorComp.alpha !== undefined && colorComp.alpha < 1) { + // mix the grdient bg color wit parent bg if alpha < 1 + let compStackBg = thisStackBG || priorStackBG; + colorComp = colorComp.getOverlayColor(compStackBg); + } gradColorComp.push(colorComp); } - } console.log("backgroundImage node=" + ruleContext.nodeName + ", id=" + ruleContext.getAttribute('id')+ ", gradColorComp==" + JSON.stringify(gradColorComp)+ ", fg==" + JSON.stringify(fg) + ", thisStackBG==" + JSON.stringify(thisStackBG)+ ", priorStackBG==" + JSON.stringify(priorStackBG)); + } thisBgColor = guessGradColor(gradColorComp, thisStackBG || priorStackBG, fg); } } - console.log("bg node =" + ruleContext.nodeName + ", id=" + ruleContext.getAttribute('id')+ ", thisBgColor==" + JSON.stringify(thisBgColor)); + // Handle non-solid opacity if (thisStackOpacity === null || (cStyle.opacity && cStyle.opacity.length > 0 && parseFloat(cStyle.opacity) < 1)) { // New stack, reset @@ -414,11 +419,10 @@ export class ColorObj { contrastRatio(bgColor : ColorObj) { let fgColor: ColorObj = this; - console.log("contrastRatio bgColor1="+JSON.stringify(bgColor) +", fgColor1="+JSON.stringify(fgColor)); + if (typeof (this.alpha) != "undefined") fgColor = this.getOverlayColor(bgColor); - console.log("contrastRatio bgColor2="+JSON.stringify(bgColor) +", fgColor2="+JSON.stringify(fgColor)); let lum1 = fgColor.relativeLuminance(); if (!bgColor.relativeLuminance) { let s = ""; @@ -462,7 +466,7 @@ export class ColorObj { } }; - getOverlayColor(bgColor : ColorObj) { console.log("getOverlayColor bgColor11="+JSON.stringify(bgColor) + ", fgColor11="+JSON.stringify(this)); + getOverlayColor(bgColor : ColorObj) { if (typeof (this.alpha) === "undefined" || this.alpha >= 1) { // No mixing required - it's opaque return this; diff --git a/accessibility-checker-engine/src/v4/rules/IBMA_Color_Contrast_WCAG2AA.ts b/accessibility-checker-engine/src/v4/rules/IBMA_Color_Contrast_WCAG2AA.ts index fba648bef..f7480f99d 100644 --- a/accessibility-checker-engine/src/v4/rules/IBMA_Color_Contrast_WCAG2AA.ts +++ b/accessibility-checker-engine/src/v4/rules/IBMA_Color_Contrast_WCAG2AA.ts @@ -16,7 +16,7 @@ import { VisUtil } from "../../v2/dom/VisUtil"; import { ColorUtil } from "../../v2/dom/ColorUtil"; import { Rule, RuleResult, RuleFail, RuleContext, RulePotential, RulePass, RuleContextHierarchy } from "../api/IRule"; import { eRulePolicy, eToolkitLevel } from "../api/IRule"; -import { setCache } from "../util/CacheUtil"; +//import { setCache } from "../util/CacheUtil"; import { getWeightNumber, getFontInPixels } from "../util/CSSUtil"; export let IBMA_Color_Contrast_WCAG2AA: Rule = { diff --git a/accessibility-checker-engine/test/v2/checker/accessibility/rules/IBMA_Color_Contrast_WCAG2AA_PV_ruleunit/Color-usingClass-BG.html b/accessibility-checker-engine/test/v2/checker/accessibility/rules/IBMA_Color_Contrast_WCAG2AA_PV_ruleunit/Color-usingClass-BG.html index 90823abc9..320456943 100644 --- a/accessibility-checker-engine/test/v2/checker/accessibility/rules/IBMA_Color_Contrast_WCAG2AA_PV_ruleunit/Color-usingClass-BG.html +++ b/accessibility-checker-engine/test/v2/checker/accessibility/rules/IBMA_Color_Contrast_WCAG2AA_PV_ruleunit/Color-usingClass-BG.html @@ -327,7 +327,7 @@

Color using Class Tests

passedXpaths: [ ], failedXpaths: [ - "/html/body/div[1]", + /**"/html/body/div[1]", "/html/body/div[2]", "/html/body/div[3]", "/html/body/div[4]", @@ -348,7 +348,7 @@

Color using Class Tests

"/html/body/div[42]", "/html/body/div[43]", "/html/body/div[44]", - "/html/body/div[45]" + "/html/body/div[45]"*/ ] } ]; diff --git a/accessibility-checker-engine/test/v2/checker/accessibility/rules/IBMA_Color_Contrast_WCAG2AA_PV_ruleunit/Color-usingInline-BG.html b/accessibility-checker-engine/test/v2/checker/accessibility/rules/IBMA_Color_Contrast_WCAG2AA_PV_ruleunit/Color-usingInline-BG.html index 61656b3fb..15b4fd467 100644 --- a/accessibility-checker-engine/test/v2/checker/accessibility/rules/IBMA_Color_Contrast_WCAG2AA_PV_ruleunit/Color-usingInline-BG.html +++ b/accessibility-checker-engine/test/v2/checker/accessibility/rules/IBMA_Color_Contrast_WCAG2AA_PV_ruleunit/Color-usingInline-BG.html @@ -112,7 +112,7 @@

Color using inline code Tests

passedXpaths: [ ], failedXpaths: [ - "/html/body/div[1]", + /**"/html/body/div[1]", "/html/body/div[2]", "/html/body/div[3]", "/html/body/div[4]", @@ -133,7 +133,7 @@

Color using inline code Tests

"/html/body/div[42]", "/html/body/div[43]", "/html/body/div[44]", - "/html/body/div[45]" + "/html/body/div[45]"*/ ] } ]; diff --git a/accessibility-checker-engine/test/v2/checker/accessibility/rules/IBMA_Color_Contrast_WCAG2AA_ruleunit/act_fail_7.html b/accessibility-checker-engine/test/v2/checker/accessibility/rules/IBMA_Color_Contrast_WCAG2AA_ruleunit/act_fail_7.html index 8883edab9..89fa98409 100644 --- a/accessibility-checker-engine/test/v2/checker/accessibility/rules/IBMA_Color_Contrast_WCAG2AA_ruleunit/act_fail_7.html +++ b/accessibility-checker-engine/test/v2/checker/accessibility/rules/IBMA_Color_Contrast_WCAG2AA_ruleunit/act_fail_7.html @@ -36,7 +36,7 @@ "reasonId": "Potential_graphic_background", "message": "Verify the contrast ratio of the text against the lightest and the darkest colors of the background meets the WCAG 2.1 AA minimum requirements for text of size 16px and weight of 400", "messageArgs": [ - "2.30", + "1.00", 16, 400 ], diff --git a/accessibility-checker-engine/test/v2/checker/accessibility/rules/IBMA_Color_Contrast_WCAG2AA_ruleunit/color_gradient_transparent.html b/accessibility-checker-engine/test/v2/checker/accessibility/rules/IBMA_Color_Contrast_WCAG2AA_ruleunit/color_gradient_transparent.html new file mode 100644 index 000000000..b587e8041 --- /dev/null +++ b/accessibility-checker-engine/test/v2/checker/accessibility/rules/IBMA_Color_Contrast_WCAG2AA_ruleunit/color_gradient_transparent.html @@ -0,0 +1,51 @@ + + + + + Test Suite + + + + + + + Hello world + + + + + \ No newline at end of file diff --git a/accessibility-checker-engine/test/v2/checker/accessibility/rules/IBMA_Color_Contrast_WCAG2AA_ruleunit/color_gradient_transparent2.html b/accessibility-checker-engine/test/v2/checker/accessibility/rules/IBMA_Color_Contrast_WCAG2AA_ruleunit/color_gradient_transparent2.html new file mode 100644 index 000000000..1c6ca651f --- /dev/null +++ b/accessibility-checker-engine/test/v2/checker/accessibility/rules/IBMA_Color_Contrast_WCAG2AA_ruleunit/color_gradient_transparent2.html @@ -0,0 +1,51 @@ + + + + + Test Suite + + + + +
+ + Hello world + +
+ + + \ No newline at end of file diff --git a/accessibility-checker-engine/test/v2/checker/accessibility/rules/IBMA_Color_Contrast_WCAG2AA_ruleunit/color_gradient_transparent3.html b/accessibility-checker-engine/test/v2/checker/accessibility/rules/IBMA_Color_Contrast_WCAG2AA_ruleunit/color_gradient_transparent3.html new file mode 100644 index 000000000..49dd74159 --- /dev/null +++ b/accessibility-checker-engine/test/v2/checker/accessibility/rules/IBMA_Color_Contrast_WCAG2AA_ruleunit/color_gradient_transparent3.html @@ -0,0 +1,83 @@ + + + + + Test Suite + + + + +
+ + Hello world + + +
+
+ + Hello world + +
+ + + \ No newline at end of file From c30396a27e7e006c6dbc7526a2f72544db5fb19a Mon Sep 17 00:00:00 2001 From: Shunguo Yan Date: Tue, 18 Apr 2023 09:26:42 -0500 Subject: [PATCH 06/24] update the rule for special characters #1202 --- .../v4/rules/IBMA_Color_Contrast_WCAG2AA.ts | 14 +++++++--- .../act_pass_7.html | 26 +------------------ 2 files changed, 12 insertions(+), 28 deletions(-) diff --git a/accessibility-checker-engine/src/v4/rules/IBMA_Color_Contrast_WCAG2AA.ts b/accessibility-checker-engine/src/v4/rules/IBMA_Color_Contrast_WCAG2AA.ts index f7480f99d..146cea157 100644 --- a/accessibility-checker-engine/src/v4/rules/IBMA_Color_Contrast_WCAG2AA.ts +++ b/accessibility-checker-engine/src/v4/rules/IBMA_Color_Contrast_WCAG2AA.ts @@ -80,9 +80,17 @@ export let IBMA_Color_Contrast_WCAG2AA: Rule = { // Ensure that this element has children with actual text. let childStr = RPTUtil.getNodeText(ruleContext); - if (childStr.trim().length == 0 && (!RPTUtil.isShadowHostElement(ruleContext) || (RPTUtil.isShadowHostElement(ruleContext) && RPTUtil.getNodeText(ruleContext.shadowRoot) === ''))) - return null; - + if (!RPTUtil.isShadowHostElement(ruleContext) || (RPTUtil.isShadowHostElement(ruleContext) && RPTUtil.getNodeText(ruleContext.shadowRoot) === '')) { + if (childStr.trim().length == 0 ) + return null; + + // ignore if the text does not convey anything in human language + //const removed = childStr.replace(/[\u0000-\u0008,\u000A-\u001F,\u007F-\u00A0]+/g, ''); + const removed = childStr.replace(/[\u0000-\u0008\u000B-\u001F\u007F-\u009F\u2000-\u200F\u2028-\u202F\u205F-\u206F\u3000\uFEFF]+/g, ''); + if (removed.length === 0) + return null; + } + let elem = ruleContext; // the child elements (rather than shadow root) of a shadow host is either re-assigned to the shadow slot if the slot exists // or not displayed, so shouldn't be checked from the light DOM, rather it should be checked as reassginged slot element(s) in the shadow DOM. diff --git a/accessibility-checker-engine/test/v2/checker/accessibility/rules/IBMA_Color_Contrast_WCAG2AA_ruleunit/act_pass_7.html b/accessibility-checker-engine/test/v2/checker/accessibility/rules/IBMA_Color_Contrast_WCAG2AA_ruleunit/act_pass_7.html index 5d7370bd8..6005d1d82 100644 --- a/accessibility-checker-engine/test/v2/checker/accessibility/rules/IBMA_Color_Contrast_WCAG2AA_ruleunit/act_pass_7.html +++ b/accessibility-checker-engine/test/v2/checker/accessibility/rules/IBMA_Color_Contrast_WCAG2AA_ruleunit/act_pass_7.html @@ -14,31 +14,7 @@ + + \ No newline at end of file From 3e832c594aa98a74fae83139c805ee3f65353f31 Mon Sep 17 00:00:00 2001 From: Shunguo Yan Date: Tue, 18 Apr 2023 15:59:13 -0500 Subject: [PATCH 08/24] add potential violation for text shadow #1202 --- accessibility-checker-engine/src/v2/dom/ColorUtil.ts | 5 +++++ .../src/v4/rules/IBMA_Color_Contrast_WCAG2AA.ts | 12 +++++++++--- .../act_pass_4.html | 12 ++++-------- 3 files changed, 18 insertions(+), 11 deletions(-) diff --git a/accessibility-checker-engine/src/v2/dom/ColorUtil.ts b/accessibility-checker-engine/src/v2/dom/ColorUtil.ts index caac7a8ba..e4e8c7305 100644 --- a/accessibility-checker-engine/src/v2/dom/ColorUtil.ts +++ b/accessibility-checker-engine/src/v2/dom/ColorUtil.ts @@ -225,6 +225,7 @@ export class ColorUtil { var retVal = { "hasGradient": false, "hasBGImage": false, + "textShadow": false, "fg": null, "bg": null }; @@ -376,6 +377,10 @@ export class ColorUtil { } retVal.fg = fg; retVal.bg = priorStackBG; + + if (cStyle.textShadow && cStyle.textShadow !== 'none') + retVal.textShadow = true; + return retVal; } catch (err) { // something happened, then... diff --git a/accessibility-checker-engine/src/v4/rules/IBMA_Color_Contrast_WCAG2AA.ts b/accessibility-checker-engine/src/v4/rules/IBMA_Color_Contrast_WCAG2AA.ts index 0c6c47059..d8e2ec71c 100644 --- a/accessibility-checker-engine/src/v4/rules/IBMA_Color_Contrast_WCAG2AA.ts +++ b/accessibility-checker-engine/src/v4/rules/IBMA_Color_Contrast_WCAG2AA.ts @@ -28,7 +28,8 @@ export let IBMA_Color_Contrast_WCAG2AA: Rule = { "Pass_0": `IBMA_Color_Contrast_WCAG2AA.html`, "Fail_1": `IBMA_Color_Contrast_WCAG2AA.html`, "Potential_same_color": `IBMA_Color_Contrast_WCAG2AA.html`, - "Potential_graphic_background": `IBMA_Color_Contrast_WCAG2AA.html` + "Potential_graphic_background": `IBMA_Color_Contrast_WCAG2AA.html`, + "Potential_text_shadow": `IBMA_Color_Contrast_WCAG2AA.html` } }, messages: { @@ -37,7 +38,8 @@ export let IBMA_Color_Contrast_WCAG2AA: Rule = { "Pass_0": "Rule Passed", "Fail_1": "Text contrast of {0} with its background is less than the WCAG AA minimum requirements for text of size {1}px and weight of {2}", "Potential_same_color": "The foreground text and its background color are both detected as {3}. Verify the text meets the WCAG 2.1 AA requirements for minimum contrast", - "Potential_graphic_background": "Verify the contrast ratio of the text against the lightest and the darkest colors of the background meets the WCAG 2.1 AA minimum requirements for text of size {1}px and weight of {2}" + "Potential_graphic_background": "Verify the contrast ratio of the text against the lightest and the darkest colors of the background meets the WCAG 2.1 AA minimum requirements for text of size {1}px and weight of {2}", + "Potential_text_shadow": "Verify the contrast ratio of the text with shadow meets the WCAG 2.1 AA minimum requirements for text of size {1}px and weight of {2}" } }, rulesets: [{ @@ -241,6 +243,7 @@ export let IBMA_Color_Contrast_WCAG2AA: Rule = { let isLargeScale = size >= 24 || size >= 18.6 && weight >= 700; let passed = ratio >= 4.5 || (ratio >= 3 && isLargeScale); let hasBackground = colorCombo.hasBGImage || colorCombo.hasGradient; + let textShadow = colorCombo.textShadow; let isDisabled = RPTUtil.isNodeDisabled(elem); if (!isDisabled) { let control = RPTUtil.getControlOfLabel(elem); @@ -272,8 +275,11 @@ export let IBMA_Color_Contrast_WCAG2AA: Rule = { } if (!passed) { if (hasBackground) { - // fire potential since a text on an image or gradient can still viewable, depending on the text location on the gradient or image + // fire potential since a text on an image or gradient may be still viewable, depending on the text location on the gradient or image return RulePotential("Potential_graphic_background", [ratio.toFixed(2), size, weight]);; + } else if (textShadow) { + // fire potential since a text with shadow may be still viewable, depending on the shadow efffects + return RulePotential("Potential_text_shadow", [ratio.toFixed(2), size, weight]);; } else { if (fg.toHex() === bg.toHex()) { return RulePotential("Potential_same_color", [ratio.toFixed(2), size, weight, fg.toHex(), bg.toHex(), colorCombo.hasBGImage, colorCombo.hasGradient]); diff --git a/accessibility-checker-engine/test/v2/checker/accessibility/rules/IBMA_Color_Contrast_WCAG2AA_ruleunit/act_pass_4.html b/accessibility-checker-engine/test/v2/checker/accessibility/rules/IBMA_Color_Contrast_WCAG2AA_ruleunit/act_pass_4.html index 46301f96c..dbe34376c 100644 --- a/accessibility-checker-engine/test/v2/checker/accessibility/rules/IBMA_Color_Contrast_WCAG2AA_ruleunit/act_pass_4.html +++ b/accessibility-checker-engine/test/v2/checker/accessibility/rules/IBMA_Color_Contrast_WCAG2AA_ruleunit/act_pass_4.html @@ -19,22 +19,18 @@ "ruleId": "IBMA_Color_Contrast_WCAG2AA", "value": [ "INFORMATION", - "FAIL" + "POTENTIAL" ], "path": { "dom": "/html[1]/body[1]/p[1]", "aria": "/document[1]/paragraph[1]" }, - "reasonId": "Fail_1", - "message": "Text contrast of 4.43 with its background is less than the WCAG AA minimum requirements for text of size 16px and weight of 400", + "reasonId": "Potential_text_shadow", + "message": "Verify the contrast ratio of the text with shadow meets the WCAG 2.1 AA minimum requirements for text of size 16px and weight of 400", "messageArgs": [ "4.43", 16, - 400, - "#000000", - "#737373", - false, - false + 400 ], "apiArgs": [], "category": "Accessibility" From bd644833dd884f095fcc5cf17955c9facd4d65d6 Mon Sep 17 00:00:00 2001 From: Shunguo Yan Date: Wed, 19 Apr 2023 11:31:48 -0500 Subject: [PATCH 09/24] update the baselines #1202 --- .../test/baselines/JSONObjectStructureVerification.html.json | 4 ++-- .../JSONObjectStructureVerificationSelenium.html.json | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/accessibility-checker/test/baselines/JSONObjectStructureVerification.html.json b/accessibility-checker/test/baselines/JSONObjectStructureVerification.html.json index 3e90d2ca3..148d5b810 100644 --- a/accessibility-checker/test/baselines/JSONObjectStructureVerification.html.json +++ b/accessibility-checker/test/baselines/JSONObjectStructureVerification.html.json @@ -533,7 +533,7 @@ }, "reasonId": "Pass_0", "message": "Rule Passed", - "messageArgs": ["21.00", 32, 700], + "messageArgs": [], "apiArgs": [], "bounds": { "left": 8, @@ -1646,7 +1646,7 @@ }, "reasonId": "Pass_0", "message": "Rule Passed", - "messageArgs": ["9.40", 16, 400], + "messageArgs": [], "apiArgs": [], "bounds": { "left": 8, diff --git a/accessibility-checker/test/baselines/JSONObjectStructureVerificationSelenium.html.json b/accessibility-checker/test/baselines/JSONObjectStructureVerificationSelenium.html.json index e63975930..814b99d0b 100644 --- a/accessibility-checker/test/baselines/JSONObjectStructureVerificationSelenium.html.json +++ b/accessibility-checker/test/baselines/JSONObjectStructureVerificationSelenium.html.json @@ -654,7 +654,7 @@ }, "category": "Accessibility", "message": "Rule Passed", - "messageArgs": ["21.00", 32, 700], + "messageArgs": [], "path": { "aria": "/document[1]/main[1]/heading[1]", "dom": "/html[1]/body[1]/div[2]/h1[1]" @@ -1767,7 +1767,7 @@ }, "category": "Accessibility", "message": "Rule Passed", - "messageArgs": ["9.40", 16, 400], + "messageArgs": [], "path": { "aria": "/document[1]/navigation[1]/link[1]", "dom": "/html[1]/body[1]/div[1]/a[1]" From 68c5b8e3fe7016bf065a0e2c0d4385515a3fcabc Mon Sep 17 00:00:00 2001 From: Shunguo Yan Date: Thu, 20 Apr 2023 10:22:43 -0500 Subject: [PATCH 10/24] update rule and test case #1336 --- .../src/v2/aria/ARIADefinitions.ts | 1 + .../body_attribute.html | 40 ++++++++++++++++++ .../section copy.html | 42 ------------------- 3 files changed, 41 insertions(+), 42 deletions(-) create mode 100644 accessibility-checker-engine/test/v2/checker/accessibility/rules/aria_semantics_role_ruleunit/body_attribute.html delete mode 100644 accessibility-checker-engine/test/v2/checker/accessibility/rules/aria_semantics_role_ruleunit/section copy.html diff --git a/accessibility-checker-engine/src/v2/aria/ARIADefinitions.ts b/accessibility-checker-engine/src/v2/aria/ARIADefinitions.ts index c8b040852..47eedf466 100644 --- a/accessibility-checker-engine/src/v2/aria/ARIADefinitions.ts +++ b/accessibility-checker-engine/src/v2/aria/ARIADefinitions.ts @@ -1710,6 +1710,7 @@ export class ARIADefinitions { "body": { implicitRole: ["generic"], validRoles: null, + otherDisallowedAriaAttributes: ['aria-hidden'], globalAriaAttributesValid: true }, "br": { diff --git a/accessibility-checker-engine/test/v2/checker/accessibility/rules/aria_semantics_role_ruleunit/body_attribute.html b/accessibility-checker-engine/test/v2/checker/accessibility/rules/aria_semantics_role_ruleunit/body_attribute.html new file mode 100644 index 000000000..618f45fc2 --- /dev/null +++ b/accessibility-checker-engine/test/v2/checker/accessibility/rules/aria_semantics_role_ruleunit/body_attribute.html @@ -0,0 +1,40 @@ + + + + Sandbox + + + + +
+

Test page

+
+ + + diff --git a/accessibility-checker-engine/test/v2/checker/accessibility/rules/aria_semantics_role_ruleunit/section copy.html b/accessibility-checker-engine/test/v2/checker/accessibility/rules/aria_semantics_role_ruleunit/section copy.html deleted file mode 100644 index 2be030999..000000000 --- a/accessibility-checker-engine/test/v2/checker/accessibility/rules/aria_semantics_role_ruleunit/section copy.html +++ /dev/null @@ -1,42 +0,0 @@ - - - - Sandbox - - - - -
-

Test page

-
- Hello -
-
- - - From 602a5adba0d83712926e0184d03bb42f077d0310 Mon Sep 17 00:00:00 2001 From: Shunguo Yan Date: Thu, 20 Apr 2023 14:54:07 -0500 Subject: [PATCH 11/24] add search element support #1336 --- .../src/v2/aria/ARIADefinitions.ts | 5 + .../search_role_attribute.html | 175 ++++++++++++++++++ 2 files changed, 180 insertions(+) create mode 100644 accessibility-checker-engine/test/v2/checker/accessibility/rules/aria_semantics_role_ruleunit/search_role_attribute.html diff --git a/accessibility-checker-engine/src/v2/aria/ARIADefinitions.ts b/accessibility-checker-engine/src/v2/aria/ARIADefinitions.ts index 47eedf466..d685f2d26 100644 --- a/accessibility-checker-engine/src/v2/aria/ARIADefinitions.ts +++ b/accessibility-checker-engine/src/v2/aria/ARIADefinitions.ts @@ -2052,6 +2052,11 @@ export class ARIADefinitions { validRoles: null, globalAriaAttributesValid: false }, + "search": { + implicitRole: ['search'], + validRoles: ['search', 'form', 'group', 'none', 'presentation', 'region'], + globalAriaAttributesValid: true + }, "slot": { implicitRole: null, validRoles: null, diff --git a/accessibility-checker-engine/test/v2/checker/accessibility/rules/aria_semantics_role_ruleunit/search_role_attribute.html b/accessibility-checker-engine/test/v2/checker/accessibility/rules/aria_semantics_role_ruleunit/search_role_attribute.html new file mode 100644 index 000000000..ad35b39c8 --- /dev/null +++ b/accessibility-checker-engine/test/v2/checker/accessibility/rules/aria_semantics_role_ruleunit/search_role_attribute.html @@ -0,0 +1,175 @@ + + + + Sandbox + + + + +
+ + + + + + + + +
+ + + From 9ba2144ef1890b42fb83345e3e81b2da88db837d Mon Sep 17 00:00:00 2001 From: Shunguo Yan Date: Mon, 24 Apr 2023 15:11:49 -0500 Subject: [PATCH 12/24] test cases #1301 --- .../src/v2/aria/ARIADefinitions.ts | 2 +- ...aria_hidden_fail_with_summary_element.html | 2 +- .../summary_element.html | 103 ++++++++++++++++++ 3 files changed, 105 insertions(+), 2 deletions(-) create mode 100644 accessibility-checker-engine/test/v2/checker/accessibility/rules/aria_semantics_role_ruleunit/summary_element.html diff --git a/accessibility-checker-engine/src/v2/aria/ARIADefinitions.ts b/accessibility-checker-engine/src/v2/aria/ARIADefinitions.ts index c8b040852..b35f3278b 100644 --- a/accessibility-checker-engine/src/v2/aria/ARIADefinitions.ts +++ b/accessibility-checker-engine/src/v2/aria/ARIADefinitions.ts @@ -2087,7 +2087,7 @@ export class ARIADefinitions { globalAriaAttributesValid: true }, "summary": { - implicitRole: ["button"], + implicitRole: null, validRoles: null, globalAriaAttributesValid: true }, diff --git a/accessibility-checker-engine/test/v2/checker/accessibility/rules/aria_hidden_focus_misuse_ruleunit/act_6cfa84_aria_hidden_fail_with_summary_element.html b/accessibility-checker-engine/test/v2/checker/accessibility/rules/aria_hidden_focus_misuse_ruleunit/act_6cfa84_aria_hidden_fail_with_summary_element.html index f6ff65ae6..c433b0afe 100644 --- a/accessibility-checker-engine/test/v2/checker/accessibility/rules/aria_hidden_focus_misuse_ruleunit/act_6cfa84_aria_hidden_fail_with_summary_element.html +++ b/accessibility-checker-engine/test/v2/checker/accessibility/rules/aria_hidden_focus_misuse_ruleunit/act_6cfa84_aria_hidden_fail_with_summary_element.html @@ -57,7 +57,7 @@ ], "path": { "dom": "/html[1]/body[1]/details[1]/summary[1]", - "aria": "/document[1]/generic[1]/group[1]/button[1]" + "aria": "/document[1]/generic[1]/group[1]" }, "reasonId": "Fail_1", "message": "Element \"summary\" should not be focusable within the subtree of an element with an 'aria-hidden' attribute with value 'true'", diff --git a/accessibility-checker-engine/test/v2/checker/accessibility/rules/aria_semantics_role_ruleunit/summary_element.html b/accessibility-checker-engine/test/v2/checker/accessibility/rules/aria_semantics_role_ruleunit/summary_element.html new file mode 100644 index 000000000..f6812537a --- /dev/null +++ b/accessibility-checker-engine/test/v2/checker/accessibility/rules/aria_semantics_role_ruleunit/summary_element.html @@ -0,0 +1,103 @@ + + + + + + + Element with aria-hidden has no focusable content + + + + + +
+ Overview +
    +
  1. Cash on hand: $500.00
  2. +
  3. Current invoice: $75.30
  4. +
  5. Due date: 5/6/19
  6. +
+
+
    +
  • li element
  • +
+ + + + \ No newline at end of file From 845c562d089e5554766635be6c023d5a47440c38 Mon Sep 17 00:00:00 2001 From: Shunguo Yan Date: Wed, 26 Apr 2023 15:35:32 -0500 Subject: [PATCH 13/24] create test cases #1301 --- .../src/v2/aria/ARIADefinitions.ts | 18 +- .../v2/checker/accessibility/util/legacy.ts | 20 +- .../summary_element.html | 541 ++++++++++++++++-- 3 files changed, 511 insertions(+), 68 deletions(-) diff --git a/accessibility-checker-engine/src/v2/aria/ARIADefinitions.ts b/accessibility-checker-engine/src/v2/aria/ARIADefinitions.ts index b35f3278b..dec8e12ea 100644 --- a/accessibility-checker-engine/src/v2/aria/ARIADefinitions.ts +++ b/accessibility-checker-engine/src/v2/aria/ARIADefinitions.ts @@ -2086,11 +2086,6 @@ export class ARIADefinitions { validRoles: ["any"], globalAriaAttributesValid: true }, - "summary": { - implicitRole: null, - validRoles: null, - globalAriaAttributesValid: true - }, "sup": { implicitRole: ["superscript"], validRoles: ["any"], @@ -2504,6 +2499,19 @@ export class ARIADefinitions { otherDisallowedAriaAttributes: ["aria-multiselectable"] } }, + "summary": { + "first-summary-of-detail": { + implicitRole: null, + validRoles: null, + globalAriaAttributesValid: true, + otherAllowedAriaAttributes: ["aria-disabled", "aria-haspopup"] + }, + "not-first-summary-of-detail": { + implicitRole: null, + validRoles: ["any"], + globalAriaAttributesValid: true + } + }, "tbody": { "des-table": { implicitRole: ["rowgroup"], diff --git a/accessibility-checker-engine/src/v2/checker/accessibility/util/legacy.ts b/accessibility-checker-engine/src/v2/checker/accessibility/util/legacy.ts index 52cb64af6..97f080380 100644 --- a/accessibility-checker-engine/src/v2/checker/accessibility/util/legacy.ts +++ b/accessibility-checker-engine/src/v2/checker/accessibility/util/legacy.ts @@ -21,6 +21,7 @@ import { DOMWalker } from "../../../dom/DOMWalker"; import { VisUtil } from "../../../dom/VisUtil"; import { FragmentUtil } from "./fragment"; import { getDefinedStyles } from "../../../../v4/util/CSSUtil"; +import { DOMUtil } from "../../../dom/DOMUtil"; export class RPTUtil { @@ -376,7 +377,15 @@ export class RPTUtil { "video": function (element) { return element.hasAttribute("controls"); }, - "summary": true + "summary": function (element) { + // first summary child of a details element is automatically focusable + return element.parentElement && element.parentElement.nodeName.toLowerCase() === 'details' + && DOMUtil.sameNode([...element.parentElement.children].filter(elem=>elem.nodeName.toLowerCase() === 'summary')[0], element); + }, + "details": function (element) { + //details element without a direct summary child is automatically focusable + return element.children && [...element.children].filter(elem=>elem.nodeName.toLowerCase() === 'summary').length === 0; + } } public static wordCount(str) : number { @@ -2559,6 +2568,15 @@ export class RPTUtil { else tagProperty = specialTagProperties["no-multiple-attr-size-gt1"]; break; + case "summary": + specialTagProperties = ARIADefinitions.documentConformanceRequirementSpecialTags["summary"]; + + if (ruleContext.parentElement && ruleContext.parentElement.nodeName.toLowerCase() === 'details' + && DOMUtil.sameNode([...ruleContext.parentElement.children].filter(elem=>elem.nodeName.toLowerCase() === 'summary')[0], ruleContext)) + tagProperty = specialTagProperties["first-summary-of-detail"]; + else + tagProperty = specialTagProperties["no-first-summary-of-detail"]; + break; case "tbody": case "td": case "tr": diff --git a/accessibility-checker-engine/test/v2/checker/accessibility/rules/aria_semantics_role_ruleunit/summary_element.html b/accessibility-checker-engine/test/v2/checker/accessibility/rules/aria_semantics_role_ruleunit/summary_element.html index f6812537a..b536d21aa 100644 --- a/accessibility-checker-engine/test/v2/checker/accessibility/rules/aria_semantics_role_ruleunit/summary_element.html +++ b/accessibility-checker-engine/test/v2/checker/accessibility/rules/aria_semantics_role_ruleunit/summary_element.html @@ -26,75 +26,492 @@ -
- Overview + + -
    -
  • li element
  • -
+ Third summary +
+ + + + + + + From 476bf68faf93df9c35cf34a5a9241539947cb100 Mon Sep 17 00:00:00 2001 From: Shunguo Yan Date: Fri, 28 Apr 2023 13:28:54 -0500 Subject: [PATCH 14/24] update role support #1301 --- .gitignore | 1 + .../summary_element_hidden.html | 520 ++++++++++++++++++ .../summary_element.html | 24 +- 3 files changed, 531 insertions(+), 14 deletions(-) create mode 100644 accessibility-checker-engine/test/v2/checker/accessibility/rules/aria_hidden_focus_misuse_ruleunit/summary_element_hidden.html diff --git a/.gitignore b/.gitignore index deec545a3..c2abf9ca0 100644 --- a/.gitignore +++ b/.gitignore @@ -35,3 +35,4 @@ jspm_packages .gz .tar accessibility-checker-engine/karma.conf.js +karma-accessibility-checker/package.json diff --git a/accessibility-checker-engine/test/v2/checker/accessibility/rules/aria_hidden_focus_misuse_ruleunit/summary_element_hidden.html b/accessibility-checker-engine/test/v2/checker/accessibility/rules/aria_hidden_focus_misuse_ruleunit/summary_element_hidden.html new file mode 100644 index 000000000..b536d21aa --- /dev/null +++ b/accessibility-checker-engine/test/v2/checker/accessibility/rules/aria_hidden_focus_misuse_ruleunit/summary_element_hidden.html @@ -0,0 +1,520 @@ + + + + + + + Element with aria-hidden has no focusable content + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/accessibility-checker-engine/test/v2/checker/accessibility/rules/aria_semantics_role_ruleunit/summary_element.html b/accessibility-checker-engine/test/v2/checker/accessibility/rules/aria_semantics_role_ruleunit/summary_element.html index b536d21aa..e472d0c31 100644 --- a/accessibility-checker-engine/test/v2/checker/accessibility/rules/aria_semantics_role_ruleunit/summary_element.html +++ b/accessibility-checker-engine/test/v2/checker/accessibility/rules/aria_semantics_role_ruleunit/summary_element.html @@ -20,35 +20,35 @@ - Element with aria-hidden has no focusable content + Summary Element -