Bug 1656330: Implement grid role, mapping, r=Jamie,devtools-reviewers,nchevobbe
[gecko.git] / devtools / server / tests / browser / browser_accessibility_keyboard_audit.js
blobe59cac87a3b7d470b135102f3e4b7f0670056eca
1 /* This Source Code Form is subject to the terms of the Mozilla Public
2  * License, v. 2.0. If a copy of the MPL was not distributed with this
3  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
5 "use strict";
7 /**
8  * Checks functionality around text label audit for the AccessibleActor.
9  */
11 const {
12   accessibility: {
13     AUDIT_TYPE: { KEYBOARD },
14     SCORES: { FAIL, WARNING },
15     ISSUE_TYPE: {
16       [KEYBOARD]: {
17         FOCUSABLE_NO_SEMANTICS,
18         FOCUSABLE_POSITIVE_TABINDEX,
19         INTERACTIVE_NOT_FOCUSABLE,
20         MOUSE_INTERACTIVE_ONLY,
21         NO_FOCUS_VISIBLE,
22       },
23     },
24   },
25 } = require("resource://devtools/shared/constants.js");
27 add_task(async function () {
28   const { target, walker, parentAccessibility, a11yWalker } =
29     await initAccessibilityFrontsForUrl(
30       `${MAIN_DOMAIN}doc_accessibility_keyboard_audit.html`
31     );
33   const tests = [
34     [
35       "Focusable element (styled button) with no semantics.",
36       "#button-1",
37       { score: WARNING, issue: FOCUSABLE_NO_SEMANTICS },
38     ],
39     ["Element (styled button) with no semantics.", "#button-2", null],
40     [
41       "Container element for out of order focusable element.",
42       "#input-container",
43       null,
44     ],
45     [
46       "Interactive element with focus out of order (-1).",
47       "#input-1",
48       {
49         score: FAIL,
50         issue: INTERACTIVE_NOT_FOCUSABLE,
51       },
52     ],
53     [
54       "Interactive element with focus out of order (-1) when disabled.",
55       "#input-2",
56       null,
57     ],
58     ["Interactive element when disabled.", "#input-3", null],
59     ["Focusable interactive element.", "#input-4", null],
60     [
61       "Interactive accesible (link with no attributes) with no accessible actions.",
62       "#link-1",
63       null,
64     ],
65     ["Interactive accessible (link with valid href).", "#link-2", null],
66     ["Interactive accessible (link with # as href).", "#link-3", null],
67     [
68       "Interactive accessible (link with empty string as href).",
69       "#link-4",
70       null,
71     ],
72     ["Interactive accessible with no tabindex.", "#button-3", null],
73     [
74       "Interactive accessible with -1 tabindex.",
75       "#button-4",
76       {
77         score: FAIL,
78         issue: INTERACTIVE_NOT_FOCUSABLE,
79       },
80     ],
81     ["Interactive accessible with 0 tabindex.", "#button-5", null],
82     [
83       "Interactive accessible with 1 tabindex.",
84       "#button-6",
85       { score: WARNING, issue: FOCUSABLE_POSITIVE_TABINDEX },
86     ],
87     [
88       "Focusable ARIA button with no focus styling.",
89       "#focusable-1",
90       { score: WARNING, issue: NO_FOCUS_VISIBLE },
91     ],
92     ["Focusable ARIA button with focus styling.", "#focusable-2", null],
93     ["Focusable ARIA button with browser styling.", "#focusable-3", null],
94     [
95       "Not focusable, non-semantic element that has a click handler.",
96       "#mouse-only-1",
97       { score: FAIL, issue: MOUSE_INTERACTIVE_ONLY },
98     ],
99     [
100       "Focusable, non-semantic element that has a click handler.",
101       "#focusable-4",
102       { score: WARNING, issue: FOCUSABLE_NO_SEMANTICS },
103     ],
104     [
105       "Not focusable, ARIA button that has a click handler.",
106       "#button-7",
107       { score: FAIL, issue: INTERACTIVE_NOT_FOCUSABLE },
108     ],
109     ["Focusable, ARIA button with a click handler.", "#button-8", null],
110     ["Regular image, no keyboard checks should flag an issue.", "#img-1", null],
111     [
112       "Image with a longdesc (accessible will have showlongdesc action).",
113       "#img-2",
114       null,
115     ],
116     [
117       "Clickable image with a longdesc (accessible will have click and showlongdesc actions).",
118       "#img-3",
119       { score: FAIL, issue: MOUSE_INTERACTIVE_ONLY },
120     ],
121     [
122       "Clickable image (accessible will have click action).",
123       "#img-4",
124       { score: FAIL, issue: MOUSE_INTERACTIVE_ONLY },
125     ],
126     ["Focusable button with aria-haspopup.", "#buttonmenu-1", null],
127     [
128       "Not focusable aria button with aria-haspopup.",
129       "#buttonmenu-2",
130       {
131         score: FAIL,
132         issue: INTERACTIVE_NOT_FOCUSABLE,
133       },
134     ],
135     ["Focusable checkbox.", "#checkbox-1", null],
136     ["Focusable select element size > 1", "#listbox-1", null],
137     ["Focusable select element with one option", "#combobox-1", null],
138     ["Focusable select element with no options", "#combobox-2", null],
139     ["Focusable select element with two options", "#combobox-3", null],
140     [
141       "Non-focusable aria combobox with one aria option.",
142       "#editcombobox-1",
143       null,
144     ],
145     ["Non-focusable aria combobox with no options.", "#editcombobox-2", null],
146     ["Focusable aria combobox with no options.", "#editcombobox-3", null],
147     [
148       "Non-focusable aria switch",
149       "#switch-1",
150       {
151         score: FAIL,
152         issue: INTERACTIVE_NOT_FOCUSABLE,
153       },
154     ],
155     ["Focusable aria switch", "#switch-2", null],
156     [
157       "Combobox list that is visible (has focusable state)",
158       "#owned_listbox",
159       null,
160     ],
161     [
162       "Mouse interactive, label that contains form element (linked)",
163       "#label-1",
164       null,
165     ],
166     ["Mouse interactive label for external element (linked)", "#label-2", null],
167     ["Not interactive unlinked label", "#label-3", null],
168     [
169       "Not interactive unlinked label with folloing form element",
170       "#label-4",
171       null,
172     ],
173     ["Image inside an anchor (href)", "#img-5", null],
174     ["Image inside an anchor (onmousedown)", "#img-6", null],
175     ["Image inside an anchor (onclick)", "#img-7", null],
176     ["Image inside an anchor (onmouseup)", "#img-8", null],
177     [
178       "Section with a collapse action from aria-expanded attribute",
179       "#section-1",
180       null,
181     ],
182     ["Tabindex -1 should not report an element as focusable", "#main", null],
183     [
184       "Not keyboard focusable element with no focus styling.",
185       "#not-keyboard-focusable-1",
186       null,
187     ],
188     ["Interactive grid that is not focusable.", "#grid-1", null],
189     [
190       "Focusable interactive grid.",
191       "#grid-2",
192       { score: "WARNING", issue: "FOCUSABLE_NO_SEMANTICS" },
193     ],
194     [
195       "Non interactive ARIA table does not need to be focusable.",
196       "#table-1",
197       null,
198     ],
199     [
200       "Focusable ARIA table does not have interactive semantics",
201       "#table-2",
202       { score: "WARNING", issue: "FOCUSABLE_NO_SEMANTICS" },
203     ],
204     ["Non interactive table does not need to be focusable.", "#table-3", null],
205     [
206       "Focusable table does not have interactive semantics",
207       "#table-4",
208       { score: "WARNING", issue: "FOCUSABLE_NO_SEMANTICS" },
209     ],
210     [
211       "Article that is not focusable is not considered interactive",
212       "#article-1",
213       null,
214     ],
215     ["Focusable article is considered interactive", "#article-2", null],
216     [
217       "Column header that is not focusable is not considered interactive (ARIA grid)",
218       "#columnheader-1",
219       null,
220     ],
221     [
222       "Column header that is not focusable is not considered interactive (ARIA table)",
223       "#columnheader-2",
224       null,
225     ],
226     [
227       "Column header that is not focusable is not considered interactive (table)",
228       "#columnheader-3",
229       null,
230     ],
231     [
232       "Column header that is focusable is considered interactive (table)",
233       "#columnheader-4",
234       null,
235     ],
236     [
237       "Column header that is not focusable is not considered interactive (table as ARIA grid)",
238       "#columnheader-5",
239       null,
240     ],
241     [
242       "Column header that is focusable is considered interactive (table as ARIA grid)",
243       "#columnheader-6",
244       null,
245     ],
246     [
247       "Row header that is not focusable is not considered interactive",
248       "#rowheader-1",
249       null,
250     ],
251     [
252       "Row header that is not focusable is not considered interactive",
253       "#rowheader-2",
254       null,
255     ],
256     [
257       "Row header that is not focusable is not considered interactive",
258       "#rowheader-3",
259       null,
260     ],
261     [
262       "Row header that is focusable is considered interactive",
263       "#rowheader-4",
264       null,
265     ],
266     [
267       "Row header that is not focusable is not considered interactive (table as ARIA grid)",
268       "#rowheader-5",
269       null,
270     ],
271     [
272       "Row header that is focusable is considered interactive (table as ARIA grid)",
273       "#rowheader-6",
274       null,
275     ],
276     [
277       "Gridcell that is not focusable is not considered interactive (ARIA grid)",
278       "#gridcell-1",
279       null,
280     ],
281     [
282       "Gridcell that is focusable is considered interactive (ARIA grid)",
283       "#gridcell-2",
284       null,
285     ],
286     [
287       "Gridcell that is not focusable is not considered interactive (table as ARIA grid)",
288       "#gridcell-3",
289       null,
290     ],
291     [
292       "Gridcell that is focusable is considered interactive (table as ARIA grid)",
293       "#gridcell-4",
294       null,
295     ],
296     [
297       "Tab list that is not focusable is not considered interactive",
298       "#tablist-1",
299       null,
300     ],
301     ["Focusable tab list is considered interactive", "#tablist-2", null],
302     [
303       "Scrollbar that is not focusable is not considered interactive",
304       "#scrollbar-1",
305       null,
306     ],
307     ["Focusable scrollbar is considered interactive", "#scrollbar-2", null],
308     [
309       "Separator that is not focusable is not considered interactive",
310       "#separator-1",
311       null,
312     ],
313     ["Focusable separator is considered interactive", "#separator-2", null],
314     [
315       "Toolbar that is not focusable is not considered interactive",
316       "#toolbar-1",
317       null,
318     ],
319     ["Focusable toolbar is considered interactive", "#toolbar-2", null],
320     [
321       "Menu popup that is not focusable is not considered interactive",
322       "#menu-1",
323       null,
324     ],
325     ["Focusable menu popup is considered interactive", "#menu-2", null],
326     [
327       "Menubar that is not focusable is not considered interactive",
328       "#menubar-1",
329       null,
330     ],
331     ["Focusable menubar is considered interactive", "#menubar-2", null],
332   ];
334   for (const [description, selector, expected] of tests) {
335     info(description);
336     const node = await walker.querySelector(walker.rootNode, selector);
337     const front = await a11yWalker.getAccessibleFor(node);
338     const audit = await front.audit({ types: [KEYBOARD] });
339     Assert.deepEqual(
340       audit[KEYBOARD],
341       expected,
342       `Audit result for ${selector} is correct.`
343     );
344   }
346   info("Text leaf inside a link (jump action is propagated to the text link)");
347   let node = await walker.querySelector(walker.rootNode, "#link-5");
348   let parent = await a11yWalker.getAccessibleFor(node);
349   let front = (await parent.children())[0];
350   let audit = await front.audit({ types: [KEYBOARD] });
351   Assert.deepEqual(
352     audit[KEYBOARD],
353     null,
354     "Text leafs are excluded from semantics rule."
355   );
357   info("Combobox list that is invisible");
358   node = await walker.querySelector(walker.rootNode, "#combobox-1");
359   parent = await a11yWalker.getAccessibleFor(node);
360   front = (await parent.children())[0];
361   audit = await front.audit({ types: [KEYBOARD] });
362   Assert.deepEqual(
363     audit[KEYBOARD],
364     null,
365     "Combobox lists (invisible) are excluded from semantics rule."
366   );
368   await waitForA11yShutdown(parentAccessibility);
369   await target.destroy();
370   gBrowser.removeCurrentTab();