Skip to content

Commit b5be5dc

Browse files
shunguoyphilljenkinstombrunet
authored
fixrule(svg_graphics_labelled, img_alt_valid): Ignore SVG & image accessible name requirement when its ancestor is a widget or requires presentational child (#2269)
* update the rules and add test cases #dev-syan-v3 * fix formatting of help * Try using npm ci instead of npm test --------- Co-authored-by: Phill Jenkins <pjenkins@us.ibm.com> Co-authored-by: Tom Brunet <thbrunet@us.ibm.com>
1 parent 98f4cd2 commit b5be5dc

File tree

9 files changed

+389
-79
lines changed

9 files changed

+389
-79
lines changed

.github/workflows/test.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -549,7 +549,7 @@ jobs:
549549
working-directory: report-react
550550
- run: npm install
551551
working-directory: accessibility-checker-extension
552-
- run: npm install
552+
- run: npm ci
553553
working-directory: accessibility-checker-extension/test
554554
- run: npm install
555555
working-directory: rule-server

accessibility-checker-engine/help-v4/en-US/svg_graphics_labelled.html

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -70,7 +70,7 @@ <h3 id="ruleMessage"></h3>
7070
* **Or**, add a direct child `<title>` element that provides a tooltip, when ARIA label attributes are used to provide the accessible name.
7171
* **Or**, add a `xlink:title` attribute on a link, if not used to provide the accessible name.
7272

73-
Ensure the _decorative_ SVG element use `aria-hidden` or `role=none | presentation` to provides a clear indication that the element is not visible,
73+
Ensure the _decorative_ SVG element use `aria-hidden` or `role="none"` or `role="presentation"` to provides a clear indication that the element is redundant with the nearby text or not visible,
7474
perceivable, or interactive to users.
7575

7676
Note: The `aria-labelledby` and `aria-describedby` properties can reference the element on which they are given,

accessibility-checker-engine/src/v4/rules/img_alt_valid.ts

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ import { Rule, RuleResult, RuleFail, RuleContext, RulePass, RuleContextHierarchy
1515
import { eRulePolicy, eToolkitLevel } from "../api/IRule";
1616
import { AriaUtil } from "../util/AriaUtil";
1717
import { VisUtil } from "../util/VisUtil";
18+
import { AccNameUtil } from "../util/AccNameUtil";
1819

1920
export const img_alt_valid: Rule = {
2021
id: "img_alt_valid",
@@ -53,8 +54,8 @@ export const img_alt_valid: Rule = {
5354
act: "23a2a8",
5455
run: (context: RuleContext, options?: {}, contextHierarchies?: RuleContextHierarchy): RuleResult | RuleResult[] => {
5556
const ruleContext = context["dom"].node as Element;
56-
// If not visible to the screen reader, ignore
57-
if (VisUtil.isNodeHiddenFromAT(ruleContext))
57+
// If not visible to the screen reader, or can be ignored
58+
if (VisUtil.isNodeHiddenFromAT(ruleContext) || AccNameUtil.isAccessibleNameIgnorable(ruleContext))
5859
return null;
5960

6061
if (AriaUtil.getAriaLabel(ruleContext).trim().length !== 0) {

accessibility-checker-engine/src/v4/rules/svg_graphics_labelled.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,7 @@ export const svg_graphics_labelled: Rule = {
4949
const ruleContext = context["dom"].node as Element;
5050

5151
//skip the rule
52-
if (VisUtil.isNodeHiddenFromAT(ruleContext) || VisUtil.isNodePresentational(ruleContext)) return null;
52+
if (VisUtil.isNodeHiddenFromAT(ruleContext) || VisUtil.isNodePresentational(ruleContext) || AccNameUtil.isAccessibleNameIgnorable(ruleContext)) return null;
5353

5454
const name_pair = AccNameUtil.computeAccessibleName(ruleContext);
5555
if (name_pair && name_pair.name && name_pair.name.trim().length > 0)

accessibility-checker-engine/src/v4/util/AccNameUtil.ts

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -481,4 +481,20 @@ export class AccNameUtil {
481481

482482
return null;
483483
}
484+
485+
// if accessible name can be ignored for image or svg
486+
public static isAccessibleNameIgnorable(elem: Element) : boolean {
487+
if (!elem) return false;
488+
489+
const nodeName = elem.nodeName.toLowerCase();
490+
if (nodeName !== 'img' && nodeName !== 'svg') return false;
491+
492+
let parent = elem.parentElement;
493+
if (parent) {
494+
// if the parent is a widget and has an aria label, then image/svg label is not necessary
495+
if ((AriaUtil.isWidget(parent) || AriaUtil.containsPresentationalChildrenOnly(parent)) && AriaUtil.hasAriaLabel(parent))
496+
return true;
497+
}
498+
return false;
499+
}
484500
}

accessibility-checker-engine/src/v4/util/ClipPathUtil.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -116,8 +116,8 @@ export class ClipPathUtil {
116116

117117
// to prevent the bottom edge from crossing over the top edge and right edge from crossing over the left edge.
118118
// for example, rect(10px 0 0 20px) is clamped to rect(10px 20px 10px 20px)
119-
if (numbers[2] < numbers[0] ) numbers[2] = numbers[0];
120-
if (numbers[1] < numbers[3] ) numbers[1] = numbers[3];
119+
numbers[2] = Math.max(numbers[0], numbers[2]);
120+
numbers[1] = Math.max(numbers[1], numbers[3])
121121

122122
let top = parseInt(numbers[0]);
123123
if (isNaN(top)) {

accessibility-checker-engine/test/test.html

Lines changed: 76 additions & 72 deletions
Original file line numberDiff line numberDiff line change
@@ -5,15 +5,53 @@
55
<title>test case</title>
66
</head>
77
<body>
8+
<a href="https://ibm.com">Content</a>
9+
<hr style="margin-top:50px;">
10+
<div>Auto Scrollable w/o tabindex</div>
11+
<section id='section1' style="height: 100px; width: 500px; overflow-x: auto; overflow-y: auto;">
812
<hr style="margin-top:50px;">
913
<section id='section1' style="height: 100px; width: 500px; overflow-x: hidden; overflow-y: hidden;">
10-
<p>
11-
Web Content Accessibility Guidelines (WCAG) covers a wide range of recommendations for making Web content more
12-
accessible.
13-
</p>
14-
15-
</section>
14+
<div>Auto Scrollable w/o tabindex</div>
15+
<section id='section3' style="height: 100px; width: 500px; overflow-x: auto; overflow-y: auto;">
16+
<h1>WCAG Abstract (no tabindex)</h1>
17+
<p>
18+
Web Content Accessibility Guidelines (WCAG) covers a wide range of recommendations for making Web content more
19+
accessible. Following these guidelines will make content more accessible to a wider range of people with
20+
disabilities, including accommodations for blindness and low vision, deafness and hearing loss, limited movement,
21+
speech disabilities, photosensitivity, and combinations of these, and some accommodation for learning disabilities
22+
and cognitive limitations; but will not address every user need for people with these disabilities. These guidelines
23+
address accessibility of web content on desktops, laptops, tablets, and mobile devices. Following these guidelines
24+
will also often make Web content more usable to users in general.
25+
</p>
26+
</section>
27+
<hr style="margin-top:50px;">
28+
<div>Auto Scrollable w/ tabindex='-1'</div>
29+
<section id='section3' tabindex='-1' style="height: 100px; width: 500px; overflow-x: auto; overflow-y: auto;">
30+
<h1>WCAG Abstract</h1>
31+
<p>
32+
Web Content Accessibility Guidelines (WCAG) covers a wide range of recommendations for making Web content more
33+
accessible. Following these guidelines will make content more accessible to a wider range of people with
34+
disabilities, including accommodations for blindness and low vision, deafness and hearing loss, limited movement,
35+
speech disabilities, photosensitivity, and combinations of these, and some accommodation for learning disabilities
36+
and cognitive limitations; but will not address every user need for people with these disabilities. These guidelines
37+
address accessibility of web content on desktops, laptops, tablets, and mobile devices. Following these guidelines
38+
will also often make Web content more usable to users in general.
39+
</p>
40+
</section>
41+
1642
<hr style="margin-top:50px;">
43+
<div>iframe w/o tabindex short content</div>
44+
<iframe id='section2' style="height: 100px; width: 500px; overflow-x: auto; overflow-y: auto;"
45+
srcdoc="Web Content Accessibility Guidelines (WCAG) covers a wide range of recommendations for making Web content more
46+
accessible."
47+
48+
>
49+
</iframe>
50+
51+
<hr style="margin-top:50px;">
52+
<div>iframe w/o tabindex long content</div>
53+
<iframe id='section2' role='none' style="height: 100px; width: 500px; overflow-x: auto; overflow-y: auto;"
54+
srcdoc="Web Content Accessibility Guidelines (WCAG) covers a wide range of recommendations for making Web content more
1755
<iframe id='section2' src='./test2.html' style="height: 100px; width: 500px; overflow-x: hidden; overflow-y: hidden;">
1856

1957
</body>
@@ -26,14 +64,29 @@
2664
<h1>WCAG Abstract</h1>
2765
<p>
2866
Web Content Accessibility Guidelines (WCAG) covers a wide range of recommendations for making Web content more
67+
68+
will also often make Web content more usable to users in general."
69+
70+
>
71+
</iframe>
72+
73+
<hr style="margin-top:50px;">
74+
<div>iframe w/ tabindex='-1'</div>
75+
<iframe id='section2' tabindex='-1' style="height: 100px; width: 500px; overflow-x: auto; overflow-y: auto;"
76+
srcdoc="Web Content Accessibility Guidelines (WCAG) covers a wide range of recommendations for making Web content more
2977
accessible. Following these guidelines will make content more accessible to a wider range of people with
3078
disabilities, including accommodations for blindness and low vision, deafness and hearing loss, limited movement,
3179
speech disabilities, photosensitivity, and combinations of these, and some accommodation for learning disabilities
3280
and cognitive limitations; but will not address every user need for people with these disabilities. These guidelines
3381
address accessibility of web content on desktops, laptops, tablets, and mobile devices. Following these guidelines
34-
will also often make Web content more usable to users in general.
35-
</p>
36-
</section>
82+
will also often make Web content more usable to users in general."
83+
84+
>
85+
</iframe>
86+
87+
<iframe role='none' src="./tinker.html">
88+
</iframe>
89+
3790

3891
<hr style="margin-top:50px;">
3992
<button aria-label="a test button">
@@ -49,73 +102,24 @@ <h1>WCAG Abstract</h1>
49102
<button aria-label="a test nutton"><img src="http://thinkingstiff.com/images/matt.jpg" alt=""></button>
50103
<button aria-label="a test nutton"><img src="http://thinkingstiff.com/images/matt.jpg" role="none"></button>
51104

52-
<a href="http://ibm.com"><img src="http://thinkingstiff.com/images/matt.jpg" />Here</a>
53-
54-
<a href="http://ibm.com"><img src="http://thinkingstiff.com/images/matt.jpg" alt="image" /></a>
105+
will also often make Web content more usable to users in general.
106+
</p>
107+
</section>
55108

56-
<ol>
57-
<li>Option 1<img src="http://thinkingstiff.com/images/matt.jpg"></li>
58-
<li>Option 2<img src="http://thinkingstiff.com/images/matt.jpg"></li>
59-
</ol>
109+
<hr style="margin-top:50px;">
110+
<button aria-label="a test button">
111+
<svg>
112+
</svg>
113+
</button>
60114

115+
<button aria-label="a test nutton"><img src="http://thinkingstiff.com/images/matt.jpg"></button>
116+
<button><img src="http://thinkingstiff.com/images/matt.jpg" alt="an image"></button>
117+
<button><img src="http://thinkingstiff.com/images/matt.jpg">Submit</button>
118+
<button><img src="http://thinkingstiff.com/images/matt.jpg" alt="">Submit</button>
61119

62-
</main>
120+
<button aria-label="a test nutton"><img src="http://thinkingstiff.com/images/matt.jpg" alt=""></button>
121+
<button aria-label="a test nutton"><img src="http://thinkingstiff.com/images/matt.jpg" role="none"></button>
63122

64-
<script>
65-
UnitTest = {
66-
ruleIds: ["element_scrollable_tabbable", "element_tabbable_role_valid"],
67-
results: [
68-
{
69-
"ruleId": "element_scrollable_tabbable",
70-
"value": [
71-
"INFORMATION",
72-
"PASS"
73-
],
74-
"path": {
75-
"dom": "/html[1]/body[1]/section[1]",
76-
"aria": "/document[1]"
77-
},
78-
"reasonId": "pass_tabbable",
79-
"message": "The scrollable element is tabbable",
80-
"messageArgs": [],
81-
"apiArgs": [],
82-
"category": "Accessibility"
83-
},
84-
{
85-
"ruleId": "element_tabbable_role_valid",
86-
"value": [
87-
"INFORMATION",
88-
"FAIL"
89-
],
90-
"path": {
91-
"dom": "/html[1]/body[1]/section[2]",
92-
"aria": "/document[1]"
93-
},
94-
"reasonId": "fail_no_valid_role",
95-
"message": "The tabbable element does not have a valid widget role",
96-
"messageArgs": [],
97-
"apiArgs": [],
98-
"category": "Accessibility"
99-
},
100-
{
101-
"ruleId": "element_tabbable_role_valid",
102-
"value": [
103-
"INFORMATION",
104-
"FAIL"
105-
],
106-
"path": {
107-
"dom": "/html[1]/body[1]/section[3]",
108-
"aria": "/document[1]"
109-
},
110-
"reasonId": "fail_no_valid_role",
111-
"message": "The tabbable element does not have a valid widget role",
112-
"messageArgs": [],
113-
"apiArgs": [],
114-
"category": "Accessibility"
115-
}
116-
]
117-
}
118-
</script>
119123
</body>
120124

121125
</html>

0 commit comments

Comments
 (0)