diff options
Diffstat (limited to 'dom/tests/mochitest/general/frameSelectEvents.html')
-rw-r--r-- | dom/tests/mochitest/general/frameSelectEvents.html | 467 |
1 files changed, 467 insertions, 0 deletions
diff --git a/dom/tests/mochitest/general/frameSelectEvents.html b/dom/tests/mochitest/general/frameSelectEvents.html new file mode 100644 index 000000000..c53bdb5e7 --- /dev/null +++ b/dom/tests/mochitest/general/frameSelectEvents.html @@ -0,0 +1,467 @@ +<!doctype html> +<html> + <head> + <title>Testing Selection Events</title> + <script type="text/javascript" src="/tests/SimpleTest/EventUtils.js"></script> + <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" /> + </head> + + <body> + <div id="normal"> + <span id="inner">A bunch of text in a span inside of a div which should be selected</span> + </div> + + <div id="ce"> + This is a random block of text + </div> + + <input type="text" id="input" value="XXXXXXXXXXXXXXXXXXX" width="200"> <br> + + <textarea id="textarea" width="200">XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX</textarea> + + <script> + // Call the testing methods from the parent window + var is = parent.is; + var ok = parent.ok; + + // spin() spins the event loop for two cycles, giving time for + // selectionchange events to be fired, and handled by our listeners. + function spin() { + return new Promise(function(a) { + parent.SimpleTest.executeSoon(function() { + parent.SimpleTest.executeSoon(a) + }); + }); + } + + // The main test + parent.add_task(function *() { + yield spin(); + + var selectstart = 0; + var selectionchange = 0; + var inputSelectionchange = 0; + var textareaSelectionchange = 0; + + var cancel = false; + var selectstartTarget = null; + + function* UpdateSelectEventsOntextControlsPref(aEnabled) { + yield SpecialPowers.pushPrefEnv({'set': [['dom.select_events.textcontrols.enabled', aEnabled]]}); + } + yield* UpdateSelectEventsOntextControlsPref(false); + + document.addEventListener('selectstart', function(aEvent) { + console.log("originaltarget", aEvent.originalTarget, "new", selectstartTarget); + is(aEvent.originalTarget, selectstartTarget, + "The original target of selectstart"); + selectstartTarget = null; + + console.log(selectstart); + selectstart++; + + if (cancel) { + aEvent.preventDefault(); + } + }); + document.addEventListener('selectionchange', function(aEvent) { + is(aEvent.originalTarget, document, + "The original target of selectionchange should be the document"); + console.log(selectionchange); + selectionchange++; + }); + + function elt(aId) { return document.getElementById(aId); } + function reset() { + selectstart = 0; + selectionchange = 0; + inputSelectionchange = 0; + textareaSelectionchange = 0; + cancel = false; + } + + elt("input").addEventListener('selectionchange', function(aEvent) { + is (aEvent.originalTarget, elt("input"), + "The original target of selectionchange should be the input"); + console.log(inputSelectionchange); + inputSelectionchange++; + }); + elt("textarea").addEventListener('selectionchange', function(aEvent) { + is (aEvent.originalTarget, elt("textarea"), + "The original target of selectionchange should be the textarea"); + console.log(textareaSelectionchange); + textareaSelectionchange++; + }); + function* mouseAction(aElement, aOffset, aType, + aSelStart, aSelChng, aISelChng, aTSelChng, + aYOffset) + { + if (aType == "click") { // You can simulate a click event by sending undefined + aType = undefined; + } + if (!aYOffset) { + aYOffset = 10; + } + synthesizeMouse(aElement, aOffset, aYOffset, { type: aType }); + yield spin(); + + is(selectstart, aSelStart, + "SelStart Mouse Action (" + aOffset + " - " + aType + ")"); + is(selectionchange, aSelChng, + "SelChng Mouse Action (" + aOffset + " - " + aType + ")"); + is(inputSelectionchange, aISelChng || 0, + "ISelChng Mouse Action (" + aOffset + " - " + aType + ")"); + is(textareaSelectionchange, aTSelChng || 0, + "TSelChng Mouse Action (" + aOffset + " - " + aType + ")"); + reset(); + } + + function* keyAction(aKey, aShift, aAccel, + aSelStart, aSelChng, aISelChng, aTSelChng) + { + synthesizeKey(aKey, { shiftKey: aShift, accelKey: aAccel }); + yield spin(); + is(selectstart, aSelStart, + "SelStart Key Action (" + aKey + " - " + aShift + " - " + aAccel + ")"); + is(selectionchange, aSelChng, + "SelChng Key Action (" + aKey + " - " + aShift + " - " + aAccel + ")"); + is(inputSelectionchange, aISelChng || 0, + "ISelChng Key Action (" + aKey + " - " + aShift + " - " + aAccel + ")"); + is(textareaSelectionchange, aTSelChng || 0, + "TSelChng Key Action (" + aKey + " - " + aShift + " - " + aAccel + ")"); + reset(); + } + + function* contentEditableAction(aElement, aContentEditable, + aSelStart, aSelChng, + aISelChng, aTSelChng) + { + aElement.setAttribute("contenteditable", + aContentEditable ? "true" : "false"); + yield spin(); + + is(selectstart, aSelStart, + "SelStart ContentEditable Action"); + is(selectionchange, aSelChng, + "SelStart ContentEditable Action"); + is(inputSelectionchange, aISelChng || 0, + "SelStart ContentEditable Action"); + is(textareaSelectionchange, aTSelChng || 0, + "SelStart ContentEditable Action"); + reset(); + } + + var selection = document.getSelection(); + function isCollapsed() { + is(selection.isCollapsed, true, "Selection is collapsed"); + } + function isNotCollapsed() { + is(selection.isCollapsed, false, "Selection is not collapsed"); + } + + // Make sure setting the element to contentEditable doesn't cause any selectionchange events + yield* contentEditableAction(elt("ce"), true, 0, 0, 0, 0); + + // Make sure setting the element to not be contentEditable doesn't cause any selectionchange events + yield* contentEditableAction(elt("ce"), false, 0, 0, 0, 0); + + // Now make the div contentEditable and proceed with the test + yield* contentEditableAction(elt("ce"), true, 0, 0, 0, 0); + + // Focus the contenteditable text + yield* mouseAction(elt("ce"), 100, "click", 0, 1); + isCollapsed(); + + // Move the selection to the right, this should only fire selectstart once + selectstartTarget = elt("ce").firstChild; + yield* keyAction("VK_RIGHT", true, false, 1, 1); + isNotCollapsed(); + yield* keyAction("VK_RIGHT", true, false, 0, 1); + isNotCollapsed(); + + // Move it back so that the selection is empty again + yield* keyAction("VK_LEFT", true, false, 0, 1); + isNotCollapsed(); + yield* keyAction("VK_LEFT", true, false, 0, 1); + isCollapsed(); + + // Going from empty to non-empty should fire selectstart again + selectstartTarget = elt("ce").firstChild; + yield* keyAction("VK_LEFT", true, false, 1, 1); + isNotCollapsed(); + + function* mouseMoves(aElement, aTarget) { + // Select a region + yield* mouseAction(aElement, 50, "mousedown", 0, 1); + isCollapsed(); + + selectstartTarget = aTarget; + yield* mouseAction(aElement, 100, "mousemove", 1, 1); + isNotCollapsed(); + + // Moving it more shouldn't trigger a start (move back to empty) + yield* mouseAction(aElement, 75, "mousemove", 0, 1); + isNotCollapsed(); + yield* mouseAction(aElement, 50, "mousemove", 0, 1); + isCollapsed(); + + // Wiggling the mouse a little such that it doesn't select any + // characters shouldn't trigger a selection + yield* mouseAction(aElement, 50, "mousemove", 0, 0, 0, 0, 11); + isCollapsed(); + + // Moving the mouse again from an empty selection should trigger a + // selectstart + selectstartTarget = aTarget; + yield* mouseAction(aElement, 25, "mousemove", 1, 1); + isNotCollapsed(); + + // Releasing the mouse shouldn't do anything + yield* mouseAction(aElement, 25, "mouseup", 0, 0); + isNotCollapsed(); + + // And neither should moving your mouse around when the mouse + // button isn't pressed + yield* mouseAction(aElement, 50, "mousemove", 0, 0); + isNotCollapsed(); + + // Clicking in an random location should move the selection, but not perform a + // selectstart + yield* mouseAction(aElement, 50, "click", 0, 1); + isCollapsed(); + + // Clicking there again should do nothing + yield* mouseAction(aElement, 50, "click", 0, 0); + isCollapsed(); + + // Selecting a region, and canceling the selectstart should mean that the + // selection remains collapsed + yield* mouseAction(aElement, 75, "mousedown", 0, 1); + isCollapsed(); + cancel = true; + selectstartTarget = aTarget; + yield* mouseAction(aElement, 100, "mousemove", 1, 1); + isCollapsed(); + yield* mouseAction(aElement, 100, "mouseup", 0, 0); + isCollapsed(); + } + + // Should work both on normal + yield* mouseMoves(elt("inner"), elt("inner").firstChild); + // and contenteditable fields + yield* mouseMoves(elt("ce"), elt("ce").firstChild); + // and fields with elements in them + yield* mouseMoves(elt("normal"), elt("inner").firstChild); + + yield* mouseAction(elt("inner"), 50, "click", 0, 1); + isCollapsed(); + + reset(); + // Select all should fire both selectstart and change + selectstartTarget = document.body; + yield* keyAction("A", false, true, 1, 1); + isNotCollapsed(); + + // Clear the selection + yield* mouseAction(elt("inner"), 50, "click", 0, 1); + isCollapsed(); + + // Even if we already have a selection + yield* mouseAction(elt("inner"), 75, "mousedown", 0, 1); + isCollapsed(); + selectstartTarget = elt("inner").firstChild; + yield* mouseAction(elt("inner"), 100, "mousemove", 1, 1); + isNotCollapsed(); + yield* mouseAction(elt("inner"), 100, "mouseup", 0, 0); + isNotCollapsed(); + + selectstartTarget = document.body; + yield* keyAction("A", false, true, 1, 1); + isNotCollapsed(); + + // Clear the selection + yield* mouseAction(elt("inner"), 50, "click", 0, 1); + isCollapsed(); + + // Make sure that a synthesized selection change doesn't fire selectstart + var s = document.getSelection(); + s.removeAllRanges(); + yield spin(); + is(selectstart, 0, "Synthesized range removals shouldn't fire selectstart"); + is(selectionchange, 1, "Synthesized range removals should change selectionchange"); + reset(); + isCollapsed(); + + var range = document.createRange(); + range.selectNode(elt("inner")); + s.addRange(range); + yield spin(); + is(selectstart, 0, "Synthesized range additions shouldn't fire selectstart"); + is(selectionchange, 1, "Synthesized range additions should change selectionchange"); + reset(); + isNotCollapsed(); + + // Change the range, without replacing + range.selectNode(elt("ce")); + yield spin(); + is(selectstart, 0, "Synthesized range mutations shouldn't fire selectstart"); + is(selectionchange, 1, "Synthesized range mutations should change selectionchange"); + reset(); + isNotCollapsed(); + + // Remove the range + s.removeAllRanges(); + yield spin(); + is(selectstart, 0, "Synthesized range removal"); + is(selectionchange, 1, "Synthesized range removal"); + reset(); + isCollapsed(); + + + /* + Selection events mouse move on input type=text + */ + + // Select a region + + // Without the dom.select_events.textcontrols.enabled pref, + // pressing the mouse shouldn't do anything. + yield* mouseAction(elt("input"), 50, "mousedown", 0, 1, 0, 0); + + // Releasing the mouse shouldn't do anything + yield* mouseAction(elt("input"), 50, "mouseup", 0, 0, 0, 0); + + yield* UpdateSelectEventsOntextControlsPref(true); + + yield* mouseAction(elt("input"), 50, "mousedown", 0, 0, 0, 0); + + selectstartTarget = elt("input"); + yield* mouseAction(elt("input"), 100, "mousemove", 1, 0, 1, 0); + + // Moving it more shouldn't trigger a start (move back to empty) + yield* mouseAction(elt("input"), 75, "mousemove", 0, 0, 1, 0); + yield* mouseAction(elt("input"), 50, "mousemove", 0, 0, 1, 0); + + // Wiggling the mouse a little such that it doesn't select any + // characters shouldn't trigger a selection + yield* mouseAction(elt("input"), 50, "mousemove", 0, 0, 0, 0, 11); + + // Moving the mouse again from an empty selection should trigger a + // selectstart + selectstartTarget = elt("input"); + yield* mouseAction(elt("input"), 25, "mousemove", 1, 0, 1, 0); + + // Releasing the mouse shouldn't do anything + yield* mouseAction(elt("input"), 25, "mouseup", 0, 0, 0, 0); + + // And neither should moving your mouse around when the mouse + // button isn't pressed + yield* mouseAction(elt("input"), 50, "mousemove", 0, 0, 0, 0); + + // Clicking in an random location should move the selection, but + // not perform a selectstart + yield* mouseAction(elt("input"), 50, "click", 0, 0, 1, 0); + + // Clicking there again should do nothing + yield* mouseAction(elt("input"), 50, "click", 0, 0, 0, 0); + + // Selecting a region, and canceling the selectstart should mean that the + // selection remains collapsed + yield* mouseAction(elt("input"), 75, "mousedown", 0, 0, 1, 0); + cancel = true; + selectstartTarget = elt("input"); + yield* mouseAction(elt("input"), 100, "mousemove", 1, 0, 1, 0); + yield* mouseAction(elt("input"), 100, "mouseup", 0, 0, 0, 0); + + + yield* UpdateSelectEventsOntextControlsPref(false); + + // Without the dom.select_events.textcontrols.enabled pref, + // pressing the mouse shouldn't do anything. + // XXX For some reason we fire 2 selectchange events on the body + // when switching from the input to the text area. + yield* mouseAction(elt("textarea"), 50, "mousedown", 0, 2, 0, 0); + + // Releasing the mouse shouldn't do anything + yield* mouseAction(elt("textarea"), 50, "mouseup", 0, 0, 0, 0); + + yield* UpdateSelectEventsOntextControlsPref(true); + + // Select a region + yield* mouseAction(elt("textarea"), 50, "mousedown", 0, 0, 0, 0); + + selectstartTarget = elt("textarea"); + yield* mouseAction(elt("textarea"), 100, "mousemove", 1, 0, 0, 1); + + // Moving it more shouldn't trigger a start (move back to empty) + yield* mouseAction(elt("textarea"), 75, "mousemove", 0, 0, 0, 1); + yield* mouseAction(elt("textarea"), 50, "mousemove", 0, 0, 0, 1); + + // Wiggling the mouse a little such that it doesn't select any + // characters shouldn't trigger a selection + yield* mouseAction(elt("textarea"), 50, "mousemove", 0, 0, 0, 0, 11); + + // Moving the mouse again from an empty selection should trigger a + // selectstart + selectstartTarget = elt("textarea"); + yield* mouseAction(elt("textarea"), 25, "mousemove", 1, 0, 0, 1); + + // Releasing the mouse shouldn't do anything + yield* mouseAction(elt("textarea"), 25, "mouseup", 0, 0, 0, 0); + + // And neither should moving your mouse around when the mouse + // button isn't pressed + yield* mouseAction(elt("textarea"), 50, "mousemove", 0, 0, 0, 0); + + // Clicking in an random location should move the selection, but not perform a + // selectstart + yield* mouseAction(elt("textarea"), 50, "click", 0, 0, 0, 1); + + // Clicking there again should do nothing + yield* mouseAction(elt("textarea"), 50, "click", 0, 0, 0, 0); + + // Selecting a region, and canceling the selectstart should mean that the + // selection remains collapsed + yield* mouseAction(elt("textarea"), 75, "mousedown", 0, 0, 0, 1); + cancel = true; + selectstartTarget = elt("textarea"); + yield* mouseAction(elt("textarea"), 100, "mousemove", 1, 0, 0, 1); + yield* mouseAction(elt("textarea"), 100, "mouseup", 0, 0, 0, 0); + + // Marking the input and textarea as display: none and then as visible again + // shouldn't trigger any changes, although the nodes will be re-framed + elt("input").setAttribute("style", "display: none;"); + yield spin(); + is(selectstart, 0, "idn - ss 1"); + is(selectionchange, 0, "idn - sc 1"); + is(inputSelectionchange, 0, "idn - isc 1"); + is(textareaSelectionchange, 0, "idn - tsc 1"); + reset(); + + elt("input").setAttribute("style", ""); + yield spin(); + is(selectstart, 0, "idn - ss 2"); + is(selectionchange, 0, "idn - sc 2"); + is(inputSelectionchange, 0, "idn - isc 2"); + is(textareaSelectionchange, 0, "idn - tsc 2"); + reset(); + + elt("textarea").setAttribute("style", "display: none;"); + yield spin(); + is(selectstart, 0, "tdn - ss 1"); + is(selectionchange, 0, "tdn - sc 1"); + is(inputSelectionchange, 0, "tdn - isc 1"); + is(textareaSelectionchange, 0, "tdn - tsc 1"); + reset(); + + elt("textarea").setAttribute("style", ""); + yield spin(); + is(selectstart, 0, "tdn - ss 2"); + is(selectionchange, 0, "tdn - sc 2"); + is(inputSelectionchange, 0, "tdn - isc 2"); + is(textareaSelectionchange, 0, "tdn - tsc 2"); + reset(); + }); + </script> + </body> +</html> |