diff options
Diffstat (limited to '')
-rw-r--r-- | devtools/server/tests/browser/browser_accessibility_keyboard_audit.js | 367 |
1 files changed, 367 insertions, 0 deletions
diff --git a/devtools/server/tests/browser/browser_accessibility_keyboard_audit.js b/devtools/server/tests/browser/browser_accessibility_keyboard_audit.js new file mode 100644 index 0000000000..fee9814b6c --- /dev/null +++ b/devtools/server/tests/browser/browser_accessibility_keyboard_audit.js @@ -0,0 +1,367 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +"use strict"; + +/** + * Checks functionality around text label audit for the AccessibleActor. + */ + +const { + accessibility: { + AUDIT_TYPE: { KEYBOARD }, + SCORES: { FAIL, WARNING }, + ISSUE_TYPE: { + [KEYBOARD]: { + FOCUSABLE_NO_SEMANTICS, + FOCUSABLE_POSITIVE_TABINDEX, + INTERACTIVE_NOT_FOCUSABLE, + MOUSE_INTERACTIVE_ONLY, + NO_FOCUS_VISIBLE, + }, + }, + }, +} = require("resource://devtools/shared/constants.js"); + +add_task(async function () { + const { target, walker, parentAccessibility, a11yWalker } = + await initAccessibilityFrontsForUrl( + `${MAIN_DOMAIN}doc_accessibility_keyboard_audit.html` + ); + + const tests = [ + [ + "Focusable element (styled button) with no semantics.", + "#button-1", + { score: WARNING, issue: FOCUSABLE_NO_SEMANTICS }, + ], + ["Element (styled button) with no semantics.", "#button-2", null], + [ + "Container element for out of order focusable element.", + "#input-container", + null, + ], + [ + "Interactive element with focus out of order (-1).", + "#input-1", + { + score: FAIL, + issue: INTERACTIVE_NOT_FOCUSABLE, + }, + ], + [ + "Interactive element with focus out of order (-1) when disabled.", + "#input-2", + null, + ], + ["Interactive element when disabled.", "#input-3", null], + ["Focusable interactive element.", "#input-4", null], + [ + "Interactive accesible (link with no attributes) with no accessible actions.", + "#link-1", + null, + ], + ["Interactive accessible (link with valid href).", "#link-2", null], + ["Interactive accessible (link with # as href).", "#link-3", null], + [ + "Interactive accessible (link with empty string as href).", + "#link-4", + null, + ], + ["Interactive accessible with no tabindex.", "#button-3", null], + [ + "Interactive accessible with -1 tabindex.", + "#button-4", + { + score: FAIL, + issue: INTERACTIVE_NOT_FOCUSABLE, + }, + ], + ["Interactive accessible with 0 tabindex.", "#button-5", null], + [ + "Interactive accessible with 1 tabindex.", + "#button-6", + { score: WARNING, issue: FOCUSABLE_POSITIVE_TABINDEX }, + ], + [ + "Focusable ARIA button with no focus styling.", + "#focusable-1", + { score: WARNING, issue: NO_FOCUS_VISIBLE }, + ], + ["Focusable ARIA button with focus styling.", "#focusable-2", null], + ["Focusable ARIA button with browser styling.", "#focusable-3", null], + [ + "Not focusable, non-semantic element that has a click handler.", + "#mouse-only-1", + { score: FAIL, issue: MOUSE_INTERACTIVE_ONLY }, + ], + [ + "Focusable, non-semantic element that has a click handler.", + "#focusable-4", + { score: WARNING, issue: FOCUSABLE_NO_SEMANTICS }, + ], + [ + "Not focusable, ARIA button that has a click handler.", + "#button-7", + { score: FAIL, issue: INTERACTIVE_NOT_FOCUSABLE }, + ], + ["Focusable, ARIA button with a click handler.", "#button-8", null], + ["Regular image, no keyboard checks should flag an issue.", "#img-1", null], + [ + "Image with a longdesc (accessible will have showlongdesc action).", + "#img-2", + null, + ], + [ + "Clickable image with a longdesc (accessible will have click and showlongdesc actions).", + "#img-3", + { score: FAIL, issue: MOUSE_INTERACTIVE_ONLY }, + ], + [ + "Clickable image (accessible will have click action).", + "#img-4", + { score: FAIL, issue: MOUSE_INTERACTIVE_ONLY }, + ], + ["Focusable button with aria-haspopup.", "#buttonmenu-1", null], + [ + "Not focusable aria button with aria-haspopup.", + "#buttonmenu-2", + { + score: FAIL, + issue: INTERACTIVE_NOT_FOCUSABLE, + }, + ], + ["Focusable checkbox.", "#checkbox-1", null], + ["Focusable select element size > 1", "#listbox-1", null], + ["Focusable select element with one option", "#combobox-1", null], + ["Focusable select element with no options", "#combobox-2", null], + ["Focusable select element with two options", "#combobox-3", null], + [ + "Non-focusable aria combobox with one aria option.", + "#editcombobox-1", + null, + ], + ["Non-focusable aria combobox with no options.", "#editcombobox-2", null], + ["Focusable aria combobox with no options.", "#editcombobox-3", null], + [ + "Non-focusable aria switch", + "#switch-1", + { + score: FAIL, + issue: INTERACTIVE_NOT_FOCUSABLE, + }, + ], + ["Focusable aria switch", "#switch-2", null], + [ + "Combobox list that is visible (has focusable state)", + "#owned_listbox", + null, + ], + [ + "Mouse interactive, label that contains form element (linked)", + "#label-1", + null, + ], + ["Mouse interactive label for external element (linked)", "#label-2", null], + ["Not interactive unlinked label", "#label-3", null], + [ + "Not interactive unlinked label with folloing form element", + "#label-4", + null, + ], + ["Image inside an anchor (href)", "#img-5", null], + ["Image inside an anchor (onmousedown)", "#img-6", null], + ["Image inside an anchor (onclick)", "#img-7", null], + ["Image inside an anchor (onmouseup)", "#img-8", null], + [ + "Section with a collapse action from aria-expanded attribute", + "#section-1", + null, + ], + ["Tabindex -1 should not report an element as focusable", "#main", null], + [ + "Not keyboard focusable element with no focus styling.", + "#not-keyboard-focusable-1", + null, + ], + ["Interactive grid that is not focusable.", "#grid-1", null], + ["Focusable interactive grid.", "#grid-2", null], + [ + "Non interactive ARIA table does not need to be focusable.", + "#table-1", + null, + ], + [ + "Focusable ARIA table does not have interactive semantics", + "#table-2", + { score: "WARNING", issue: "FOCUSABLE_NO_SEMANTICS" }, + ], + ["Non interactive table does not need to be focusable.", "#table-3", null], + [ + "Focusable table does not have interactive semantics", + "#table-4", + { score: "WARNING", issue: "FOCUSABLE_NO_SEMANTICS" }, + ], + [ + "Article that is not focusable is not considered interactive", + "#article-1", + null, + ], + ["Focusable article is considered interactive", "#article-2", null], + [ + "Column header that is not focusable is not considered interactive (ARIA grid)", + "#columnheader-1", + null, + ], + [ + "Column header that is not focusable is not considered interactive (ARIA table)", + "#columnheader-2", + null, + ], + [ + "Column header that is not focusable is not considered interactive (table)", + "#columnheader-3", + null, + ], + [ + "Column header that is focusable is considered interactive (table)", + "#columnheader-4", + null, + ], + [ + "Column header that is not focusable is not considered interactive (table as ARIA grid)", + "#columnheader-5", + null, + ], + [ + "Column header that is focusable is considered interactive (table as ARIA grid)", + "#columnheader-6", + null, + ], + [ + "Row header that is not focusable is not considered interactive", + "#rowheader-1", + null, + ], + [ + "Row header that is not focusable is not considered interactive", + "#rowheader-2", + null, + ], + [ + "Row header that is not focusable is not considered interactive", + "#rowheader-3", + null, + ], + [ + "Row header that is focusable is considered interactive", + "#rowheader-4", + null, + ], + [ + "Row header that is not focusable is not considered interactive (table as ARIA grid)", + "#rowheader-5", + null, + ], + [ + "Row header that is focusable is considered interactive (table as ARIA grid)", + "#rowheader-6", + null, + ], + [ + "Gridcell that is not focusable is not considered interactive (ARIA grid)", + "#gridcell-1", + null, + ], + [ + "Gridcell that is focusable is considered interactive (ARIA grid)", + "#gridcell-2", + null, + ], + [ + "Gridcell that is not focusable is not considered interactive (table as ARIA grid)", + "#gridcell-3", + null, + ], + [ + "Gridcell that is focusable is considered interactive (table as ARIA grid)", + "#gridcell-4", + null, + ], + [ + "Tab list that is not focusable is not considered interactive", + "#tablist-1", + null, + ], + ["Focusable tab list is considered interactive", "#tablist-2", null], + [ + "Scrollbar that is not focusable is not considered interactive", + "#scrollbar-1", + null, + ], + ["Focusable scrollbar is considered interactive", "#scrollbar-2", null], + [ + "Separator that is not focusable is not considered interactive", + "#separator-1", + null, + ], + ["Focusable separator is considered interactive", "#separator-2", null], + [ + "Toolbar that is not focusable is not considered interactive", + "#toolbar-1", + null, + ], + ["Focusable toolbar is considered interactive", "#toolbar-2", null], + [ + "Menu popup that is not focusable is not considered interactive", + "#menu-1", + null, + ], + ["Focusable menu popup is considered interactive", "#menu-2", null], + [ + "Menubar that is not focusable is not considered interactive", + "#menubar-1", + null, + ], + ["Focusable menubar is considered interactive", "#menubar-2", null], + ]; + + for (const [description, selector, expected] of tests) { + info(description); + const node = await walker.querySelector(walker.rootNode, selector); + const front = await a11yWalker.getAccessibleFor(node); + const audit = await front.audit({ types: [KEYBOARD] }); + Assert.deepEqual( + audit[KEYBOARD], + expected, + `Audit result for ${selector} is correct.` + ); + } + + info("Text leaf inside a link (jump action is propagated to the text link)"); + let node = await walker.querySelector(walker.rootNode, "#link-5"); + let parent = await a11yWalker.getAccessibleFor(node); + let front = (await parent.children())[0]; + let audit = await front.audit({ types: [KEYBOARD] }); + Assert.deepEqual( + audit[KEYBOARD], + null, + "Text leafs are excluded from semantics rule." + ); + + info("Combobox list that is invisible"); + node = await walker.querySelector(walker.rootNode, "#combobox-1"); + parent = await a11yWalker.getAccessibleFor(node); + front = (await parent.children())[0]; + audit = await front.audit({ types: [KEYBOARD] }); + Assert.deepEqual( + audit[KEYBOARD], + null, + "Combobox lists (invisible) are excluded from semantics rule." + ); + + await waitForA11yShutdown(parentAccessibility); + await target.destroy(); + gBrowser.removeCurrentTab(); +}); |