diff options
Diffstat (limited to 'accessible/tests/browser/selectable')
-rw-r--r-- | accessible/tests/browser/selectable/browser.toml | 13 | ||||
-rw-r--r-- | accessible/tests/browser/selectable/browser_test_aria_select.js | 164 | ||||
-rw-r--r-- | accessible/tests/browser/selectable/browser_test_select.js | 329 | ||||
-rw-r--r-- | accessible/tests/browser/selectable/head.js | 88 |
4 files changed, 594 insertions, 0 deletions
diff --git a/accessible/tests/browser/selectable/browser.toml b/accessible/tests/browser/selectable/browser.toml new file mode 100644 index 0000000000..38a13c25f4 --- /dev/null +++ b/accessible/tests/browser/selectable/browser.toml @@ -0,0 +1,13 @@ +[DEFAULT] +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"] + +["browser_test_aria_select.js"] + +["browser_test_select.js"] diff --git a/accessible/tests/browser/selectable/browser_test_aria_select.js b/accessible/tests/browser/selectable/browser_test_aria_select.js new file mode 100644 index 0000000000..f52603d1cb --- /dev/null +++ b/accessible/tests/browser/selectable/browser_test_aria_select.js @@ -0,0 +1,164 @@ +/* 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/selectable.js */ + +// //////////////////////////////////////////////////////////////////////// +// role="tablist" role="listbox" role="grid" role="tree" role="treegrid" +addAccessibleTask( + `<div role="tablist" id="tablist"> + <div role="tab">tab1</div> + <div role="tab">tab2</div> + </div> + <div role="listbox" id="listbox"> + <div role="option">item1</div> + <div role="option">item2</div> + </div> + <div role="grid" id="grid"> + <div role="row"> + <span role="gridcell">cell</span> + <span role="gridcell">cell</span> + </div> + <div role="row"> + <span role="gridcell">cell</span> + <span role="gridcell">cell</span> + </div> + </div> + <div role="tree" id="tree"> + <div role="treeitem"> + item1 + <div role="group"> + <div role="treeitem">item1.1</div> + </div> + </div> + <div>item2</div> + </div> + <div role="treegrid" id="treegrid"> + <div role="row" aria-level="1"> + <span role="gridcell">cell</span> + <span role="gridcell">cell</span> + </div> + <div role="row" aria-level="2"> + <span role="gridcell">cell</span> + <span role="gridcell">cell</span> + </div> + <div role="row" aria-level="1"> + <span role="gridcell">cell</span> + <span role="gridcell">cell</span> + </div> + </div>`, + async function (browser, docAcc) { + info( + 'role="tablist" role="listbox" role="grid" role="tree" role="treegrid"' + ); + testSelectableSelection(findAccessibleChildByID(docAcc, "tablist"), []); + testSelectableSelection(findAccessibleChildByID(docAcc, "listbox"), []); + testSelectableSelection(findAccessibleChildByID(docAcc, "grid"), []); + testSelectableSelection(findAccessibleChildByID(docAcc, "tree"), []); + testSelectableSelection(findAccessibleChildByID(docAcc, "treegrid"), []); + }, + { + chrome: true, + topLevel: true, + iframe: true, + remoteIframe: true, + } +); + +// //////////////////////////////////////////////////////////////////////// +// 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_multi2">tab2</div> + </div>`, + async function (browser, docAcc) { + info('role="tablist" aria-multiselectable'); + let tablist = findAccessibleChildByID(docAcc, "tablist", [ + nsIAccessibleSelectable, + ]); + + await testMultiSelectable(tablist, ["tab_multi1", "tab_multi2"]); + }, + { + chrome: true, + topLevel: true, + iframe: true, + remoteIframe: true, + } +); + +// //////////////////////////////////////////////////////////////////////// +// 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_item2">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"]); + }, + { + chrome: true, + topLevel: true, + iframe: true, + remoteIframe: true, + } +); + +// //////////////////////////////////////////////////////////////////////// +// role="grid" aria-multiselectable, selectable children in subtree +addAccessibleTask( + `<table tabindex="0" border="2" cellspacing="0" id="grid" role="grid" + aria-multiselectable="true"> + <thead> + <tr> + <th tabindex="-1" role="columnheader" id="grid_colhead1" + style="width:6em">Entry #</th> + <th tabindex="-1" role="columnheader" id="grid_colhead2" + style="width:10em">Date</th> + <th tabindex="-1" role="columnheader" id="grid_colhead3" + style="width:20em">Expense</th> + </tr> + </thead> + <tbody> + <tr> + <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> + <td tabindex="-1" role="gridcell" id="grid_cell2" + aria-selected="false">Conference Fee</td> + </tr> + </tobdy> + </table>`, + async function (browser, docAcc) { + info('role="grid" aria-multiselectable, selectable children in subtree'); + let grid = findAccessibleChildByID(docAcc, "grid", [ + nsIAccessibleSelectable, + ]); + + await testMultiSelectable(grid, [ + "grid_colhead1", + "grid_colhead2", + "grid_colhead3", + "grid_rowhead", + "grid_cell1", + "grid_cell2", + ]); + }, + { + chrome: true, + topLevel: true, + iframe: true, + remoteIframe: true, + } +); diff --git a/accessible/tests/browser/selectable/browser_test_select.js b/accessible/tests/browser/selectable/browser_test_select.js new file mode 100644 index 0000000000..f86a371d81 --- /dev/null +++ b/accessible/tests/browser/selectable/browser_test_select.js @@ -0,0 +1,329 @@ +/* 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/selectable.js */ +/* import-globals-from ../../mochitest/states.js */ + +// //////////////////////////////////////////////////////////////////////// +// select@size="1" aka combobox +addAccessibleTask( + `<select id="combobox"> + <option id="item1">option1</option> + <option id="item2">option2</option> + </select>`, + async function (browser, docAcc) { + info("select@size='1' aka combobox"); + let combobox = findAccessibleChildByID(docAcc, "combobox"); + let comboboxList = combobox.firstChild; + ok( + isAccessible(comboboxList, [nsIAccessibleSelectable]), + "No selectable accessible for combobox" + ); + + let select = getAccessible(comboboxList, [nsIAccessibleSelectable]); + testSelectableSelection(select, ["item1"]); + + // select 2nd item + let promise = Promise.all([ + waitForStateChange("item2", STATE_SELECTED, true), + waitForStateChange("item1", STATE_SELECTED, false), + ]); + select.addItemToSelection(1); + await promise; + testSelectableSelection(select, ["item2"], "addItemToSelection(1): "); + + // unselect 2nd item, 1st item gets selected automatically + promise = Promise.all([ + waitForStateChange("item2", STATE_SELECTED, false), + waitForStateChange("item1", STATE_SELECTED, true), + ]); + select.removeItemFromSelection(1); + await promise; + testSelectableSelection(select, ["item1"], "removeItemFromSelection(1): "); + + // doesn't change selection + is(select.selectAll(), false, "No way to select all items in combobox"); + testSelectableSelection(select, ["item1"], "selectAll: "); + + // doesn't change selection + select.unselectAll(); + testSelectableSelection(select, ["item1"], "unselectAll: "); + }, + { + chrome: true, + topLevel: true, + iframe: true, + remoteIframe: true, + } +); + +// //////////////////////////////////////////////////////////////////////// +// select@size="1" with optgroups +addAccessibleTask( + `<select id="combobox"> + <option id="item1">option1</option> + <optgroup>optgroup + <option id="item2">option2</option> + </optgroup> + </select>`, + async function (browser, docAcc) { + info("select@size='1' with optgroups"); + let combobox = findAccessibleChildByID(docAcc, "combobox"); + let comboboxList = combobox.firstChild; + ok( + isAccessible(comboboxList, [nsIAccessibleSelectable]), + "No selectable accessible for combobox" + ); + + let select = getAccessible(comboboxList, [nsIAccessibleSelectable]); + testSelectableSelection(select, ["item1"]); + + let promise = Promise.all([ + waitForStateChange("item2", STATE_SELECTED, true), + waitForStateChange("item1", STATE_SELECTED, false), + ]); + select.addItemToSelection(1); + await promise; + testSelectableSelection(select, ["item2"], "addItemToSelection(1): "); + + promise = Promise.all([ + waitForStateChange("item2", STATE_SELECTED, false), + waitForStateChange("item1", STATE_SELECTED, true), + ]); + select.removeItemFromSelection(1); + await promise; + testSelectableSelection(select, ["item1"], "removeItemFromSelection(1): "); + + is(select.selectAll(), false, "No way to select all items in combobox"); + testSelectableSelection(select, ["item1"]); + + select.unselectAll(); + testSelectableSelection(select, ["item1"]); + }, + { + chrome: true, + topLevel: true, + iframe: true, + remoteIframe: true, + } +); + +// //////////////////////////////////////////////////////////////////////// +// select@size="4" aka single selectable listbox +addAccessibleTask( + `<select id="listbox" size="4"> + <option id="item1">option1</option> + <option id="item2">option2</option> + </select>`, + async function (browser, docAcc) { + info("select@size='4' aka single selectable listbox"); + let select = findAccessibleChildByID(docAcc, "listbox", [ + nsIAccessibleSelectable, + ]); + testSelectableSelection(select, []); + + // select 2nd item + let promise = waitForStateChange("item2", STATE_SELECTED, true); + select.addItemToSelection(1); + await promise; + testSelectableSelection(select, ["item2"], "addItemToSelection(1): "); + + // unselect 2nd item, 1st item gets selected automatically + promise = waitForStateChange("item2", STATE_SELECTED, false); + select.removeItemFromSelection(1); + await promise; + testSelectableSelection(select, [], "removeItemFromSelection(1): "); + + // doesn't change selection + is( + select.selectAll(), + false, + "No way to select all items in single selectable listbox" + ); + testSelectableSelection(select, [], "selectAll: "); + + // doesn't change selection + select.unselectAll(); + testSelectableSelection(select, [], "unselectAll: "); + }, + { + chrome: true, + topLevel: true, + iframe: true, + remoteIframe: true, + } +); + +// //////////////////////////////////////////////////////////////////////// +// select@size="4" with optgroups, single selectable +addAccessibleTask( + `<select id="listbox" size="4"> + <option id="item1">option1</option> + <optgroup>optgroup> + <option id="item2">option2</option> + </optgroup> + </select>`, + async function (browser, docAcc) { + info("select@size='4' with optgroups, single selectable"); + let select = findAccessibleChildByID(docAcc, "listbox", [ + nsIAccessibleSelectable, + ]); + testSelectableSelection(select, []); + + let promise = waitForStateChange("item2", STATE_SELECTED, true); + select.addItemToSelection(1); + await promise; + testSelectableSelection(select, ["item2"]); + + promise = waitForStateChange("item2", STATE_SELECTED, false); + select.removeItemFromSelection(1); + await promise; + testSelectableSelection(select, []); + + is( + select.selectAll(), + false, + "No way to select all items in single selectable listbox" + ); + testSelectableSelection(select, []); + + select.unselectAll(); + testSelectableSelection(select, []); + }, + { + chrome: true, + topLevel: true, + iframe: true, + remoteIframe: true, + } +); + +// //////////////////////////////////////////////////////////////////////// +// select@size="4" multiselect aka listbox +addAccessibleTask( + `<select id="listbox" size="4" multiple="true"> + <option id="item1">option1</option> + <option id="item2">option2</option> + </select>`, + async function (browser, docAcc) { + info("select@size='4' multiselect aka listbox"); + let select = findAccessibleChildByID(docAcc, "listbox", [ + nsIAccessibleSelectable, + ]); + await testMultiSelectable( + select, + ["item1", "item2"], + "select@size='4' multiselect aka listbox " + ); + }, + { + chrome: true, + topLevel: true, + iframe: true, + remoteIframe: true, + } +); + +// //////////////////////////////////////////////////////////////////////// +// select@size="4" multiselect with optgroups +addAccessibleTask( + `<select id="listbox" size="4" multiple="true"> + <option id="item1">option1</option> + <optgroup>optgroup> + <option id="item2">option2</option> + </optgroup> + </select>`, + async function (browser, docAcc) { + info("select@size='4' multiselect with optgroups"); + let select = findAccessibleChildByID(docAcc, "listbox", [ + nsIAccessibleSelectable, + ]); + await testMultiSelectable( + select, + ["item1", "item2"], + "select@size='4' multiselect aka listbox " + ); + }, + { + chrome: true, + topLevel: true, + iframe: true, + remoteIframe: true, + } +); + +// //////////////////////////////////////////////////////////////////////// +// multiselect with coalesced selection event +addAccessibleTask( + `<select id="listbox" size="4" multiple="true"> + <option id="item1">option1</option> + <option id="item2">option2</option> + <option id="item3">option3</option> + <option id="item4">option4</option> + <option id="item5">option5</option> + <option id="item6">option6</option> + <option id="item7">option7</option> + <option id="item8">option8</option> + <option id="item9">option9</option> + </select>`, + async function (browser, docAcc) { + info("select@size='4' multiselect with coalesced selection event"); + let select = findAccessibleChildByID(docAcc, "listbox", [ + nsIAccessibleSelectable, + ]); + await testMultiSelectable( + select, + [ + "item1", + "item2", + "item3", + "item4", + "item5", + "item6", + "item7", + "item8", + "item9", + ], + "select@size='4' multiselect with coalesced selection event " + ); + }, + { + chrome: false, + topLevel: true, + iframe: false, + remoteIframe: false, + } +); + +/** + * Ensure that we don't assert when dealing with defunct items in selection + * events dropped due to coalescence (bug 1800755). + */ +addAccessibleTask( + ` +<form id="form"> + <select id="select"> + <option> + <optgroup id="optgroup"> + <option> + </optgroup> + </select> +</form> + `, + async function (browser, docAcc) { + let selected = waitForEvent(EVENT_SELECTION_WITHIN, "select"); + await invokeContentTask(browser, [], () => { + const form = content.document.getElementById("form"); + const select = content.document.getElementById("select"); + const optgroup = content.document.getElementById("optgroup"); + form.reset(); + select.selectedIndex = 1; + select.add(optgroup); + select.item(0).remove(); + }); + await selected; + } +); diff --git a/accessible/tests/browser/selectable/head.js b/accessible/tests/browser/selectable/head.js new file mode 100644 index 0000000000..ccf9e86f77 --- /dev/null +++ b/accessible/tests/browser/selectable/head.js @@ -0,0 +1,88 @@ +/* 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"; + +/* exported testMultiSelectable */ + +// Load the shared-head file first. +Services.scriptloader.loadSubScript( + "chrome://mochitests/content/browser/accessible/tests/browser/shared-head.js", + this +); + +// Loading and common.js from accessible/tests/mochitest/ for all tests, as +// well as promisified-events.js. +/* import-globals-from ../../mochitest/selectable.js */ +/* import-globals-from ../../mochitest/states.js */ +loadScripts( + { name: "common.js", dir: MOCHITESTS_DIR }, + { name: "promisified-events.js", dir: MOCHITESTS_DIR }, + { name: "selectable.js", dir: MOCHITESTS_DIR }, + { name: "states.js", dir: MOCHITESTS_DIR }, + { name: "role.js", dir: MOCHITESTS_DIR } +); + +// Handle case where multiple selection change events are coalesced into +// a SELECTION_WITHIN event. Promise resolves to true in that case. +function multipleSelectionChanged(widget, changedChildren, selected) { + return Promise.race([ + Promise.all( + changedChildren.map(id => + waitForStateChange(id, STATE_SELECTED, selected) + ) + ).then(() => false), + waitForEvent(EVENT_SELECTION_WITHIN, widget).then(() => true), + ]); +} + +async function testMultiSelectable(widget, selectableChildren, msg = "") { + let isRemote = false; + try { + widget.DOMNode; + } catch (e) { + isRemote = true; + } + + testSelectableSelection(widget, [], `${msg}: initial`); + + let promise = waitForStateChange(selectableChildren[0], STATE_SELECTED, true); + widget.addItemToSelection(0); + await promise; + testSelectableSelection( + widget, + [selectableChildren[0]], + `${msg}: addItemToSelection(0)` + ); + + promise = waitForStateChange(selectableChildren[0], STATE_SELECTED, false); + widget.removeItemFromSelection(0); + await promise; + testSelectableSelection(widget, [], `${msg}: removeItemFromSelection(0)`); + + promise = multipleSelectionChanged(widget, selectableChildren, true); + let success = widget.selectAll(); + ok(success, `${msg}: selectAll success`); + await promise; + if (isRemote) { + await untilCacheIs( + () => widget.selectedItemCount, + selectableChildren.length, + "Selection cache updated" + ); + } + testSelectableSelection(widget, selectableChildren, `${msg}: selectAll`); + + promise = multipleSelectionChanged(widget, selectableChildren, false); + widget.unselectAll(); + await promise; + if (isRemote) { + await untilCacheIs( + () => widget.selectedItemCount, + 0, + "Selection cache updated" + ); + } + testSelectableSelection(widget, [], `${msg}: selectAll`); +} |