diff options
Diffstat (limited to 'accessible/tests')
39 files changed, 1128 insertions, 336 deletions
diff --git a/accessible/tests/browser/.eslintrc.js b/accessible/tests/browser/.eslintrc.js index 528797cb91..96c0859468 100644 --- a/accessible/tests/browser/.eslintrc.js +++ b/accessible/tests/browser/.eslintrc.js @@ -18,7 +18,7 @@ module.exports = { "no-proto": "error", "no-return-assign": "error", "no-shadow": "error", - "no-unused-vars": ["error", { vars: "all", args: "none" }], + "no-unused-vars": ["error", { vars: "all", argsIgnorePattern: "^_" }], "one-var": ["error", "never"], radix: "error", strict: ["error", "global"], diff --git a/accessible/tests/browser/bounds/browser.toml b/accessible/tests/browser/bounds/browser.toml index da1fe37a1e..c4c421cdeb 100644 --- a/accessible/tests/browser/bounds/browser.toml +++ b/accessible/tests/browser/bounds/browser.toml @@ -3,7 +3,6 @@ subsuite = "a11y" support-files = [ "head.js", "!/accessible/tests/browser/shared-head.js", - "!/accessible/tests/browser/*.jsm", "!/accessible/tests/mochitest/*.js", "!/accessible/tests/mochitest/letters.gif", ] diff --git a/accessible/tests/browser/e10s/browser.toml b/accessible/tests/browser/e10s/browser.toml index 914f839993..dff9b1c712 100644 --- a/accessible/tests/browser/e10s/browser.toml +++ b/accessible/tests/browser/e10s/browser.toml @@ -10,7 +10,6 @@ support-files = [ "doc_treeupdate_whitespace.html", "fonts/Ahem.sjs", "!/accessible/tests/browser/shared-head.js", - "!/accessible/tests/browser/*.jsm", "!/accessible/tests/mochitest/*.js", "!/accessible/tests/mochitest/events/slow_image.sjs", "!/accessible/tests/mochitest/letters.gif", diff --git a/accessible/tests/browser/e10s/browser_aria_activedescendant.js b/accessible/tests/browser/e10s/browser_aria_activedescendant.js index f58c5aab39..fadda0f964 100644 --- a/accessible/tests/browser/e10s/browser_aria_activedescendant.js +++ b/accessible/tests/browser/e10s/browser_aria_activedescendant.js @@ -277,7 +277,7 @@ async function basicListboxTest(browser, elementReflection) { addAccessibleTask( LISTBOX_MARKUP, - async function (browser, docAcc) { + async function (browser) { info("Test aria-activedescendant content attribute"); await basicListboxTest(browser, false); @@ -303,7 +303,7 @@ addAccessibleTask( addAccessibleTask( LISTBOX_MARKUP, - async function (browser, docAcc) { + async function (browser) { info("Test ariaActiveDescendantElement element reflection"); await basicListboxTest(browser, true); }, @@ -316,7 +316,7 @@ addAccessibleTask( <div role="listbox"> <div role="option" id="activedesc_nondesc_option">option</div> </div>`, - async function (browser, docAcc) { + async function (browser) { info("Test aria-activedescendant non-descendant"); await synthFocus( browser, @@ -348,7 +348,7 @@ addAccessibleTask( item.setAttribute("role", "option"); listbox.appendChild(item); </script>`, - async function (browser, docAcc) { + async function (browser) { info("Test aria-activedescendant in shadow root"); // We want to retrieve elements using their IDs inside the shadow root, so // we define a custom get element by ID method that our utility functions @@ -448,7 +448,7 @@ customElements.define("custom-listbox", } ); </script>`, - async function (browser, docAcc) { + async function (browser) { await synthFocus(browser, "custom-listbox1", "l1_3"); let evtProm = Promise.all([ diff --git a/accessible/tests/browser/e10s/browser_caching_value.js b/accessible/tests/browser/e10s/browser_caching_value.js index 2b968b5948..926110199e 100644 --- a/accessible/tests/browser/e10s/browser_caching_value.js +++ b/accessible/tests/browser/e10s/browser_caching_value.js @@ -46,16 +46,6 @@ const valueTests = [ expected: ["5", 5, 0, 7, 0], }, { - desc: "Value should change when currentValue is called", - id: "slider", - async action(browser, acc) { - acc.QueryInterface(nsIAccessibleValue); - acc.currentValue = 4; - }, - waitFor: EVENT_VALUE_CHANGE, - expected: ["4", 4, 0, 7, 0], - }, - { desc: "Value should change when @aria-valuenow is updated", id: "slider", attrs: [ diff --git a/accessible/tests/browser/events/browser.toml b/accessible/tests/browser/events/browser.toml index 7ec3c3621a..ffbb96cfbb 100644 --- a/accessible/tests/browser/events/browser.toml +++ b/accessible/tests/browser/events/browser.toml @@ -4,12 +4,13 @@ support-files = [ "head.js", "!/accessible/tests/browser/shared-head.js", "!/accessible/tests/mochitest/*.js", - "!/accessible/tests/browser/*.jsm", ] prefs = ["javascript.options.asyncstack_capture_debuggee_only=false"] ["browser_alert.js"] +["browser_content_prompt.js"] + ["browser_test_A11yUtils_announce.js"] ["browser_test_caret_move_granularity.js"] diff --git a/accessible/tests/browser/events/browser_content_prompt.js b/accessible/tests/browser/events/browser_content_prompt.js new file mode 100644 index 0000000000..7677c0258a --- /dev/null +++ b/accessible/tests/browser/events/browser_content_prompt.js @@ -0,0 +1,48 @@ +/* Any copyright is dedicated to the Public Domain. + https://creativecommons.org/publicdomain/zero/1.0/ */ + +"use strict"; + +// Want to test relations. +/* import-globals-from ../../mochitest/name.js */ +/* import-globals-from ../../mochitest/relations.js */ +/* import-globals-from ../../mochitest/role.js */ +loadScripts( + { name: "relations.js", dir: MOCHITESTS_DIR }, + { name: "name.js", dir: MOCHITESTS_DIR }, + { name: "role.js", dir: MOCHITESTS_DIR } +); + +addAccessibleTask(``, async function (browser) { + info("Showing alert"); + let shown = waitForEvent( + EVENT_SHOW, + evt => evt.accessible.role == ROLE_INTERNAL_FRAME + ); + // Let's make sure the dialog content gets focus. + // On macOS, we unfortunately focus the label. We focus the OK button on + // all other platforms. See https://phabricator.services.mozilla.com/D204908 + // for more discussion. + let expectedRole = + AppConstants.platform == "macosx" ? ROLE_LABEL : ROLE_PUSHBUTTON; + let focused = waitForEvent(EVENT_FOCUS, evt => { + return evt.accessible.role == expectedRole; + }); + await invokeContentTask(browser, [], () => { + // Use setTimeout to avoid blocking the return of the content task + // on the alert, which is otherwise synchronous. + content.setTimeout(() => content.alert("test"), 0); + }); + const frame = (await shown).accessible; + const focusedEl = (await focused).accessible; + ok(true, "Dialog shown and something got focused"); + let dialog = getAccessible(focusedEl.DOMNode.ownerDocument); + testRole(dialog, ROLE_DIALOG); + let infoBody = focusedEl.DOMNode.ownerDocument.getElementById("infoBody"); + testRelation(dialog, RELATION_DESCRIBED_BY, infoBody); + testDescr(dialog, "test "); + info("Dismissing alert"); + let hidden = waitForEvent(EVENT_HIDE, frame); + EventUtils.synthesizeKey("KEY_Escape", {}, frame.DOMNode.contentWindow); + await hidden; +}); diff --git a/accessible/tests/browser/fission/browser.toml b/accessible/tests/browser/fission/browser.toml index 0332573db9..f795ec6b3d 100644 --- a/accessible/tests/browser/fission/browser.toml +++ b/accessible/tests/browser/fission/browser.toml @@ -3,7 +3,6 @@ subsuite = "a11y" support-files = [ "head.js", "!/accessible/tests/browser/shared-head.js", - "!/accessible/tests/browser/*.jsm", "!/accessible/tests/mochitest/*.js", ] prefs = ["javascript.options.asyncstack_capture_debuggee_only=false"] diff --git a/accessible/tests/browser/hittest/browser.toml b/accessible/tests/browser/hittest/browser.toml index 7f82a6ff49..894bf05c39 100644 --- a/accessible/tests/browser/hittest/browser.toml +++ b/accessible/tests/browser/hittest/browser.toml @@ -3,7 +3,6 @@ subsuite = "a11y" support-files = [ "head.js", "!/accessible/tests/browser/shared-head.js", - "!/accessible/tests/browser/*.jsm", "!/accessible/tests/mochitest/*.js", "!/accessible/tests/mochitest/letters.gif", ] diff --git a/accessible/tests/browser/mac/browser.toml b/accessible/tests/browser/mac/browser.toml index b180a42ab7..227575fb4d 100644 --- a/accessible/tests/browser/mac/browser.toml +++ b/accessible/tests/browser/mac/browser.toml @@ -9,7 +9,6 @@ support-files = [ "doc_menulist.xhtml", "doc_tree.xhtml", "!/accessible/tests/browser/shared-head.js", - "!/accessible/tests/browser/*.jsm", "!/accessible/tests/mochitest/*.js", "!/accessible/tests/mochitest/letters.gif", "!/accessible/tests/mochitest/moz.png", @@ -29,6 +28,8 @@ https_first_disabled = true ["browser_aria_haspopup.js"] +["browser_aria_placeholder.js"] + ["browser_aria_setsize.js"] ["browser_attributed_text.js"] diff --git a/accessible/tests/browser/mac/browser_aria_placeholder.js b/accessible/tests/browser/mac/browser_aria_placeholder.js new file mode 100644 index 0000000000..e5102fd093 --- /dev/null +++ b/accessible/tests/browser/mac/browser_aria_placeholder.js @@ -0,0 +1,70 @@ +/* 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"; + +/** + * Test that inputs with placeholder text expose it via AXPlaceholderValue and + * correctly _avoid_ exposing it via AXTItle, AXValue, or AXDescription. Verify AXPlaceholderValue is not exposed when the placeholder is used as the name. + */ +addAccessibleTask( + ` + <input id="input" placeholder="Name"><br> + <label for="input2">Enter Name</label><input id="input2" placeholder="Name" value="Elmer Fudd"> + `, + (browser, accDoc) => { + let input = getNativeInterface(accDoc, "input"); + let input2 = getNativeInterface(accDoc, "input2"); + + is( + input.getAttributeValue("AXPlaceholderValue"), + null, + "Placeholder is used as name, so no AXPlaceholderValue is stored." + ); + is(input.getAttributeValue("AXDescription"), "Name"); + is(input.getAttributeValue("AXTitle"), "", "Correct title"); + is(input.getAttributeValue("AXValue"), "", "Correct value"); + + is( + input2.getAttributeValue("AXPlaceholderValue"), + "Name", + "Correct placeholder value in presence of value" + ); + is( + input2.getAttributeValue("AXDescription"), + "Enter Name", + "Correct label" + ); + is(input2.getAttributeValue("AXTitle"), "", "Correct title"); + is(input2.getAttributeValue("AXValue"), "Elmer Fudd", "Correct value"); + } +); + +/** + * Test that aria-placeholder gets exposed via AXPlaceholderValue and correctly + * contributes to AXValue (but not title or description). + */ +addAccessibleTask( + ` + <span id="date-of-birth">Birthday</span> + <div + id="bday" + contenteditable + role="textbox" + aria-labelledby="date-of-birth" + aria-placeholder="MM-DD-YYYY">MM-DD-YYYY</div> + `, + (browser, accDoc) => { + let bday = getNativeInterface(accDoc, "bday"); + + is( + bday.getAttributeValue("AXPlaceholderValue"), + "MM-DD-YYYY", + "Correct placeholder value" + ); + is(bday.getAttributeValue("AXDescription"), "Birthday", "Correct label"); + is(bday.getAttributeValue("AXTitle"), "", "Correct title"); + is(bday.getAttributeValue("AXValue"), "MM-DD-YYYY", "Correct value"); + } +); diff --git a/accessible/tests/browser/mac/browser_roles_elements.js b/accessible/tests/browser/mac/browser_roles_elements.js index b6049e7afd..65caf308c4 100644 --- a/accessible/tests/browser/mac/browser_roles_elements.js +++ b/accessible/tests/browser/mac/browser_roles_elements.js @@ -73,8 +73,8 @@ addAccessibleTask( <div id="switch" role="switch"></div> <div id="timer" role="timer"></div> <div id="tooltip" role="tooltip"></div> - <input type="radio" role="menuitemradio" id="menuitemradio"> - <input type="checkbox" role="menuitemcheckbox" id="menuitemcheckbox"> + <div role="menu"><input type="radio" role="menuitemradio" id="menuitemradio"></div> + <div role="menu"><input type="checkbox" role="menuitemcheckbox" id="menuitemcheckbox"></div> <input type="datetime-local" id="datetime"> <!-- text entries --> diff --git a/accessible/tests/browser/mac/browser_selectables.js b/accessible/tests/browser/mac/browser_selectables.js index af88c2e136..cc489e566d 100644 --- a/accessible/tests/browser/mac/browser_selectables.js +++ b/accessible/tests/browser/mac/browser_selectables.js @@ -300,9 +300,6 @@ addAccessibleTask( async (browser, accDoc) => { let select = getNativeInterface(accDoc, "select"); let one = getNativeInterface(accDoc, "one"); - let two = getNativeInterface(accDoc, "two"); - let three = getNativeInterface(accDoc, "three"); - let four = getNativeInterface(accDoc, "four"); is( select.getAttributeValue("AXTitle"), @@ -339,25 +336,5 @@ addAccessibleTask( }); await evt; is(select.getAttributeValue("AXSelectedChildren").length, 0); - evt = waitForMacEvent("AXSelectedChildrenChanged"); - three.setAttributeValue("AXSelected", true); - await evt; - is(select.getAttributeValue("AXSelectedChildren").length, 1); - ok(getSelectedIds(select).includes("three"), "'three' is selected"); - evt = waitForMacEvent("AXSelectedChildrenChanged"); - select.setAttributeValue("AXSelectedChildren", [one, two]); - await evt; - await untilCacheOk(() => { - let ids = getSelectedIds(select); - return ids[0] == "one" && ids[1] == "two"; - }, "Got correct selected children"); - - evt = waitForMacEvent("AXSelectedChildrenChanged"); - select.setAttributeValue("AXSelectedChildren", [three, two, four]); - await evt; - await untilCacheOk(() => { - let ids = getSelectedIds(select); - return ids[0] == "two" && ids[1] == "three"; - }, "Got correct selected children"); } ); diff --git a/accessible/tests/browser/role/browser_computedARIARole.js b/accessible/tests/browser/role/browser_computedARIARole.js index 50cfe43c98..a87d0a0eae 100644 --- a/accessible/tests/browser/role/browser_computedARIARole.js +++ b/accessible/tests/browser/role/browser_computedARIARole.js @@ -14,7 +14,9 @@ addAccessibleTask( <div id="ariaDirectory" role="directory">ARIA directory</div> <div id="ariaAlertdialog" role="alertdialog">ARIA alertdialog</div> <div id="ariaFeed" role="feed">ARIA feed</div> -<div id="ariaRowgroup" role="rowgroup">ARIA rowgroup</div> +<div role="table"> + <div id="ariaRowgroup" role="rowgroup">ARIA rowgroup</div> +</div> <div id="ariaSearchbox" role="searchbox">ARIA searchbox</div> <div id="ariaUnknown" role="unknown">unknown ARIA role</div> <button id="htmlButton">HTML button</button> diff --git a/accessible/tests/browser/scroll/browser.toml b/accessible/tests/browser/scroll/browser.toml index ef637fe9a5..390e07db8e 100644 --- a/accessible/tests/browser/scroll/browser.toml +++ b/accessible/tests/browser/scroll/browser.toml @@ -3,7 +3,6 @@ subsuite = "a11y" support-files = [ "head.js", "!/accessible/tests/browser/shared-head.js", - "!/accessible/tests/browser/*.jsm", "!/accessible/tests/mochitest/*.js", ] prefs = ["javascript.options.asyncstack_capture_debuggee_only=false"] diff --git a/accessible/tests/browser/selectable/browser.toml b/accessible/tests/browser/selectable/browser.toml index 38a13c25f4..144555b6a0 100644 --- a/accessible/tests/browser/selectable/browser.toml +++ b/accessible/tests/browser/selectable/browser.toml @@ -3,7 +3,6 @@ subsuite = "a11y" support-files = [ "head.js", "!/accessible/tests/browser/shared-head.js", - "!/accessible/tests/browser/*.jsm", "!/accessible/tests/mochitest/*.js", ] prefs = ["javascript.options.asyncstack_capture_debuggee_only=false"] diff --git a/accessible/tests/browser/selectable/browser_test_aria_select.js b/accessible/tests/browser/selectable/browser_test_aria_select.js index f52603d1cb..dbc36956f8 100644 --- a/accessible/tests/browser/selectable/browser_test_aria_select.js +++ b/accessible/tests/browser/selectable/browser_test_aria_select.js @@ -72,16 +72,16 @@ addAccessibleTask( // role="tablist" aria-multiselectable addAccessibleTask( `<div role="tablist" id="tablist" aria-multiselectable="true"> - <div role="tab" id="tab_multi1">tab1</div> + <div role="tab" id="tab_multi1" aria-selected="true">tab1</div> <div role="tab" id="tab_multi2">tab2</div> + <div role="tab" id="tab_multi3" aria-selected="true">tab3</div> </div>`, async function (browser, docAcc) { info('role="tablist" aria-multiselectable'); let tablist = findAccessibleChildByID(docAcc, "tablist", [ nsIAccessibleSelectable, ]); - - await testMultiSelectable(tablist, ["tab_multi1", "tab_multi2"]); + testSelectableSelection(tablist, ["tab_multi1", "tab_multi3"]); }, { chrome: true, @@ -95,16 +95,16 @@ addAccessibleTask( // role="listbox" aria-multiselectable addAccessibleTask( `<div role="listbox" id="listbox" aria-multiselectable="true"> - <div role="option" id="listbox2_item1">item1</div> + <div role="option" id="listbox2_item1" aria-selected="true">item1</div> <div role="option" id="listbox2_item2">item2</div> + <div role="option" id="listbox2_item3" aria-selected="true">item2</div> </div>`, async function (browser, docAcc) { info('role="listbox" aria-multiselectable'); let listbox = findAccessibleChildByID(docAcc, "listbox", [ nsIAccessibleSelectable, ]); - - await testMultiSelectable(listbox, ["listbox2_item1", "listbox2_item2"]); + testSelectableSelection(listbox, ["listbox2_item1", "listbox2_item3"]); }, { chrome: true, @@ -122,7 +122,7 @@ addAccessibleTask( <thead> <tr> <th tabindex="-1" role="columnheader" id="grid_colhead1" - style="width:6em">Entry #</th> + style="width:6em" aria-selected="true">Entry #</th> <th tabindex="-1" role="columnheader" id="grid_colhead2" style="width:10em">Date</th> <th tabindex="-1" role="columnheader" id="grid_colhead3" @@ -134,7 +134,7 @@ addAccessibleTask( <td tabindex="-1" role="rowheader" id="grid_rowhead" aria-readonly="true">1</td> <td tabindex="-1" role="gridcell" id="grid_cell1" - aria-selected="false">03/14/05</td> + aria-selected="true">03/14/05</td> <td tabindex="-1" role="gridcell" id="grid_cell2" aria-selected="false">Conference Fee</td> </tr> @@ -145,15 +145,7 @@ addAccessibleTask( let grid = findAccessibleChildByID(docAcc, "grid", [ nsIAccessibleSelectable, ]); - - await testMultiSelectable(grid, [ - "grid_colhead1", - "grid_colhead2", - "grid_colhead3", - "grid_rowhead", - "grid_cell1", - "grid_cell2", - ]); + testSelectableSelection(grid, ["grid_colhead1", "grid_cell1"]); }, { chrome: true, diff --git a/accessible/tests/browser/states/browser.toml b/accessible/tests/browser/states/browser.toml index fe29597d27..6b2d20ae14 100644 --- a/accessible/tests/browser/states/browser.toml +++ b/accessible/tests/browser/states/browser.toml @@ -4,7 +4,6 @@ support-files = [ "head.js", "!/accessible/tests/browser/shared-head.js", "!/accessible/tests/mochitest/*.js", - "!/accessible/tests/browser/*.jsm", ] prefs = ["javascript.options.asyncstack_capture_debuggee_only=false"] diff --git a/accessible/tests/browser/text/browser.toml b/accessible/tests/browser/text/browser.toml index c04531b126..4bc64866fc 100644 --- a/accessible/tests/browser/text/browser.toml +++ b/accessible/tests/browser/text/browser.toml @@ -3,7 +3,6 @@ subsuite = "a11y" support-files = [ "head.js", "!/accessible/tests/browser/shared-head.js", - "!/accessible/tests/browser/*.jsm", "!/accessible/tests/mochitest/*.js", ] prefs = ["javascript.options.asyncstack_capture_debuggee_only=false"] diff --git a/accessible/tests/browser/tree/browser.toml b/accessible/tests/browser/tree/browser.toml index 64be6853d1..a7d9894fcb 100644 --- a/accessible/tests/browser/tree/browser.toml +++ b/accessible/tests/browser/tree/browser.toml @@ -4,7 +4,6 @@ support-files = [ "head.js", "!/accessible/tests/browser/shared-head.js", "!/accessible/tests/mochitest/*.js", - "!/accessible/tests/browser/*.jsm", ] prefs = ["javascript.options.asyncstack_capture_debuggee_only=false"] diff --git a/accessible/tests/browser/windows/a11y_setup.py b/accessible/tests/browser/windows/a11y_setup.py index 726eea07a4..860364d99b 100644 --- a/accessible/tests/browser/windows/a11y_setup.py +++ b/accessible/tests/browser/windows/a11y_setup.py @@ -61,9 +61,6 @@ uiaClient = comtypes.CoCreateInstance( interface=uiaMod.IUIAutomation, clsctx=comtypes.CLSCTX_INPROC_SERVER, ) -TreeScope_Descendants = uiaMod.TreeScope_Descendants -UIA_AutomationIdPropertyId = uiaMod.UIA_AutomationIdPropertyId -del uiaMod def AccessibleObjectFromWindow(hwnd, objectID=OBJID_CLIENT): @@ -173,7 +170,7 @@ class WaitForWinEvent: """ def __init__(self, eventId, match): - """event is the event id to wait for. + """eventId is the event id to wait for. match is either None to match any object, an str containing the DOM id of the desired object, or a function taking a WinEvent which should return True if this is the requested event. @@ -235,6 +232,7 @@ class WaitForWinEvent: raise finally: user32.UnhookWinEvent(self._hook) + ctypes.windll.kernel32.CloseHandle(self._signal) self._proc = None if isinstance(self._matched, Exception): raise self._matched from self._matched @@ -243,17 +241,153 @@ class WaitForWinEvent: def getDocUia(): """Get the IUIAutomationElement for the document being tested.""" - # We start with IAccessible2 because there's no efficient way to - # find the document we want with UIA. - ia2 = getDocIa2() - return uiaClient.ElementFromIAccessible(ia2, CHILDID_SELF) + # There's no efficient way to find the document we want with UIA. We can't + # get the IA2 and then get UIA from that because that will always use the + # IA2 -> UIA proxy, but we don't want that if we're trying to test our + # native implementation. For now, we just search the tree. In future, we + # could perhaps implement a custom property. + hwnd = getFirefoxHwnd() + root = uiaClient.ElementFromHandle(hwnd) + doc = findUiaByDomId(root, "body") + if not doc: + # Sometimes, when UIA is disabled, we can't find the document for some + # unknown reason. Since this only happens when UIA is disabled, we want + # the IA2 -> UIA proxy anyway, so we can start with IA2 in this case. + info("getUiaDoc: Falling back to IA2") # noqa: F821 + ia2 = getDocIa2() + return uiaClient.ElementFromIAccessible(ia2, CHILDID_SELF) + child = uiaClient.RawViewWalker.GetFirstChildElement(doc) + if child and child.CurrentAutomationId == "default-iframe-id": + # This is an iframe or remoteIframe test. + doc = uiaClient.RawViewWalker.GetFirstChildElement(child) + return doc def findUiaByDomId(root, id): - cond = uiaClient.CreatePropertyCondition(UIA_AutomationIdPropertyId, id) + cond = uiaClient.CreatePropertyCondition(uiaMod.UIA_AutomationIdPropertyId, id) # FindFirst ignores elements in the raw tree, so we have to use # FindFirstBuildCache to override that, even though we don't want to cache # anything. request = uiaClient.CreateCacheRequest() request.TreeFilter = uiaClient.RawViewCondition - return root.FindFirstBuildCache(TreeScope_Descendants, cond, request) + el = root.FindFirstBuildCache(uiaMod.TreeScope_Descendants, cond, request) + if not el: + return None + # We need to test things that were introduced after UIA was initially + # introduced in Windows 7. + return el.QueryInterface(uiaMod.IUIAutomationElement9) + + +class WaitForUiaEvent(comtypes.COMObject): + """Wait for a UIA event. + This should be used as follows: + 1. Create an instance to wait for the desired event. + 2. Perform the action that should fire the event. + 3. Call wait() on the instance you created in 1) to wait for the event. + """ + + # This tells comtypes which COM interfaces we implement. It will then call + # either `ISomeInterface_SomeMethod` or just `SomeMethod` on this instance + # when that method is called using COM. We use the shorter convention, since + # we don't anticipate method name conflicts with UIA interfaces. + _com_interfaces_ = [ + uiaMod.IUIAutomationFocusChangedEventHandler, + uiaMod.IUIAutomationPropertyChangedEventHandler, + uiaMod.IUIAutomationEventHandler, + ] + + def __init__(self, *, eventId=None, property=None, match=None): + """eventId is the event id to wait for. Alternatively, you can pass + property to wait for a particular property to change. + match is either None to match any object, an str containing the DOM id + of the desired object, or a function taking a IUIAutomationElement which + should return True if this is the requested event. + """ + self._match = match + self._matched = None + # A kernel event used to signal when we get the desired event. + self._signal = ctypes.windll.kernel32.CreateEventW(None, True, False, None) + if eventId == uiaMod.UIA_AutomationFocusChangedEventId: + uiaClient.AddFocusChangedEventHandler(None, self) + elif eventId: + # Generic automation event. + uiaClient.AddAutomationEventHandler( + eventId, + uiaClient.GetRootElement(), + uiaMod.TreeScope_Subtree, + None, + self, + ) + elif property: + uiaClient.AddPropertyChangedEventHandler( + uiaClient.GetRootElement(), + uiaMod.TreeScope_Subtree, + None, + self, + [property], + ) + else: + raise ValueError("No supported event specified") + + def _checkMatch(self, sender): + if isinstance(self._match, str): + try: + if sender.CurrentAutomationId == self._match: + self._matched = sender + except comtypes.COMError: + pass + elif callable(self._match): + try: + if self._match(sender): + self._matched = sender + except Exception as e: + self._matched = e + else: + self._matched = sender + if self._matched: + ctypes.windll.kernel32.SetEvent(self._signal) + + def HandleFocusChangedEvent(self, sender): + self._checkMatch(sender) + + def HandlePropertyChangedEvent(self, sender, propertyId, newValue): + self._checkMatch(sender) + + def HandleAutomationEvent(self, sender, eventId): + self._checkMatch(sender) + + def wait(self): + """Wait for and return the IUIAutomationElement which sent the desired + event.""" + # Pump Windows messages until we get the desired event, which will be + # signalled using a kernel event. + handles = (ctypes.c_void_p * 1)(self._signal) + index = ctypes.wintypes.DWORD() + TIMEOUT = 10000 + try: + ctypes.oledll.ole32.CoWaitForMultipleHandles( + COWAIT_DEFAULT, TIMEOUT, 1, handles, ctypes.byref(index) + ) + except WindowsError as e: + if e.winerror == RPC_S_CALLPENDING: + raise TimeoutError("Timeout before desired event received") + raise + finally: + uiaClient.RemoveAllEventHandlers() + ctypes.windll.kernel32.CloseHandle(self._signal) + if isinstance(self._matched, Exception): + raise self._matched from self._matched + return self._matched + + +def getUiaPattern(element, patternName): + """Get a control pattern interface from an IUIAutomationElement.""" + patternId = getattr(uiaMod, f"UIA_{patternName}PatternId") + unknown = element.GetCurrentPattern(patternId) + if not unknown: + return None + # GetCurrentPattern returns an IUnknown. We have to QI to the real + # interface. + # Get the comtypes interface object. + interface = getattr(uiaMod, f"IUIAutomation{patternName}Pattern") + return unknown.QueryInterface(interface) diff --git a/accessible/tests/browser/windows/uia/browser.toml b/accessible/tests/browser/windows/uia/browser.toml index d1513c1822..75728f56d7 100644 --- a/accessible/tests/browser/windows/uia/browser.toml +++ b/accessible/tests/browser/windows/uia/browser.toml @@ -10,4 +10,9 @@ support-files = ["head.js"] ["browser_elementFromPoint.js"] +["browser_focus.js"] +["browser_generalProps.js"] + +["browser_simplePatterns.js"] + ["browser_tree.js"] diff --git a/accessible/tests/browser/windows/uia/browser_focus.js b/accessible/tests/browser/windows/uia/browser_focus.js new file mode 100644 index 0000000000..f26c9e1d1b --- /dev/null +++ b/accessible/tests/browser/windows/uia/browser_focus.js @@ -0,0 +1,61 @@ +/* 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"; + +async function testIsFocusable(pyVar, isFocusable) { + const result = await runPython(`${pyVar}.CurrentIsKeyboardFocusable`); + if (isFocusable) { + ok(result, `${pyVar} is focusable`); + } else { + ok(!result, `${pyVar} isn't focusable`); + } +} + +async function testHasFocus(pyVar, hasFocus) { + const result = await runPython(`${pyVar}.CurrentHasKeyboardFocus`); + if (hasFocus) { + ok(result, `${pyVar} has focus`); + } else { + ok(!result, `${pyVar} doesn't have focus`); + } +} + +addUiaTask( + ` +<button id="button1">button1</button> +<p id="p">p</p> +<button id="button2">button2</button> + `, + async function (browser) { + await definePyVar("doc", `getDocUia()`); + await testIsFocusable("doc", true); + await testHasFocus("doc", true); + + await assignPyVarToUiaWithId("button1"); + await testIsFocusable("button1", true); + await testHasFocus("button1", false); + info("Focusing button1"); + await setUpWaitForUiaEvent("AutomationFocusChanged", "button1"); + await invokeFocus(browser, "button1"); + await waitForUiaEvent(); + ok(true, "Got AutomationFocusChanged event on button1"); + await testHasFocus("button1", true); + + await assignPyVarToUiaWithId("p"); + await testIsFocusable("p", false); + await testHasFocus("p", false); + + await assignPyVarToUiaWithId("button2"); + await testIsFocusable("button2", true); + await testHasFocus("button2", false); + info("Focusing button2"); + await setUpWaitForUiaEvent("AutomationFocusChanged", "button2"); + await invokeFocus(browser, "button2"); + await waitForUiaEvent(); + ok(true, "Got AutomationFocusChanged event on button2"); + await testHasFocus("button2", true); + await testHasFocus("button1", false); + } +); diff --git a/accessible/tests/browser/windows/uia/browser_generalProps.js b/accessible/tests/browser/windows/uia/browser_generalProps.js new file mode 100644 index 0000000000..5cfda226d0 --- /dev/null +++ b/accessible/tests/browser/windows/uia/browser_generalProps.js @@ -0,0 +1,105 @@ +/* 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"; + +/** + * Test the Name property. + */ +addUiaTask( + ` +<button id="button">before</button> +<div id="div">div</div> + `, + async function testName(browser) { + await definePyVar("doc", `getDocUia()`); + await assignPyVarToUiaWithId("button"); + is( + await runPython(`button.CurrentName`), + "before", + "button has correct name" + ); + await assignPyVarToUiaWithId("div"); + is(await runPython(`div.CurrentName`), "", "div has no name"); + + info("Setting aria-label on button"); + await setUpWaitForUiaPropEvent("Name", "button"); + await invokeSetAttribute(browser, "button", "aria-label", "after"); + await waitForUiaEvent(); + ok(true, "Got Name prop change event on button"); + is( + await runPython(`button.CurrentName`), + "after", + "button has correct name" + ); + } +); + +/** + * Test the FullDescription property. + */ +addUiaTask( + ` +<button id="button" aria-description="before">button</button> +<div id="div">div</div> + `, + async function testFullDescription(browser) { + await definePyVar("doc", `getDocUia()`); + await assignPyVarToUiaWithId("button"); + is( + await runPython(`button.CurrentFullDescription`), + "before", + "button has correct FullDescription" + ); + await assignPyVarToUiaWithId("div"); + is( + await runPython(`div.CurrentFullDescription`), + "", + "div has no FullDescription" + ); + + info("Setting aria-description on button"); + await setUpWaitForUiaPropEvent("FullDescription", "button"); + await invokeSetAttribute(browser, "button", "aria-description", "after"); + await waitForUiaEvent(); + ok(true, "Got FullDescription prop change event on button"); + is( + await runPython(`button.CurrentFullDescription`), + "after", + "button has correct FullDescription" + ); + }, + // The IA2 -> UIA proxy doesn't support FullDescription. + { uiaEnabled: true, uiaDisabled: false } +); + +/** + * Test the IsEnabled property. + */ +addUiaTask( + ` +<button id="button">button</button> +<p id="p">p</p> + `, + async function testIsEnabled(browser) { + await definePyVar("doc", `getDocUia()`); + await assignPyVarToUiaWithId("button"); + ok(await runPython(`button.CurrentIsEnabled`), "button has IsEnabled true"); + // The IA2 -> UIA proxy doesn't fire IsEnabled prop change events. + if (gIsUiaEnabled) { + info("Setting disabled on button"); + await setUpWaitForUiaPropEvent("IsEnabled", "button"); + await invokeSetAttribute(browser, "button", "disabled", true); + await waitForUiaEvent(); + ok(true, "Got IsEnabled prop change event on button"); + ok( + !(await runPython(`button.CurrentIsEnabled`)), + "button has IsEnabled false" + ); + } + + await assignPyVarToUiaWithId("p"); + ok(await runPython(`p.CurrentIsEnabled`), "p has IsEnabled true"); + } +); diff --git a/accessible/tests/browser/windows/uia/browser_simplePatterns.js b/accessible/tests/browser/windows/uia/browser_simplePatterns.js new file mode 100644 index 0000000000..f464db0e13 --- /dev/null +++ b/accessible/tests/browser/windows/uia/browser_simplePatterns.js @@ -0,0 +1,445 @@ +/* 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"; + +/* import-globals-from ../../../mochitest/role.js */ +/* import-globals-from ../../../mochitest/states.js */ +loadScripts( + { name: "role.js", dir: MOCHITESTS_DIR }, + { name: "states.js", dir: MOCHITESTS_DIR } +); + +/* eslint-disable camelcase */ +const ExpandCollapseState_Collapsed = 0; +const ExpandCollapseState_Expanded = 1; +const ToggleState_Off = 0; +const ToggleState_On = 1; +const ToggleState_Indeterminate = 2; +/* eslint-enable camelcase */ + +/** + * Test the Invoke pattern. + */ +addUiaTask( + ` +<button id="button">button</button> +<p id="p">p</p> +<input id="checkbox" type="checkbox"> + `, + async function testInvoke() { + await definePyVar("doc", `getDocUia()`); + await assignPyVarToUiaWithId("button"); + await definePyVar("pattern", `getUiaPattern(button, "Invoke")`); + ok(await runPython(`bool(pattern)`), "button has Invoke pattern"); + info("Calling Invoke on button"); + // The button will get focus when it is clicked. + let focused = waitForEvent(EVENT_FOCUS, "button"); + // The UIA -> IA2 proxy doesn't fire the Invoked event. + if (gIsUiaEnabled) { + await setUpWaitForUiaEvent("Invoke_Invoked", "button"); + } + await runPython(`pattern.Invoke()`); + await focused; + ok(true, "button got focus"); + if (gIsUiaEnabled) { + await waitForUiaEvent(); + ok(true, "button got Invoked event"); + } + + await testPatternAbsent("p", "Invoke"); + // The Microsoft IA2 -> UIA proxy doesn't follow Microsoft's own rules. + if (gIsUiaEnabled) { + // Check boxes expose the Toggle pattern, so they should not expose the + // Invoke pattern. + await testPatternAbsent("checkbox", "Invoke"); + } + } +); + +/** + * Test the Toggle pattern. + */ +addUiaTask( + ` +<input id="checkbox" type="checkbox" checked> +<button id="toggleButton" aria-pressed="false">toggle</button> +<button id="button">button</button> +<p id="p">p</p> + +<script> + // When checkbox is clicked and it is not checked, make it indeterminate. + document.getElementById("checkbox").addEventListener("click", evt => { + // Within the event listener, .checked is reversed and you can't set + // .indeterminate. Work around this by deferring and handling the changes + // ourselves. + evt.preventDefault(); + const target = evt.target; + setTimeout(() => { + if (target.checked) { + target.checked = false; + } else { + target.indeterminate = true; + } + }, 0); + }); + + // When toggleButton is clicked, set aria-pressed to true. + document.getElementById("toggleButton").addEventListener("click", evt => { + evt.target.ariaPressed = "true"; + }); +</script> + `, + async function testToggle() { + await definePyVar("doc", `getDocUia()`); + await assignPyVarToUiaWithId("checkbox"); + await definePyVar("pattern", `getUiaPattern(checkbox, "Toggle")`); + ok(await runPython(`bool(pattern)`), "checkbox has Toggle pattern"); + is( + await runPython(`pattern.CurrentToggleState`), + ToggleState_On, + "checkbox has ToggleState_On" + ); + // The IA2 -> UIA proxy doesn't fire ToggleState prop change events. + if (gIsUiaEnabled) { + info("Calling Toggle on checkbox"); + await setUpWaitForUiaPropEvent("ToggleToggleState", "checkbox"); + await runPython(`pattern.Toggle()`); + await waitForUiaEvent(); + ok(true, "Got ToggleState prop change event on checkbox"); + is( + await runPython(`pattern.CurrentToggleState`), + ToggleState_Off, + "checkbox has ToggleState_Off" + ); + info("Calling Toggle on checkbox"); + await setUpWaitForUiaPropEvent("ToggleToggleState", "checkbox"); + await runPython(`pattern.Toggle()`); + await waitForUiaEvent(); + ok(true, "Got ToggleState prop change event on checkbox"); + is( + await runPython(`pattern.CurrentToggleState`), + ToggleState_Indeterminate, + "checkbox has ToggleState_Indeterminate" + ); + } + + await assignPyVarToUiaWithId("toggleButton"); + await definePyVar("pattern", `getUiaPattern(toggleButton, "Toggle")`); + ok(await runPython(`bool(pattern)`), "toggleButton has Toggle pattern"); + is( + await runPython(`pattern.CurrentToggleState`), + ToggleState_Off, + "toggleButton has ToggleState_Off" + ); + if (gIsUiaEnabled) { + info("Calling Toggle on toggleButton"); + await setUpWaitForUiaPropEvent("ToggleToggleState", "toggleButton"); + await runPython(`pattern.Toggle()`); + await waitForUiaEvent(); + ok(true, "Got ToggleState prop change event on toggleButton"); + is( + await runPython(`pattern.CurrentToggleState`), + ToggleState_On, + "toggleButton has ToggleState_Off" + ); + } + + await testPatternAbsent("button", "Toggle"); + await testPatternAbsent("p", "Toggle"); + } +); + +/** + * Test the ExpandCollapse pattern. + */ +addUiaTask( + ` +<details> + <summary id="summary">summary</summary> + details +</details> +<button id="popup" aria-haspopup="true">popup</button> +<button id="button">button</button> +<script> + // When popup is clicked, set aria-expanded to true. + document.getElementById("popup").addEventListener("click", evt => { + evt.target.ariaExpanded = "true"; + }); +</script> + `, + async function testExpandCollapse() { + await definePyVar("doc", `getDocUia()`); + await assignPyVarToUiaWithId("summary"); + await definePyVar("pattern", `getUiaPattern(summary, "ExpandCollapse")`); + ok(await runPython(`bool(pattern)`), "summary has ExpandCollapse pattern"); + is( + await runPython(`pattern.CurrentExpandCollapseState`), + ExpandCollapseState_Collapsed, + "summary has ExpandCollapseState_Collapsed" + ); + // The IA2 -> UIA proxy doesn't fire ToggleState prop change events, nor + // does it fail when Expand/Collapse is called on a control which is + // already in the desired state. + if (gIsUiaEnabled) { + info("Calling Expand on summary"); + await setUpWaitForUiaPropEvent( + "ExpandCollapseExpandCollapseState", + "summary" + ); + await runPython(`pattern.Expand()`); + await waitForUiaEvent(); + ok( + true, + "Got ExpandCollapseExpandCollapseState prop change event on summary" + ); + is( + await runPython(`pattern.CurrentExpandCollapseState`), + ExpandCollapseState_Expanded, + "summary has ExpandCollapseState_Expanded" + ); + info("Calling Expand on summary"); + await testPythonRaises(`pattern.Expand()`, "Expand on summary failed"); + info("Calling Collapse on summary"); + await setUpWaitForUiaPropEvent( + "ExpandCollapseExpandCollapseState", + "summary" + ); + await runPython(`pattern.Collapse()`); + await waitForUiaEvent(); + ok( + true, + "Got ExpandCollapseExpandCollapseState prop change event on summary" + ); + is( + await runPython(`pattern.CurrentExpandCollapseState`), + ExpandCollapseState_Collapsed, + "summary has ExpandCollapseState_Collapsed" + ); + info("Calling Collapse on summary"); + await testPythonRaises( + `pattern.Collapse()`, + "Collapse on summary failed" + ); + } + + await assignPyVarToUiaWithId("popup"); + // Initially, popup has aria-haspopup but not aria-expanded. That should + // be exposed as collapsed. + await definePyVar("pattern", `getUiaPattern(popup, "ExpandCollapse")`); + ok(await runPython(`bool(pattern)`), "popup has ExpandCollapse pattern"); + // The IA2 -> UIA proxy doesn't expose ExpandCollapseState_Collapsed for + // aria-haspopup without aria-expanded. + if (gIsUiaEnabled) { + is( + await runPython(`pattern.CurrentExpandCollapseState`), + ExpandCollapseState_Collapsed, + "popup has ExpandCollapseState_Collapsed" + ); + info("Calling Expand on popup"); + await setUpWaitForUiaPropEvent( + "ExpandCollapseExpandCollapseState", + "popup" + ); + await runPython(`pattern.Expand()`); + await waitForUiaEvent(); + ok( + true, + "Got ExpandCollapseExpandCollapseState prop change event on popup" + ); + is( + await runPython(`pattern.CurrentExpandCollapseState`), + ExpandCollapseState_Expanded, + "popup has ExpandCollapseState_Expanded" + ); + } + + await testPatternAbsent("button", "ExpandCollapse"); + } +); + +/** + * Test the ScrollItem pattern. + */ +addUiaTask( + ` +<hr style="height: 100vh;"> +<button id="button">button</button> + `, + async function testScrollItem(browser, docAcc) { + await definePyVar("doc", `getDocUia()`); + await assignPyVarToUiaWithId("button"); + await definePyVar("pattern", `getUiaPattern(button, "ScrollItem")`); + ok(await runPython(`bool(pattern)`), "button has ScrollItem pattern"); + const button = findAccessibleChildByID(docAcc, "button"); + testStates(button, STATE_OFFSCREEN); + info("Calling ScrollIntoView on button"); + // UIA doesn't have an event for this. + let scrolled = waitForEvent(EVENT_SCROLLING_END, docAcc); + await runPython(`pattern.ScrollIntoView()`); + await scrolled; + ok(true, "Document scrolled"); + testStates(button, 0, 0, STATE_OFFSCREEN); + } +); + +/** + * Test the Value pattern. + */ +addUiaTask( + ` +<input id="text" value="before"> +<input id="textRo" readonly value="textRo"> +<input id="textDis" disabled value="textDis"> +<select id="select"><option selected>a</option><option>b</option></select> +<progress id="progress" value="0.5"></progress> +<input id="range" type="range" aria-valuetext="02:00:00"> +<a id="link" href="https://example.com/">Link</a> +<div id="ariaTextbox" contenteditable role="textbox">before</div> +<button id="button">button</button> + `, + async function testValue() { + await definePyVar("doc", `getDocUia()`); + await assignPyVarToUiaWithId("text"); + await definePyVar("pattern", `getUiaPattern(text, "Value")`); + ok(await runPython(`bool(pattern)`), "text has Value pattern"); + ok( + !(await runPython(`pattern.CurrentIsReadOnly`)), + "text has IsReadOnly false" + ); + is( + await runPython(`pattern.CurrentValue`), + "before", + "text has correct Value" + ); + info("SetValue on text"); + await setUpWaitForUiaPropEvent("ValueValue", "text"); + await runPython(`pattern.SetValue("after")`); + await waitForUiaEvent(); + is( + await runPython(`pattern.CurrentValue`), + "after", + "text has correct Value" + ); + + await assignPyVarToUiaWithId("textRo"); + await definePyVar("pattern", `getUiaPattern(textRo, "Value")`); + ok(await runPython(`bool(pattern)`), "textRo has Value pattern"); + ok( + await runPython(`pattern.CurrentIsReadOnly`), + "textRo has IsReadOnly true" + ); + is( + await runPython(`pattern.CurrentValue`), + "textRo", + "textRo has correct Value" + ); + info("SetValue on textRo"); + await testPythonRaises( + `pattern.SetValue("after")`, + "SetValue on textRo failed" + ); + + await assignPyVarToUiaWithId("textDis"); + await definePyVar("pattern", `getUiaPattern(textDis, "Value")`); + ok(await runPython(`bool(pattern)`), "textDis has Value pattern"); + ok( + !(await runPython(`pattern.CurrentIsReadOnly`)), + "textDis has IsReadOnly false" + ); + is( + await runPython(`pattern.CurrentValue`), + "textDis", + "textDis has correct Value" + ); + // The IA2 -> UIA proxy doesn't fail SetValue for a disabled element. + if (gIsUiaEnabled) { + info("SetValue on textDis"); + await testPythonRaises( + `pattern.SetValue("after")`, + "SetValue on textDis failed" + ); + } + + await assignPyVarToUiaWithId("select"); + await definePyVar("pattern", `getUiaPattern(select, "Value")`); + ok(await runPython(`bool(pattern)`), "select has Value pattern"); + ok( + !(await runPython(`pattern.CurrentIsReadOnly`)), + "select has IsReadOnly false" + ); + is( + await runPython(`pattern.CurrentValue`), + "a", + "select has correct Value" + ); + info("SetValue on select"); + await testPythonRaises( + `pattern.SetValue("b")`, + "SetValue on select failed" + ); + + await assignPyVarToUiaWithId("progress"); + await definePyVar("pattern", `getUiaPattern(progress, "Value")`); + ok(await runPython(`bool(pattern)`), "progress has Value pattern"); + // Gecko a11y doesn't treat progress bars as read only, but it probably + // should. + todo( + await runPython(`pattern.CurrentIsReadOnly`), + "progress has IsReadOnly true" + ); + is( + await runPython(`pattern.CurrentValue`), + "50%", + "progress has correct Value" + ); + info("SetValue on progress"); + await testPythonRaises( + `pattern.SetValue("60%")`, + "SetValue on progress failed" + ); + + await assignPyVarToUiaWithId("range"); + await definePyVar("pattern", `getUiaPattern(range, "Value")`); + ok(await runPython(`bool(pattern)`), "range has Value pattern"); + is( + await runPython(`pattern.CurrentValue`), + "02:00:00", + "range has correct Value" + ); + + await assignPyVarToUiaWithId("link"); + await definePyVar("pattern", `getUiaPattern(link, "Value")`); + ok(await runPython(`bool(pattern)`), "link has Value pattern"); + is( + await runPython(`pattern.CurrentValue`), + "https://example.com/", + "link has correct Value" + ); + + await assignPyVarToUiaWithId("ariaTextbox"); + await definePyVar("pattern", `getUiaPattern(ariaTextbox, "Value")`); + ok(await runPython(`bool(pattern)`), "ariaTextbox has Value pattern"); + ok( + !(await runPython(`pattern.CurrentIsReadOnly`)), + "ariaTextbox has IsReadOnly false" + ); + is( + await runPython(`pattern.CurrentValue`), + "before", + "ariaTextbox has correct Value" + ); + info("SetValue on ariaTextbox"); + await setUpWaitForUiaPropEvent("ValueValue", "ariaTextbox"); + await runPython(`pattern.SetValue("after")`); + await waitForUiaEvent(); + is( + await runPython(`pattern.CurrentValue`), + "after", + "ariaTextbox has correct Value" + ); + + await testPatternAbsent("button", "Value"); + } +); diff --git a/accessible/tests/browser/windows/uia/browser_tree.js b/accessible/tests/browser/windows/uia/browser_tree.js index 778609bedb..c63045b6d1 100644 --- a/accessible/tests/browser/windows/uia/browser_tree.js +++ b/accessible/tests/browser/windows/uia/browser_tree.js @@ -13,24 +13,6 @@ async function testIsControl(pyVar, isControl) { } } -/** - * Define a global Python variable and assign it to a given Python expression. - */ -function definePyVar(varName, expression) { - return runPython(` - global ${varName} - ${varName} = ${expression} - `); -} - -/** - * Get the UIA element with the given id and assign it to a global Python - * variable using the id as the variable name. - */ -function assignPyVarToUiaWithId(id) { - return definePyVar(id, `findUiaByDomId(doc, "${id}")`); -} - addUiaTask( ` <p id="p">paragraph</p> @@ -46,7 +28,7 @@ addUiaTask( <div id="editable" contenteditable>editable</div> <table id="table"><tr><th>th</th></tr></table> `, - async function (browser, docAcc) { + async function () { await definePyVar("doc", `getDocUia()`); await assignPyVarToUiaWithId("p"); await testIsControl("p", false); diff --git a/accessible/tests/browser/windows/uia/head.js b/accessible/tests/browser/windows/uia/head.js index e659354c7c..5b453ce6fe 100644 --- a/accessible/tests/browser/windows/uia/head.js +++ b/accessible/tests/browser/windows/uia/head.js @@ -4,7 +4,7 @@ "use strict"; -/* exported gIsUiaEnabled, addUiaTask */ +/* exported gIsUiaEnabled, addUiaTask, definePyVar, assignPyVarToUiaWithId, setUpWaitForUiaEvent, setUpWaitForUiaPropEvent, waitForUiaEvent, testPatternAbsent, testPythonRaises */ // Load the shared-head file first. Services.scriptloader.loadSubScript( @@ -53,3 +53,76 @@ function addUiaTask(doc, task, options = {}) { addTask(false); } } + +/** + * Define a global Python variable and assign it to a given Python expression. + */ +function definePyVar(varName, expression) { + return runPython(` + global ${varName} + ${varName} = ${expression} + `); +} + +/** + * Get the UIA element with the given id and assign it to a global Python + * variable using the id as the variable name. + */ +function assignPyVarToUiaWithId(id) { + return definePyVar(id, `findUiaByDomId(doc, "${id}")`); +} + +/** + * Set up to wait for a UIA event. You must await this before performing the + * action which fires the event. + */ +function setUpWaitForUiaEvent(eventName, id) { + return definePyVar( + "onEvent", + `WaitForUiaEvent(eventId=UIA_${eventName}EventId, match="${id}")` + ); +} + +/** + * Set up to wait for a UIA property change event. You must await this before + * performing the action which fires the event. + */ +function setUpWaitForUiaPropEvent(propName, id) { + return definePyVar( + "onEvent", + `WaitForUiaEvent(property=UIA_${propName}PropertyId, match="${id}")` + ); +} + +/** + * Wait for the event requested in setUpWaitForUia*Event. + */ +function waitForUiaEvent() { + return runPython(` + onEvent.wait() + `); +} + +/** + * Verify that a UIA element does *not* support the given control pattern. + */ +async function testPatternAbsent(id, patternName) { + const hasPattern = await runPython(` + el = findUiaByDomId(doc, "${id}") + return bool(getUiaPattern(el, "${patternName}")) + `); + ok(!hasPattern, `${id} doesn't have ${patternName} pattern`); +} + +/** + * Verify that a Python expression raises an exception. + */ +async function testPythonRaises(expression, message) { + let failed = false; + try { + await runPython(expression); + } catch { + failed = true; + } + ok(failed, message); +} diff --git a/accessible/tests/mochitest/attributes/test_obj_group.xhtml b/accessible/tests/mochitest/attributes/test_obj_group.xhtml index 0eda4b6f2d..ba0c8bd357 100644 --- a/accessible/tests/mochitest/attributes/test_obj_group.xhtml +++ b/accessible/tests/mochitest/attributes/test_obj_group.xhtml @@ -196,17 +196,19 @@ </menulist> <vbox> - <description role="menuitem" id="aria-menuitem" - value="conventional menuitem"/> - <description role="menuitemcheckbox" id="aria-menuitemcheckbox" - value="conventional checkbox menuitem"/> - <description role="menuitem" hidden="true"/> - <description role="menuitemradio" id="aria-menuitemradio" - value="conventional radio menuitem"/> - <description role="separator" - value="conventional separator"/> - <description role="menuitem" id="aria-menuitem2" - value="conventional menuitem"/> + <div role="menu"> + <description role="menuitem" id="aria-menuitem" + value="conventional menuitem"/> + <description role="menuitemcheckbox" id="aria-menuitemcheckbox" + value="conventional checkbox menuitem"/> + <description role="menuitem" hidden="true"/> + <description role="menuitemradio" id="aria-menuitemradio" + value="conventional radio menuitem"/> + <description role="separator" + value="conventional separator"/> + <description role="menuitem" id="aria-menuitem2" + value="conventional menuitem"/> + </div> </vbox> </vbox> diff --git a/accessible/tests/mochitest/focus/test_takeFocus.html b/accessible/tests/mochitest/focus/test_takeFocus.html index 752ed66b36..6384fbfcb8 100644 --- a/accessible/tests/mochitest/focus/test_takeFocus.html +++ b/accessible/tests/mochitest/focus/test_takeFocus.html @@ -48,7 +48,6 @@ gQueue.push(new takeFocusInvoker("aria-link")); gQueue.push(new takeFocusInvoker("aria-link2")); gQueue.push(new takeFocusInvoker("link")); - gQueue.push(new takeFocusInvoker("item2")); gQueue.push(new takeFocusInvoker(document)); gQueue.push(new takeFocusInvoker("lb_item2")); gQueue.push(new takeFocusInvoker(document)); diff --git a/accessible/tests/mochitest/name/test_general.html b/accessible/tests/mochitest/name/test_general.html index 09723e6222..47104ced3e 100644 --- a/accessible/tests/mochitest/name/test_general.html +++ b/accessible/tests/mochitest/name/test_general.html @@ -105,7 +105,7 @@ // The label element contains the button. The name is calculated from // this button. // Note: the name contains the content of the button. - testName("btn_label_inside", "text10text"); + testName("btn_label_inside", "text 10 text"); // The label element and the button are placed in the same form. Gets // the name from the label subtree. @@ -713,17 +713,21 @@ <div id="grouping" role="group">label</div> <button id="requested_name_from_grouping"aria-labelledby="grouping"></button> <!-- Name from sub tree of tbody marked as display:block;, which is also a grouping --> - <div id="listitem_containing_block_tbody" role="listitem"> - <table> - <tbody style="display: block;"> - <tr><td>label</td></tr> - </tbody> - </table> + <div role="list"> + <div id="listitem_containing_block_tbody" role="listitem"> + <table> + <tbody style="display: block;"> + <tr><td>label</td></tr> + </tbody> + </table> + </div> </div> <!-- Name from subtree of treeitem containing grouping --> - <div id="treeitem_containing_grouping" role="treeitem" aria-level="1" aria-expanded="true">root - <div role="group"> - <div role="treeitem" aria-level="2">sub</div> + <div role="tree"> + <div id="treeitem_containing_grouping" role="treeitem" aria-level="1" aria-expanded="true">root + <div role="group"> + <div role="treeitem" aria-level="2">sub</div> + </div> </div> </div> @@ -735,11 +739,13 @@ </div> <!-- Text nodes and inline elements. --> - <div id="container_text_inline" role="option">a<strong>b</strong>c</div> - <!-- Text nodes and block elements. --> - <div id="container_text_block" role="option">a<p>b</p>c</div> - <!-- Text nodes and empty block elements. --> - <div id="container_text_emptyblock" role="option">a<p></p><p></p>b</div> + <div role="listbox"> + <div id="container_text_inline" role="option">a<strong>b</strong>c</div> + <!-- Text nodes and block elements. --> + <div id="container_text_block" role="option">a<p>b</p>c</div> + <!-- Text nodes and empty block elements. --> + <div id="container_text_emptyblock" role="option">a<p></p><p></p>b</div> + </div> <!-- aria-labelledby referring to a slot --> <div id="shadowHost"> diff --git a/accessible/tests/mochitest/relations/a11y.toml b/accessible/tests/mochitest/relations/a11y.toml index ae41bf91a5..77021c28cf 100644 --- a/accessible/tests/mochitest/relations/a11y.toml +++ b/accessible/tests/mochitest/relations/a11y.toml @@ -18,6 +18,4 @@ skip-if = [ ["test_tree.xhtml"] -["test_ui_modalprompt.html"] - ["test_update.html"] diff --git a/accessible/tests/mochitest/relations/test_ui_modalprompt.html b/accessible/tests/mochitest/relations/test_ui_modalprompt.html deleted file mode 100644 index a05b273d86..0000000000 --- a/accessible/tests/mochitest/relations/test_ui_modalprompt.html +++ /dev/null @@ -1,111 +0,0 @@ -<html> - -<head> - <title>Modal prompts</title> - <link rel="stylesheet" type="text/css" - href="chrome://mochikit/content/tests/SimpleTest/test.css" /> - - <script src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script> - <script src="chrome://mochikit/content/tests/SimpleTest/EventUtils.js"></script> - - <script type="application/javascript" - src="../common.js"></script> - <script type="application/javascript" - src="../relations.js"></script> - <script type="application/javascript" - src="../role.js"></script> - <script type="application/javascript" - src="../events.js"></script> - <script type="application/javascript" - src="../browser.js"></script> - - <script type="application/javascript"> - SpecialPowers.pushPrefEnv({ - set: [["prompts.contentPromptSubDialog", false]], - }); - function showAlert() { - this.eventSeq = [ - { - type: EVENT_SHOW, - match(aEvent) { - return aEvent.accessible.role == ROLE_DIALOG; - }, - }, - ]; - - this.invoke = function showAlert_invoke() { - window.setTimeout( - function() { - currentTabDocument().defaultView.alert("hello"); - }, 0); - }; - - this.check = function showAlert_finalCheck(aEvent) { - if(aEvent.type === EVENT_HIDE) { - return; - } - var dialog = aEvent.accessible.DOMNode; - var info = dialog.querySelector(".tabmodalprompt-infoBody"); - testRelation(info, RELATION_DESCRIPTION_FOR, dialog); - testRelation(dialog, RELATION_DESCRIBED_BY, info); - }; - - this.getID = function showAlert_getID() { - return "show alert"; - }; - } - - function closeAlert() { - this.eventSeq = [ - { - type: EVENT_HIDE, - match(aEvent) { - return aEvent.accessible.role == ROLE_DIALOG; - }, - }, - ]; - - this.invoke = function showAlert_invoke() { - synthesizeKey("VK_RETURN", {}, browserWindow()); - }; - - this.getID = function showAlert_getID() { - return "cleanup alert"; - }; - } - - - // gA11yEventDumpToConsole = true; // debug - - var gQueue = null; - function doTests() { - gQueue = new eventQueue(); - gQueue.push(new showAlert()); - gQueue.push(new closeAlert()); - gQueue.onFinish = function() { - closeBrowserWindow(); - }; - gQueue.invoke(); // will call SimpleTest.finish() - } - - SimpleTest.waitForExplicitFinish(); - openBrowserWindow(doTests); - </script> - -</head> - -<body id="body"> - - <a target="_blank" - href="https://bugzilla.mozilla.org/show_bug.cgi?id=661293" - title="The tabmodalprompt dialog's prompt label doesn't get the text properly associated for accessibility"> - Mozilla Bug 661293 - </a> - <br> - <p id="display"></p> - <div id="content" style="display: none"></div> - <pre id="test"> - </pre> - -</body> -</html> diff --git a/accessible/tests/mochitest/role/test_aria.html b/accessible/tests/mochitest/role/test_aria.html index 0e7873c485..dcd2c7839e 100644 --- a/accessible/tests/mochitest/role/test_aria.html +++ b/accessible/tests/mochitest/role/test_aria.html @@ -42,8 +42,6 @@ testRole("aria_checkbox_mixed", ROLE_CHECKBUTTON); testRole("aria_code", ROLE_CODE); testRole("aria_code_mixed", ROLE_CODE); - testRole("aria_columnheader", ROLE_COLUMNHEADER); - testRole("aria_columnheader_mixed", ROLE_COLUMNHEADER); testRole("aria_combobox", ROLE_EDITCOMBOBOX); testRole("aria_combobox_mixed", ROLE_EDITCOMBOBOX); testRole("aria_comment", ROLE_COMMENT); @@ -66,8 +64,6 @@ testRole("aria_figure_mixed", ROLE_FIGURE); testRole("aria_grid", ROLE_GRID); testRole("aria_grid_mixed", ROLE_GRID); - testRole("aria_gridcell", ROLE_GRID_CELL); - testRole("aria_gridcell_mixed", ROLE_GRID_CELL); testRole("aria_group", ROLE_GROUPING); testRole("aria_group_mixed", ROLE_GROUPING); testRole("aria_heading", ROLE_HEADING); @@ -82,8 +78,6 @@ testRole("aria_list_mixed", ROLE_LIST); testRole("aria_listbox", ROLE_LISTBOX); testRole("aria_listbox_mixed", ROLE_LISTBOX); - testRole("aria_listitem", ROLE_LISTITEM); - testRole("aria_listitem_mixed", ROLE_LISTITEM); testRole("aria_log", ROLE_TEXT); // weak role testRole("aria_log_mixed", ROLE_TEXT); // weak role testRole("aria_mark", ROLE_MARK); @@ -96,12 +90,6 @@ testRole("aria_menu_mixed", ROLE_MENUPOPUP); testRole("aria_menubar", ROLE_MENUBAR); testRole("aria_menubar_mixed", ROLE_MENUBAR); - testRole("aria_menuitem", ROLE_MENUITEM); - testRole("aria_menuitem_mixed", ROLE_MENUITEM); - testRole("aria_menuitemcheckbox", ROLE_CHECK_MENU_ITEM); - testRole("aria_menuitemcheckbox_mixed", ROLE_CHECK_MENU_ITEM); - testRole("aria_menuitemradio", ROLE_RADIO_MENU_ITEM); - testRole("aria_menuitemradio_mixed", ROLE_RADIO_MENU_ITEM); testRole("aria_meter", ROLE_METER); testRole("aria_meter_mixed", ROLE_METER); testRole("aria_note", ROLE_NOTE); @@ -130,10 +118,6 @@ testRole("aria_region_as_table_with_caption_mixed", ROLE_REGION); testRole("aria_region_as_table_with_miscaption", ROLE_TABLE); testRole("aria_region_as_table_with_miscaption_mixed", ROLE_TABLE); - testRole("aria_row", ROLE_ROW); - testRole("aria_row_mixed", ROLE_ROW); - testRole("aria_rowheader", ROLE_ROWHEADER); - testRole("aria_rowheader_mixed", ROLE_ROWHEADER); testRole("aria_scrollbar", ROLE_SCROLLBAR); testRole("aria_scrollbar_mixed", ROLE_SCROLLBAR); testRole("aria_searchbox", ROLE_ENTRY); @@ -154,8 +138,6 @@ testRole("aria_superscript_mixed", ROLE_SUPERSCRIPT); testRole("aria_switch", ROLE_SWITCH); testRole("aria_switch_mixed", ROLE_SWITCH); - testRole("aria_tab", ROLE_PAGETAB); - testRole("aria_tab_mixed", ROLE_PAGETAB); testRole("aria_tablist", ROLE_PAGETABLIST); testRole("aria_tablist_mixed", ROLE_PAGETABLIST); testRole("aria_tabpanel", ROLE_PROPERTYPAGE); @@ -174,8 +156,6 @@ testRole("aria_tree_mixed", ROLE_OUTLINE); testRole("aria_treegrid", ROLE_TREE_TABLE); testRole("aria_treegrid_mixed", ROLE_TREE_TABLE); - testRole("aria_treeitem", ROLE_OUTLINEITEM); - testRole("aria_treeitem_mixed", ROLE_OUTLINEITEM); // Note: // The phrase "weak foo" here means that there is no good foo-to-platform @@ -262,6 +242,29 @@ testRole("implicit_gridcell_mixed", ROLE_GRID_CELL); // //////////////////////////////////////////////////////////////////////// + // child roles dependent on ancestor role presence + testRole("aria_columnheader", ROLE_COLUMNHEADER); + testRole("aria_columnheader_mixed", ROLE_COLUMNHEADER); + testRole("aria_gridcell", ROLE_GRID_CELL); + testRole("aria_gridcell_mixed", ROLE_GRID_CELL); + testRole("aria_rowheader", ROLE_ROWHEADER); + testRole("aria_rowheader_mixed", ROLE_ROWHEADER); + testRole("aria_listitem", ROLE_LISTITEM); + testRole("aria_listitem_mixed", ROLE_LISTITEM); + testRole("aria_menuitem", ROLE_MENUITEM); + testRole("aria_menuitem_mixed", ROLE_MENUITEM); + testRole("aria_menuitemcheckbox", ROLE_CHECK_MENU_ITEM); + testRole("aria_menuitemcheckbox_mixed", ROLE_CHECK_MENU_ITEM); + testRole("aria_menuitemradio", ROLE_RADIO_MENU_ITEM); + testRole("aria_menuitemradio_mixed", ROLE_RADIO_MENU_ITEM); + testRole("aria_row", ROLE_ROW); + testRole("aria_row_mixed", ROLE_ROW); + testRole("aria_tab", ROLE_PAGETAB); + testRole("aria_tab_mixed", ROLE_PAGETAB); + testRole("aria_treeitem", ROLE_OUTLINEITEM); + testRole("aria_treeitem_mixed", ROLE_OUTLINEITEM); + + // //////////////////////////////////////////////////////////////////////// // ignore unknown roles, take first known testRole("unknown_roles", ROLE_PUSHBUTTON); testRole("unknown_roles_mixed", ROLE_PUSHBUTTON); @@ -400,8 +403,6 @@ <span id="aria_checkbox_mixed" role="cHECKBOx"></span> <span id="aria_code" role="code"></span> <span id="aria_code_mixed" role="cODe"></span> - <span id="aria_columnheader" role="columnheader"></span> - <span id="aria_columnheader_mixed" role="cOLUMNHEADEr"></span> <span id="aria_combobox" role="combobox"></span> <span id="aria_combobox_mixed" role="cOMBOBOx"></span> <span id="aria_comment" role="comment"></span> @@ -424,8 +425,6 @@ <span id="aria_figure_mixed" role="fIGURe"></span> <span id="aria_grid" role="grid"></span> <span id="aria_grid_mixed" role="gRId"></span> - <span id="aria_gridcell" role="gridcell"></span> - <span id="aria_gridcell_mixed" role="gRIDCELl"></span> <span id="aria_group" role="group"></span> <span id="aria_group_mixed" role="gROUp"></span> <span id="aria_heading" role="heading"></span> @@ -440,8 +439,6 @@ <span id="aria_list_mixed" role="lISt"></span> <span id="aria_listbox" role="listbox"></span> <span id="aria_listbox_mixed" role="lISTBOx"></span> - <span id="aria_listitem" role="listitem"></span> - <span id="aria_listitem_mixed" role="lISTITEm"></span> <span id="aria_log" role="log"></span> <span id="aria_log_mixed" role="lOg"></span> <span id="aria_mark" role="mark"></span> @@ -454,12 +451,6 @@ <span id="aria_menu_mixed" role="mENu"></span> <span id="aria_menubar" role="menubar"></span> <span id="aria_menubar_mixed" role="mENUBAr"></span> - <span id="aria_menuitem" role="menuitem"></span> - <span id="aria_menuitem_mixed" role="mENUITEm"></span> - <span id="aria_menuitemcheckbox" role="menuitemcheckbox"></span> - <span id="aria_menuitemcheckbox_mixed" role="mENUITEMCHECKBOx"></span> - <span id="aria_menuitemradio" role="menuitemradio"></span> - <span id="aria_menuitemradio_mixed" role="mENUITEMRADIo"></span> <span id="aria_meter" role="meter"></span> <span id="aria_meter_mixed" role="meTer"></span> <span id="aria_note" role="note"></span> @@ -488,10 +479,6 @@ <table id="aria_region_as_table_with_caption_mixed" role="rEGIOn"><caption>hello</caption></table> <table id="aria_region_as_table_with_miscaption" role="region"><caption role="option">hello</caption></table> <table id="aria_region_as_table_with_miscaption_mixed" role="rEGIOn"><caption role="option">hello</caption></table> - <span id="aria_row" role="row"></span> - <span id="aria_row_mixed" role="rOw"></span> - <span id="aria_rowheader" role="rowheader"></span> - <span id="aria_rowheader_mixed" role="rOWHEADEr"></span> <span id="aria_scrollbar" role="scrollbar"></span> <span id="aria_scrollbar_mixed" role="sCROLLBAr"></span> <span id="aria_searchbox" role="textbox"></span> @@ -512,8 +499,6 @@ <span id="aria_superscript_mixed" role="sUPERSCRIPt"></span> <span id="aria_switch" role="switch"></span> <span id="aria_switch_mixed" role="sWITCh"></span> - <span id="aria_tab" role="tab"></span> - <span id="aria_tab_mixed" role="tAb"></span> <span id="aria_tablist" role="tablist"></span> <span id="aria_tablist_mixed" role="tABLISt"></span> <span id="aria_tabpanel" role="tabpanel"></span> @@ -532,8 +517,6 @@ <span id="aria_tree_mixed" role="tREe"></span> <span id="aria_treegrid" role="treegrid"></span> <span id="aria_treegrid_mixed" role="tREEGRId"></span> - <span id="aria_treeitem" role="treeitem"></span> - <span id="aria_treeitem_mixed" role="tREEITEm"></span> <article id="articlemain" role="main">a main area</article> <article id="articlemain_mixed" role="mAIn">a main area</article> @@ -665,6 +648,42 @@ </tr> </table> + <!-- child roles dependent on ancestor role presence --> + <div role="grid"> + <div role="row"> + <span id="aria_columnheader" role="columnheader"></span> + <span id="aria_columnheader_mixed" role="cOLUMNHEADEr"></span> + <span id="aria_gridcell" role="gridcell"></span> + <span id="aria_gridcell_mixed" role="gRIDCELl"></span> + <span id="aria_rowheader" role="rowheader"></span> + <span id="aria_rowheader_mixed" role="rOWHEADEr"></span> + </div> + </div> + <div role="list"> + <span id="aria_listitem" role="listitem"></span> + <span id="aria_listitem_mixed" role="lISTITEm"></span> + </div> + <div role="menu"> + <span id="aria_menuitem" role="menuitem"></span> + <span id="aria_menuitem_mixed" role="mENUITEm"></span> + <span id="aria_menuitemcheckbox" role="menuitemcheckbox"></span> + <span id="aria_menuitemcheckbox_mixed" role="mENUITEMCHECKBOx"></span> + <span id="aria_menuitemradio" role="menuitemradio"></span> + <span id="aria_menuitemradio_mixed" role="mENUITEMRADIo"></span> + </div> + <div role="table"> + <span id="aria_row" role="row"></span> + <span id="aria_row_mixed" role="rOw"></span> + </div> + <div role="tablist"> + <span id="aria_tab" role="tab"></span> + <span id="aria_tab_mixed" role="tAb"></span> + </div> + <div role="tree"> + <span id="aria_treeitem" role="treeitem"></span> + <span id="aria_treeitem_mixed" role="tREEITEm"></span> + </div> + <!-- roles transformed by ARIA state attributes --> <button aria-pressed="true" id="togglebutton"></button> <button aria-pressed="tRUe" id="togglebutton_mixed"></button> diff --git a/accessible/tests/mochitest/test_custom_element_accessibility_defaults.html b/accessible/tests/mochitest/test_custom_element_accessibility_defaults.html index 672b5c36ad..799aefc163 100644 --- a/accessible/tests/mochitest/test_custom_element_accessibility_defaults.html +++ b/accessible/tests/mochitest/test_custom_element_accessibility_defaults.html @@ -33,7 +33,7 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=1665151 ["disabled", "button", internals => internals.ariaDisabled = "true"], ["expanded", "button", internals => internals.ariaExpanded = "true"], ["haspopup", "button", internals => internals.ariaHasPopup = "true"], - ["hidden", "region", internals => internals.ariaHidden = "false"], + ["hidden", "region", internals => internals.ariaHidden = "true"], ["invalid", "textbox", internals => internals.ariaInvalid = "true"], ["keyshortcuts", "button", internals => internals.ariaKeyShortcuts = "Alt+Shift+A"], ["label", "button", internals => internals.ariaLabel = "Default"], @@ -122,8 +122,8 @@ async function runTest() { testAttrs("default-haspopup", {"haspopup": "true"}, true); testAbsentAttrs("custom-haspopup", {"haspopup": "false"}); - ok(isAccessible("default-hidden"), "Accessible for not aria-hidden"); - ok(!isAccessible("custom-hidden"), "No accessible for aria-hidden"); + ok(!isAccessible("default-hidden"), "Accessible for aria-hidden default"); + ok(isAccessible("custom-hidden"), "Accessible for custom aria-hidden=false"); testStates("default-invalid", STATE_INVALID); testStates("custom-invalid", 0, 0, STATE_INVALID); @@ -277,7 +277,7 @@ addA11yLoadEvent(runTest); <custom-haspopup id="custom-haspopup" aria-haspopup="false"></custom-haspopup> <custom-hidden id="default-hidden"></custom-hidden> -<custom-hidden id="custom-hidden" aria-hidden="true"></custom-hidden> +<custom-hidden id="custom-hidden" aria-hidden="false"></custom-hidden> <custom-invalid id="default-invalid"></custom-invalid> <custom-invalid id="custom-invalid" aria-invalid="false"></custom-invalid> @@ -306,8 +306,10 @@ addA11yLoadEvent(runTest); <custom-orientation id="default-orientation"></custom-orientation> <custom-orientation id="custom-orientation" aria-orientation="horizontal"></custom-orientation> -<custom-posinset id="default-posinset"></custom-posinset> -<custom-posinset id="custom-posinset" aria-posinset="2"></custom-posinset> +<div role="listbox"> + <custom-posinset id="default-posinset"></custom-posinset> + <custom-posinset id="custom-posinset" aria-posinset="2"></custom-posinset> +</div> <custom-pressed id="default-pressed"></custom-pressed> <custom-pressed id="custom-pressed" aria-pressed="false"></custom-pressed> @@ -345,10 +347,10 @@ addA11yLoadEvent(runTest); <custom-selected id="default-selected"></custom-selected> <custom-selected id="custom-selected" aria-selected="false"></custom-selected> -<div role="listbox"> +<div role="list"> <custom-setsize id="default-setsize"></custom-setsize> </div> -<div role="listbox"> +<div role="list"> <custom-setsize id="custom-setsize" aria-setsize="2"></custom-setsize> <div role="listitem" aria-setsize="2"></div> </div> diff --git a/accessible/tests/mochitest/tree/test_aria_display_contents.html b/accessible/tests/mochitest/tree/test_aria_display_contents.html index 454e4e46e1..5b2331e730 100644 --- a/accessible/tests/mochitest/tree/test_aria_display_contents.html +++ b/accessible/tests/mochitest/tree/test_aria_display_contents.html @@ -53,11 +53,11 @@ ] }, ] }, { SECTION: [ - { LISTITEM: [ + { SECTION: [ { TEXT_LEAF: [ ] } ] }, ] }, - { LISTITEM: [ + { SECTION: [ { TEXT_LEAF: [ ] } ] }, ] }; @@ -93,63 +93,63 @@ </pre> <div id="gridWithoutDisplayContents" role="grid"> - <div role="row">
- <div role="columnheader">col1</div>
- <div role="columnheader">col2</div>
- </div>
- <div role="row">
- <div role="rowheader">row1</div>
- <div role="gridcell">cell1</div>
+ <div role="row"> + <div role="columnheader">col1</div> + <div role="columnheader">col2</div> + </div> + <div role="row"> + <div role="rowheader">row1</div> + <div role="gridcell">cell1</div> </div> </div> <div id="gridWithDisplayContents" role="grid" style="display:contents;"> - <div role="row">
- <div role="columnheader">col1</div>
- <div role="columnheader">col2</div>
- </div>
- <div role="row">
- <div role="rowheader">row1</div>
- <div role="gridcell">cell1</div>
+ <div role="row"> + <div role="columnheader">col1</div> + <div role="columnheader">col2</div> + </div> + <div role="row"> + <div role="rowheader">row1</div> + <div role="gridcell">cell1</div> </div> </div> <div id="gridWithDisplayContentsRow" role="grid"> - <div role="row" style="display:contents;">
- <div role="columnheader">col1</div>
- <div role="columnheader">col2</div>
- </div>
- <div role="row">
- <div role="rowheader">row1</div>
- <div role="gridcell">cell1</div>
+ <div role="row" style="display:contents;"> + <div role="columnheader">col1</div> + <div role="columnheader">col2</div> + </div> + <div role="row"> + <div role="rowheader">row1</div> + <div role="gridcell">cell1</div> </div> </div> <div id="gridWithDisplayContentsColHeader" role="grid"> - <div role="row">
- <div role="columnheader" style="display:contents;">col1</div>
- <div role="columnheader">col2</div>
- </div>
- <div role="row">
- <div role="rowheader">row1</div>
- <div role="gridcell">cell1</div>
+ <div role="row"> + <div role="columnheader" style="display:contents;">col1</div> + <div role="columnheader">col2</div> + </div> + <div role="row"> + <div role="rowheader">row1</div> + <div role="gridcell">cell1</div> </div> </div> <div id="gridWithDisplayContentsRowHeader" role="grid"> - <div role="row">
- <div role="columnheader">col1</div>
- <div role="columnheader">col2</div>
- </div>
- <div role="row">
- <div role="rowheader" style="display:contents;">row1</div>
- <div role="gridcell">cell1</div>
+ <div role="row"> + <div role="columnheader">col1</div> + <div role="columnheader">col2</div> + </div> + <div role="row"> + <div role="rowheader" style="display:contents;">row1</div> + <div role="gridcell">cell1</div> </div> </div> <div id="gridWithDisplayContentsGridCell" role="grid"> - <div role="row">
- <div role="columnheader">col1</div>
- <div role="columnheader">col2</div>
- </div>
- <div role="row">
- <div role="rowheader">row1</div>
- <div role="gridcell" style="display:contents;">cell1</div>
+ <div role="row"> + <div role="columnheader">col1</div> + <div role="columnheader">col2</div> + </div> + <div role="row"> + <div role="rowheader">row1</div> + <div role="gridcell" style="display:contents;">cell1</div> </div> </div> diff --git a/accessible/tests/mochitest/tree/test_aria_grid.html b/accessible/tests/mochitest/tree/test_aria_grid.html index 4dd30e4183..d409c87c34 100644 --- a/accessible/tests/mochitest/tree/test_aria_grid.html +++ b/accessible/tests/mochitest/tree/test_aria_grid.html @@ -19,7 +19,7 @@ var accTree = { GRID: [ - { GROUPING: [ + { ROWGROUP: [ { ROW: [ { GRID_CELL: [ { TEXT_LEAF: [ ] }, diff --git a/accessible/tests/mochitest/tree/test_aria_table.html b/accessible/tests/mochitest/tree/test_aria_table.html index 22375faf59..2d4a0f00ae 100644 --- a/accessible/tests/mochitest/tree/test_aria_table.html +++ b/accessible/tests/mochitest/tree/test_aria_table.html @@ -19,7 +19,7 @@ var accTree = { TABLE: [ - { GROUPING: [ + { ROWGROUP: [ { ROW: [ { CELL: [ { TEXT_LEAF: [ ] }, diff --git a/accessible/tests/mochitest/tree/test_display_contents.html b/accessible/tests/mochitest/tree/test_display_contents.html index 8393a35b41..9573a845d3 100644 --- a/accessible/tests/mochitest/tree/test_display_contents.html +++ b/accessible/tests/mochitest/tree/test_display_contents.html @@ -41,7 +41,7 @@ function doTest() { tree = { TABLE: [ - { GROUPING : [ + { ROWGROUP : [ { ROW: [ { CELL: [{ TEXT_LEAF: [] } ] }, { CELL: [{ TEXT_LEAF: [] } ] }, diff --git a/accessible/tests/mochitest/tree/test_table.html b/accessible/tests/mochitest/tree/test_table.html index 5f34c12067..7f7f4fe6db 100644 --- a/accessible/tests/mochitest/tree/test_table.html +++ b/accessible/tests/mochitest/tree/test_table.html @@ -283,7 +283,7 @@ // The tbody should get a grouping accessible. accTree = { TABLE: [ - { GROUPING: [ + { ROWGROUP: [ { ROW: [ { CELL: [ { TEXT_LEAF: [ ] }, |