diff options
Diffstat (limited to 'accessible/tests/mochitest/textselection/test_general.html')
-rw-r--r-- | accessible/tests/mochitest/textselection/test_general.html | 221 |
1 files changed, 221 insertions, 0 deletions
diff --git a/accessible/tests/mochitest/textselection/test_general.html b/accessible/tests/mochitest/textselection/test_general.html new file mode 100644 index 0000000000..92e7988a87 --- /dev/null +++ b/accessible/tests/mochitest/textselection/test_general.html @@ -0,0 +1,221 @@ +<html> + +<head> + <title>Text selection testing</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 type="application/javascript" + src="../common.js"></script> + <script type="application/javascript" + src="../promisified-events.js"></script> + + <script type="application/javascript"> + /** + * Helper function to test selection bounds. + * @param {string} aID The ID to test. + * @param {nsIAccessibleText} acc The accessible to test. + * @param {int} index The selection's index to test. + * @param {array} offsets The start and end offset to test against. + * @param {string} msgStart The start of the message to return in test + * messages. + */ + function testSelectionBounds(aID, acc, index, offsets, msgStart) { + const [expectedStart, expectedEnd] = offsets; + const startOffset = {}, endOffset = {}; + acc.getSelectionBounds(index, startOffset, endOffset); + + is(startOffset.value, Math.min(expectedStart, expectedEnd), + msgStart + ": Wrong start offset for " + aID); + is(endOffset.value, Math.max(expectedStart, expectedEnd), + msgStart + ": Wrong end offset for " + aID); + } + + /** + * Test adding selections to accessibles. + * @param {string} aID The ID of the element to test. + * @param {array} aSelections Array of selection start and end indices. + */ + async function addSelections(aID, aSelections) { + info("Test adding selections to " + aID); + const hyperText = getAccessible(aID, [ nsIAccessibleText ]); + const initialSelectionCount = hyperText.selectionCount; + + // Multiple selection changes will be coalesced, so just listen for one. + const selectionChange = waitForEvent(EVENT_TEXT_SELECTION_CHANGED, aID); + for (let [startOffset, endOffset] of aSelections) { + hyperText.addSelection(startOffset, endOffset); + } + await selectionChange; + + is(hyperText.selectionCount, + aSelections.length + initialSelectionCount, + "addSelection: Wrong selection count for " + aID); + + for (let i in aSelections) { + testSelectionBounds(aID, hyperText, initialSelectionCount + i, + aSelections[i], "addSelection"); + } + + is(hyperText.caretOffset, aSelections[hyperText.selectionCount -1][1], + "addSelection: caretOffset not at selection end for " + aID); + } + + /** + * Test changing selections in accessibles. + * @param {string} aID The ID of the element to test. + * @param {int} aIndex The index of the selection to change. + * @param {array} aSelection Array of the selection's new start and end + * indices. + */ + async function changeSelection(aID, aIndex, aSelection) { + info("Test changing the selection of " + aID + " at index " + aIndex); + const [startOffset, endOffset] = aSelection; + const hyperText = getAccessible(aID, [ nsIAccessibleText ]); + + const selectionChanged = waitForEvent(EVENT_TEXT_SELECTION_CHANGED, aID); + hyperText.setSelectionBounds(aIndex, startOffset, endOffset); + await selectionChanged; + + testSelectionBounds(aID, hyperText, aIndex, + aSelection, "setSelectionBounds"); + + is(hyperText.caretOffset, endOffset, + "setSelectionBounds: caretOffset not at selection end for " + aID); + } + + /** + * Test removing all selections from accessibles. + * @param {string} aID The ID of the element to test. + */ + async function removeSelections(aID) { + info("Testing removal of all selections from " + aID); + const hyperText = getAccessible(aID, [ nsIAccessibleText ]); + + let selectionsRemoved = waitForEvent(EVENT_TEXT_SELECTION_CHANGED, document); + const selectionCount = hyperText.selectionCount; + for (let i = 0; i < selectionCount; i++) { + hyperText.removeSelection(0); + } + await selectionsRemoved; + + is(hyperText.selectionCount, 0, + "removeSelection: Wrong selection count for " + aID); + } + + /** + * Test that changing the DOM selection is reflected in the accessibles. + * @param {string} aID The container ID to test in + * @param {string} aNodeID1 The start node of the selection + * @param {int} aNodeOffset1 The offset where the selection should start + * @param {string} aNodeID2 The node in which the selection should end + * @param {int} aNodeOffset2 The index at which the selection should end + * @param {array} aTests An array of accessibles and their start and end + * offsets to test. + */ + async function changeDOMSelection(aID, aNodeID1, aNodeOffset1, + aNodeID2, aNodeOffset2, + aTests) { + info("Test that DOM selection changes are reflected in the accessibles"); + + let selectionChanged = waitForEvent(EVENT_TEXT_SELECTION_CHANGED, aID); + // HyperTextAccessible::GetSelectionDOMRanges ignores hidden selections. + // Here we may be focusing an editable element (and thus hiding the + // main document selection), so blur it so that we test what we want to + // test. + document.activeElement.blur(); + + const sel = window.getSelection(); + const range = document.createRange(); + range.setStart(getNode(aNodeID1), aNodeOffset1); + range.setEnd(getNode(aNodeID2), aNodeOffset2); + sel.addRange(range); + await selectionChanged; + + for (let i = 0; i < aTests.length; i++) { + const text = getAccessible(aTests[i][0], nsIAccessibleText); + is(text.selectionCount, 1, + "setSelectionBounds: Wrong selection count for " + aID); + testSelectionBounds(aID, text, 0, [aTests[i][1], aTests[i][2]], + "setSelectionBounds"); + } + } + + /** + * Test expected and unexpected events for selecting + * all text and focusing both an input and text area. We expect a caret + * move, but not a text selection change. + * @param {string} aID The ID of the element to test. + */ + async function eventsForSelectingAllTextAndFocus(aID) { + info("Test expected caretMove and unexpected textSelection events for " +aID); + let events = waitForEvents({ + expected: [[EVENT_TEXT_CARET_MOVED, aID]], + unexpected: [[EVENT_TEXT_SELECTION_CHANGED, aID]]}, aID); + selectAllTextAndFocus(aID); + await events; + } + + /** + * Do tests + */ + + async function doTests() { + await addSelections("paragraph", [[1, 3], [6, 10]]); + await changeSelection("paragraph", 0, [2, 4]); + await removeSelections("paragraph"); + + // reverse selection + await addSelections("paragraph", [[1, 3], [10, 6]]); + await removeSelections("paragraph"); + + await eventsForSelectingAllTextAndFocus("textbox"); + await changeSelection("textbox", 0, [1, 3]); + + // reverse selection + await changeSelection("textbox", 0, [3, 1]); + + await eventsForSelectingAllTextAndFocus("textarea"); + await changeSelection("textarea", 0, [1, 3]); + + await changeDOMSelection("c1", "c1_span1", 0, "c1_span2", 0, + [["c1", 2, 2]]); + await changeDOMSelection("c2", "c2", 0, "c2_div2", 1, + [["c2", 0, 3], ["c2_div2", 0, 2]]); + + SimpleTest.finish(); + } + + SimpleTest.waitForExplicitFinish(); + addA11yLoadEvent(doTests); + </script> +</head> + +<body> + + <a target="_blank" + href="https://bugzilla.mozilla.org/show_bug.cgi?id=688126" + title="nsIAccessibleText::setSelectionBounds doesn't fire text selection changed events in some cases"> + Bug 688126 + </a> + <a target="_blank" + href="https://bugzilla.mozilla.org/show_bug.cgi?id=688124" + title="no text selection changed event when selection is removed"> + Bug 688124 + </a> + <p id="display"></p> + <div id="content" style="display: none"></div> + <pre id="test"> + </pre> + + <p id="paragraph">hello world</p> + <input id="textbox" value="hello"/> + <textarea id="textarea">hello</textarea> + <div id="c1">hi<span id="c1_span1"></span><span id="c1_span2"></span>hi</div> + <div id="c2">hi<div id="c2_div2">hi</div></div> + +</body> +</html> |