diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-19 01:47:29 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-19 01:47:29 +0000 |
commit | 0ebf5bdf043a27fd3dfb7f92e0cb63d88954c44d (patch) | |
tree | a31f07c9bcca9d56ce61e9a1ffd30ef350d513aa /testing/web-platform/tests/css/css-toggle/toggle-aria-roles.tentative.html | |
parent | Initial commit. (diff) | |
download | firefox-esr-0ebf5bdf043a27fd3dfb7f92e0cb63d88954c44d.tar.xz firefox-esr-0ebf5bdf043a27fd3dfb7f92e0cb63d88954c44d.zip |
Adding upstream version 115.8.0esr.upstream/115.8.0esr
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'testing/web-platform/tests/css/css-toggle/toggle-aria-roles.tentative.html')
-rw-r--r-- | testing/web-platform/tests/css/css-toggle/toggle-aria-roles.tentative.html | 453 |
1 files changed, 453 insertions, 0 deletions
diff --git a/testing/web-platform/tests/css/css-toggle/toggle-aria-roles.tentative.html b/testing/web-platform/tests/css/css-toggle/toggle-aria-roles.tentative.html new file mode 100644 index 0000000000..9ba545f21a --- /dev/null +++ b/testing/web-platform/tests/css/css-toggle/toggle-aria-roles.tentative.html @@ -0,0 +1,453 @@ +<!DOCTYPE HTML> +<meta charset="UTF-8"> +<title>CSS Toggles: ARIA roles and inferred keyboard handling</title> +<link rel="author" title="L. David Baron" href="https://dbaron.org/"> +<link rel="author" title="Google" href="http://www.google.com/"> +<link rel="help" href="https://tabatkins.github.io/css-toggle/"> +<link rel="help" href="https://github.com/tabatkins/css-toggle/issues/41"> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<script src="/resources/testdriver.js"></script> +<script src="/resources/testdriver-vendor.js"></script> +<script src="support/toggle-helpers.js"></script> +<style> + +/* for send_keys */ +div { min-height: 10px } + +</style> + +<body> + +<div id="container"></div> +<script> + +let aria_role_tests = [ + // Markup to create the test assertions: + // data-expected-role: The expected aria role for this element. + // data-expected-trigger-keys: When present, indicates that keyboard events + // should be tested on this element, and indicates the keys + // (space-separated) that are expected to toggle the toggle. + // data-expected-arrows-between-children: When present, indicates + // that arrow keys should navigate between the children of this + // element that have the given role. + // + // Helper markup to create more markup: + // class=group: group the group with the toggle-group property + // class=group-self: same, but with the self keyword (narrow scope) + // class=root: create a test-role toggle with the toggle-root property + // class=root-group: same, but with the 'group' keyword + // class=root-self: same, but with the 'self' keyword + // class=trigger: toggle-trigger to activate test-role toggle + // class=visibility: toggle-visibility connected to test-role toggle + ` + <div></div> + `, + ` + <div class="root"> + <div></div> + </div> + `, + ` + <div class="root trigger" data-expected-role="checkbox"></div> + `, + // Test that ARIA attributes override the toggle inference: + ` + <div class="root trigger" role="link" data-expected-role="link"></div> + `, + ` + <div class="root"> + <div class="trigger" data-expected-role="button"></div> + </div> + `, + + // Radios and radio groups: + ` + <div class="group" data-expected-role="radiogroup"> + <div class="root-group trigger" data-expected-role="radio" data-expected-trigger-keys="Space"></div> + </div> + `, + ` + <div class="group" data-expected-role="radiogroup" data-expected-arrows-between-children="radio"> + <div class="root-group trigger" data-expected-role="radio" data-expected-trigger-keys="Space"></div> + <div class="root-group trigger" data-expected-role="radio" data-expected-trigger-keys="Space"></div> + </div> + `, + ` + <div> + <div class="root-group trigger" data-expected-role="radio"></div> + </div> + `, + ` + <div style="toggle-group: another-group"> + <div class="root-group trigger" data-expected-role="radio"></div> + </div> + `, + ` + <div style="toggle-group: another-group, test-role, third-group" data-expected-role="radiogroup"> + <div class="root-group trigger" data-expected-role="radio"></div> + </div> + `, + + + // Checkboxes and checkbox groups: + ` + <div> + <div class="root trigger" data-expected-role="checkbox" data-expected-trigger-keys="Space"></div> + </div> + `, + // TODO(https://crbug.com/1250716): This is a checkbox group... but we + // can't distinguish that with current ARIA roles. + ` + <div data-expected-arrows-between-children="checkbox"> + <div class="root trigger" data-expected-role="checkbox" data-expected-trigger-keys="Space"></div> + <div class="root trigger" data-expected-role="checkbox" data-expected-trigger-keys="Space"></div> + </div> + `, + + // Disclosure: + // TODO(https://crbug.com/1250716): This is a disclosure... but how is + // it possible to distinguish with ARIA roles (compare to next test!)? + ` + <div class="root"> + <div class="trigger" data-expected-role="button" data-expected-trigger-keys="Space Enter"></div> + <div class="visibility"></div> + </div> + `, + // This is not a disclosure because it has a toggle-group. + ` + <div class="root-group"> + <div class="trigger" data-expected-role="button" data-expected-trigger-keys="Space Enter"></div> + <div class="visibility"></div> + </div> + `, + // This is button with popup (absolute positioning) + // TODO(https://crbug.com/1250716): This test doesn't actually + // distinguish this from disclosure because the internal kPopUpButton + // role maps to "button" in kReverseRoles in ax_object.cc. + ` + <div class="root"> + <div class="trigger" data-expected-role="button"></div> + <div class="visibility" style="position: absolute"></div> + </div> + `, + // This is button with popup (fixed positioning) + // TODO(https://crbug.com/1250716): This test doesn't actually + // distinguish this from disclosure because the internal kPopUpButton + // role maps to "button" in kReverseRoles in ax_object.cc. + ` + <div class="root"> + <div class="trigger" data-expected-role="button" data-expected-trigger-keys="Space Enter"></div> + <div class="visibility" style="position: fixed"></div> + </div> + `, + // This is button with popup (popover) + // TODO(https://crbug.com/1250716): This test doesn't actually + // distinguish this from disclosure because the internal kPopUpButton + // role maps to "button" in kReverseRoles in ax_object.cc. + ` + <div class="root"> + <div class="trigger" data-expected-role="button" data-expected-trigger-keys="Space Enter"></div> + <div class="visibility" popover="auto"></div> + </div> + `, + // This is disclosure (NOT button with popup) (sticky positioning) + ` + <div class="root"> + <div class="trigger" data-expected-role="button" data-expected-trigger-keys="Space Enter"></div> + <div class="visibility" style="position: sticky"></div> + </div> + `, + + // Accordion: + ` + <div class="group"> + <div class="root-group" data-expected-role="region"> + <div class="trigger" data-expected-role="button"></div> + <div class="visibility"></div> + </div> + <div class="root-group" data-expected-role="region"> + <div class="trigger" data-expected-role="button"></div> + <div class="visibility"></div> + </div> + </div> + `, + // Not accordion because of other siblings: + ` + <div class="group"> + <div class="root-group"> + <div class="trigger" data-expected-role="button"></div> + <div class="visibility"></div> + </div> + <div class="root-group"> + <div class="trigger" data-expected-role="button"></div> + <div class="visibility"></div> + </div> + <div></div> + <div></div> + <div></div> + </div> + `, + + // Tree: + // TODO(https://crbug.com/1250716): This should probably also work + // with the toggles on the <button>! + // TODO(https://crbug.com/1250716): This should probably mark the + // non-interactive items as treeitem as well! + // TODO(https://crbug.com/1250716): Do the elements getting the roles + // here make sense? + // TODO(https://crbug.com/1250716): The requirement for having + // multiple disclosure-ish children to qualify as accordion-ish + // probably doesn't make sense here. The test below is basically the + // minimal example that gets detected as a tree, but simpler things + // definitely should be! + // TODO(https://crbug.com/1250716): The inner parts of the tree should + // also be getting tree roles! + ` + <ul data-expected-role="tree"> + <li class="root-self" data-expected-role="group"> + <button class="trigger" data-expected-role="treeitem"></button> + <ul class="visibility" data-expected-role="list"> + <li>item</li> + <li class="root-self"> + <button class="trigger" data-expected-role="button"></button> + <ul class="visibility" data-expected-role="list"> + <li>item</li> + <li>item</li> + </ul> + </li> + <li class="root-self"> + <button class="trigger" data-expected-role="button"></button> + <ul class="visibility" data-expected-role="list"> + <li>item</li> + <li>item</li> + </ul> + </li> + </ul> + </li> + <li class="root-self" data-expected-role="group"> + <button class="trigger" data-expected-role="treeitem"></button> + <ul class="visibility" data-expected-role="list"> + <li class="root-self"> + <button class="trigger" data-expected-role="button"></button> + <ul class="visibility" data-expected-role="list"> + <li>item</li> + <li>item</li> + </ul> + </li> + <li class="root-self"> + <button class="trigger" data-expected-role="button"></button> + <ul class="visibility" data-expected-role="list"> + <li>item</li> + <li>item</li> + </ul> + </li> + </ul> + </li> + </ul> + `, + + // Tabs: + ` + <section class="group" data-expected-role="tablist" data-expected-arrows-between-children="tab"> + <h1 class="root-group trigger" data-expected-role="tab" data-expected-trigger-keys="Space Enter"></h1> + <div class="visibility" data-expected-role="tabpanel"></div> + <h1 class="root-group trigger" data-expected-role="tab" data-expected-trigger-keys="Space Enter"></h1> + <div class="visibility" data-expected-role="tabpanel"></div> + <h1 class="root-group trigger" data-expected-role="tab" data-expected-trigger-keys="Space Enter"></h1> + <div class="visibility" data-expected-role="tabpanel"></div> + </section> + `, + ` + <section class="group" data-expected-role="tablist"> + <h1 class="root-group trigger" data-expected-role="tab"></h1> + <div class="visibility" data-expected-role="tabpanel"></div> + <h1 class="root-group trigger" data-expected-role="tab"></h1> + <div class="visibility" data-expected-role="tabpanel"></div> + <div></div> + </section> + `, + ` + <section class="group" data-expected-role="tablist"> + <h1 class="root-group trigger" data-expected-role="tab"></h1> + <div class="visibility" data-expected-role="tabpanel"></div> + <h1 class="root-group trigger" data-expected-role="tab"></h1> + <div class="visibility" data-expected-role="tabpanel"></div> + <h1 style="toggle-root: other-toggle; toggle-trigger: other-toggle" data-expected-role="checkbox"></h1> + </section> + `, + ` + <section class="group" data-expected-role="tablist"> + <h1 class="root-group trigger" data-expected-role="tab"></h1> + <div class="visibility" data-expected-role="tabpanel"></div> + <h1 class="root-group trigger" data-expected-role="tab"></h1> + <div class="visibility" data-expected-role="tabpanel"></div> + <h1 style="toggle-root: other-toggle; toggle-trigger: other-toggle" data-expected-role="button"></h1> + <div style="toggle-visibility: toggle other-toggle"></div> + </section> + `, + // TODO(https://crbug.com/758089): The expected role for the <section> + // should be generic rather than null! + ` + <section class="group" data-expected-role="null"> + <h1 class="root-group trigger" data-expected-role="button"></h1> + <div class="visibility"></div> + <h1 class="root-group trigger" data-expected-role="button"></h1> + <div class="visibility"></div> + <div></div> + <div></div> + <div></div> + <div></div> + </section> + `, + ` + <section class="group" data-expected-role="radiogroup"> + <h1 class="root-group trigger" data-expected-role="radio"></h1> + <h1 class="root-group trigger" data-expected-role="radio"></h1> + <div></div> + <div></div> + <div></div> + <div></div> + </section> + `, +]; + +function find_toggle_in_scope(e) { + let allow_self = true; + while (e) { + let toggle = e.toggles.get("test-role"); + if (toggle && (allow_self || toggle.scope == "wide")) + return toggle; + let sibling = e.previousElementSibling; + if (sibling) { + e = sibling; + allow_self = false; + } + e = e.parentNode; + allow_self = true; + } + return null; +} + +for (let t of aria_role_tests) { + promise_test(async function() { + container.innerHTML = t; + + for (let e of container.querySelectorAll('.group')) { + e.style.toggleGroup = "test-role"; + } + for (let e of container.querySelectorAll('.group-self')) { + e.style.toggleGroup = "test-role self"; + } + for (let e of container.querySelectorAll('.root')) { + e.style.toggleRoot = "test-role"; + } + for (let e of container.querySelectorAll('.root-group')) { + e.style.toggleRoot = "test-role group"; + } + for (let e of container.querySelectorAll('.root-self')) { + e.style.toggleRoot = "test-role self"; + } + for (let e of container.querySelectorAll('.trigger')) { + e.style.toggleTrigger = "test-role"; + } + for (let e of container.querySelectorAll('.visibility')) { + e.style.toggleVisibility = "toggle test-role"; + } + + for (let e of container.querySelectorAll('.root, .root-nogroup')) { + await wait_for_toggle_creation(e); + } + + let count = 0; + for (let e of container.querySelectorAll("*")) { + if (e == container) + continue; + + let expected_role = "generic"; + if (e.hasAttribute("data-expected-role")) { + expected_role = e.getAttribute("data-expected-role"); + // TODO(https://crbug.com/758089): See above regarding <section>; + // this null handling should eventually be removed. + if (expected_role === "null") { + expected_role = null; + } + } + ++count; + // NOTE: This relies on Element.computedRole, which is an + // experimental feature behind the ComputedAccessibilityInfo flag + // in blink. + assert_equals(e.computedRole, expected_role, `role on ${e.tagName} element (#${count})`); + } + + if (container.querySelector("[data-expected-arrows-between-children], [data-expected-trigger-keys]")) { + // We should do keyboard tests for this test. + for (let e of container.querySelectorAll("*")) { + if (e == container) + continue; + + let arrows = e.parentNode.hasAttribute("data-expected-arrows-between-children") && e.getAttribute("data-expected-role") == e.parentNode.getAttribute("data-expected-arrows-between-children"); + let trigger_keys = []; + if (e.hasAttribute("data-expected-trigger-keys")) { + trigger_keys = e.getAttribute("data-expected-trigger-keys").split(" "); + } + + if (!e.classList.contains("trigger")) { + // It is a bug in the test to have expected key handling for elements + // that are not toggle triggers. + assert_false(arrows); + assert_equals(trigger_keys.length, 0); + continue; + } + + // Test handling of space, enter, and all arrows, and check that + // it matches expectations. + let keys_to_test = { + "Enter": "\uE007", + // better known as " ", but "Space" in this test. + // https://w3c.github.io/webdriver/#keyboard-actions says + // "\uE00D" but that doesn't work. + "Space": " ", + "ArrowLeft": "\uE012", + "ArrowUp": "\uE013", + "ArrowRight": "\uE014", + "ArrowDown": "\uE015", + }; + for (let key in keys_to_test) { + let toggle = find_toggle_in_scope(e); + let expected_state = toggle.valueAsNumber; + e.focus(); + let expected_focus = e; + assert_equals(document.activeElement, expected_focus, `focus before ${key} key`); + await test_driver.send_keys(document.body, keys_to_test[key]); + if (trigger_keys.includes(key)) { + expected_state = expected_state ? 0 : 1; + } + if (key.startsWith("Arrow")) { + if (arrows) { + let role = e.parentNode.getAttribute("data-expected-arrows-between-children"); + let direction; + if (key == "ArrowLeft" || key == "ArrowUp") { + direction = "previousElementSibling"; + } else { + direction = "nextElementSibling"; + } + let new_element = e; + while ((new_element = new_element[direction])) { + if (new_element.getAttribute("data-expected-role") == role) + break; + } + if (new_element) + expected_focus = new_element; + } + } + assert_equals(toggle.valueAsNumber, expected_state, `state after ${key} key`); + assert_equals(document.activeElement, expected_focus, `focus after ${key} key`); + } + } + } + + }, `aria role and key handling test: ${t}`); +} + +</script> |