summaryrefslogtreecommitdiffstats
path: root/dom/tests/mochitest/general/frameSelectEvents.html
diff options
context:
space:
mode:
Diffstat (limited to 'dom/tests/mochitest/general/frameSelectEvents.html')
-rw-r--r--dom/tests/mochitest/general/frameSelectEvents.html929
1 files changed, 929 insertions, 0 deletions
diff --git a/dom/tests/mochitest/general/frameSelectEvents.html b/dom/tests/mochitest/general/frameSelectEvents.html
new file mode 100644
index 0000000000..21995c86ef
--- /dev/null
+++ b/dom/tests/mochitest/general/frameSelectEvents.html
@@ -0,0 +1,929 @@
+<!doctype html>
+<html>
+ <head>
+ <title>Testing Selection Events</title>
+ <script 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)
+ });
+ });
+ }
+
+ /**
+ * @param {Node} node
+ */
+ function isProperSelectionChangeTarget(node) {
+ return node === document || node === input || node === textarea;
+ }
+
+ // The main test
+ parent.add_task(async function() {
+ await spin();
+
+ var selectstart = 0;
+ var selectionchange = 0;
+ var inputSelectionchange = 0;
+ var textareaSelectionchange = 0;
+
+ var cancel = false;
+ var selectstartTarget = null;
+
+ async function UpdateSelectEventsOnTextControlsPref({ selectstart, selectionchange }) {
+ await SpecialPowers.pushPrefEnv({
+ 'set': [
+ ['dom.select_events.textcontrols.selectstart.enabled', !!selectstart],
+ ['dom.select_events.textcontrols.selectionchange.enabled', !!selectionchange],
+ ]
+ });
+ }
+ await UpdateSelectEventsOnTextControlsPref({
+ selectstart: false,
+ selectionchange: 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) {
+ ok(isProperSelectionChangeTarget(aEvent.target),
+ "The target of selectionchange should be one of document, input, or textarea");
+ 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 checkEventCounts(
+ aTestDescription,
+ aSituationDescription,
+ aExpectedEventCounts
+ ) {
+ let {
+ selectstartOnDocument = 0,
+ selectionchangeOnDocument = 0,
+ selectionchangeOnInput = 0,
+ selectionchangeOnTextarea = 0,
+ } = aExpectedEventCounts;
+
+ is(
+ selectstart,
+ selectstartOnDocument,
+ `${
+ aTestDescription
+ }: "selectstart" event on the document node should be fired ${
+ selectstartOnDocument
+ } times ${aSituationDescription}`
+ );
+ is(
+ selectionchange,
+ selectionchangeOnDocument,
+ `${
+ aTestDescription
+ }: "selectionchange" event on the document node should be fired ${
+ selectionchangeOnDocument
+ } times ${aSituationDescription}`
+ );
+ is(
+ inputSelectionchange,
+ selectionchangeOnInput,
+ `${
+ aTestDescription
+ }: "selectionchange" event on the <input> should be fired ${
+ selectionchangeOnInput
+ } times ${aSituationDescription}`
+ );
+ is(
+ textareaSelectionchange,
+ selectionchangeOnTextarea,
+ `${
+ aTestDescription
+ }: "selectionchange" event on the <textarea> should be fired ${
+ selectionchangeOnTextarea
+ } times ${aSituationDescription}`
+ );
+ }
+
+ async function testWithSynthesizingMouse(
+ aDescription,
+ aElement,
+ aOffset,
+ aType,
+ aExpectedEventCounts
+ ) {
+ const eventObject = aType == "click" ? {} : { type: aType };
+ if (aOffset.y === undefined || aOffset.y === null) {
+ aOffset.y = 10;
+ }
+ synthesizeMouse(aElement, aOffset.x, aOffset.y, eventObject);
+ await spin();
+
+ checkEventCounts(
+ aDescription,
+ `after synthesizing ${aType} at ${aOffset.x}, ${aOffset.y}`,
+ aExpectedEventCounts
+ );
+ reset();
+ }
+
+ async function testWithSynthesizingKey(
+ aDescription,
+ aKey,
+ aEventObject,
+ aExpectedEventCounts
+ ) {
+ synthesizeKey(aKey, aEventObject);
+ await spin();
+
+ checkEventCounts(
+ aDescription,
+ `after synthesizing a key press of "${aKey}"`,
+ aExpectedEventCounts
+ );
+ reset();
+ }
+
+ async function testWithSettingContentEditableAttribute(
+ aDescription,
+ aElement,
+ aContentEditableValue,
+ aExpectedEventCounts
+ ) {
+ aElement.setAttribute("contenteditable",
+ aContentEditableValue ? "true" : "false");
+ await spin();
+
+ checkEventCounts(
+ aDescription,
+ `after setting contenteditable attribute to ${
+ aElement.getAttribute("contenteditable")
+ }`,
+ aExpectedEventCounts
+ );
+ 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
+ await testWithSettingContentEditableAttribute(
+ "Setting contenteditable attribute to true of <div> should not change selection",
+ elt("ce"),
+ true,
+ {}
+ );
+
+ // Make sure setting the element to not be contentEditable doesn't cause any selectionchange events
+ await testWithSettingContentEditableAttribute(
+ 'Setting contenteditable attribute to false of <div contenteditable="true"> should not change selection',
+ elt("ce"),
+ false,
+ {}
+ );
+
+ // Now make the div contentEditable and proceed with the test
+ await testWithSettingContentEditableAttribute(
+ 'Setting contenteditable attribute to true of <div contenteditable="false"> should not change selection',
+ elt("ce"),
+ true,
+ {}
+ );
+
+ // Focus the contenteditable text
+ await testWithSynthesizingMouse(
+ 'Clicking in <div contenteditable="true"> should change selection',
+ elt("ce"),
+ { x: 100 },
+ "click",
+ { selectionchangeOnDocument: 1 }
+ );
+ isCollapsed();
+
+ // Move the selection to the right, this should only fire selectstart once
+ selectstartTarget = elt("ce").firstChild;
+ await testWithSynthesizingKey(
+ 'Synthesizing Shift-ArrowRight to select a character in the text node of <div contenteditable="true"> should start to select again and change selection',
+ "KEY_ArrowRight",
+ { shiftKey: true },
+ { selectstartOnDocument: 1, selectionchangeOnDocument: 1 }
+ );
+ isNotCollapsed();
+ await testWithSynthesizingKey(
+ 'Synthesizing Shift-ArrowRight again to select 2 characters in the text node of <div contenteditable="true"> should change selection',
+ "KEY_ArrowRight",
+ { shiftKey: true },
+ { selectionchangeOnDocument: 1 }
+ );
+ isNotCollapsed();
+
+ // Move it back so that the selection is empty again
+ await testWithSynthesizingKey(
+ 'Synthesizing Shift-ArrowLeft to shrink selection in the text node of <div contenteditable="true"> should change selection',
+ "KEY_ArrowLeft",
+ { shiftKey: true },
+ { selectionchangeOnDocument: 1 }
+ );
+ isNotCollapsed();
+ await testWithSynthesizingKey(
+ 'Synthesizing Shift-ArrowLeft again to collapse selection in the text node of <div contenteditable="true"> should change selection',
+ "KEY_ArrowLeft",
+ { shiftKey: true },
+ { selectionchangeOnDocument: 1 }
+ );
+ isCollapsed();
+
+ // Going from empty to non-empty should fire selectstart again
+ selectstartTarget = elt("ce").firstChild;
+ await testWithSynthesizingKey(
+ 'Synthesizing Shift-ArrowLeft again to select a character on the other side in the text node of <div contenteditable="true"> should start to select and change selection',
+ "KEY_ArrowLeft",
+ { shiftKey: true },
+ { selectstartOnDocument: 1, selectionchangeOnDocument: 1 }
+ );
+ isNotCollapsed();
+
+ async function testWithSynthesizingMouseDrag(
+ aDescription,
+ aElement,
+ aSelectstartTarget
+ ) {
+ // Select a region
+ await testWithSynthesizingMouse(
+ `Pressing left mouse button ${
+ aDescription
+ } should not start to select but should change selection`,
+ aElement,
+ { x: 50 },
+ "mousedown",
+ { selectionchangeOnDocument: 1 }
+ );
+ isCollapsed();
+
+ selectstartTarget = aSelectstartTarget;
+ await testWithSynthesizingMouse(
+ `Dragging mouse to right to extend selection ${
+ aDescription
+ } should start to select and change selection`,
+ aElement,
+ { x: 100 },
+ "mousemove",
+ { selectstartOnDocument: 1, selectionchangeOnDocument: 1 }
+ );
+ isNotCollapsed();
+
+ // Moving it more shouldn't trigger a start (move back to empty)
+ await testWithSynthesizingMouse(
+ `Dragging mouse to left to shrink selection ${
+ aDescription
+ } should change selection`,
+ aElement,
+ { x: 75 },
+ "mousemove",
+ { selectionchangeOnDocument: 1 }
+ );
+ isNotCollapsed();
+ await testWithSynthesizingMouse(
+ `Dragging mouse to left to collapse selection ${
+ aDescription
+ } should change selection`,
+ aElement,
+ { x: 50 },
+ "mousemove",
+ { selectionchangeOnDocument: 1 }
+ );
+ isCollapsed();
+
+ // Wiggling the mouse a little such that it doesn't select any
+ // characters shouldn't trigger a selection
+ await testWithSynthesizingMouse(
+ `Dragging mouse to bottom a bit ${
+ aDescription
+ } should not cause selection change`,
+ aElement,
+ { x: 50, y: 11 },
+ "mousemove",
+ {}
+ );
+ isCollapsed();
+
+ // Moving the mouse again from an empty selection should trigger a
+ // selectstart
+ selectstartTarget = aSelectstartTarget;
+ await testWithSynthesizingMouse(
+ `Dragging mouse to left to extend selection ${
+ aDescription
+ } should start to select and change selection`,
+ aElement,
+ { x: 25 },
+ "mousemove",
+ { selectstartOnDocument: 1, selectionchangeOnDocument: 1 }
+ );
+ isNotCollapsed();
+
+ // Releasing the mouse shouldn't do anything
+ await testWithSynthesizingMouse(
+ `Releasing left mouse button to stop dragging ${
+ aDescription
+ } should not change selection`,
+ aElement,
+ { x: 25 },
+ "mouseup",
+ {}
+ );
+ isNotCollapsed();
+
+ // And neither should moving your mouse around when the mouse
+ // button isn't pressed
+ await testWithSynthesizingMouse(
+ `Just moving mouse to right ${
+ aDescription
+ } should not start to select nor change selection`,
+ aElement,
+ { x: 50 },
+ "mousemove",
+ {}
+ );
+ isNotCollapsed();
+
+ // Clicking in an random location should move the selection, but not perform a
+ // selectstart
+ await testWithSynthesizingMouse(
+ `Clicking to collapse selection ${
+ aDescription
+ } should cause only selection change`,
+ aElement,
+ { x: 50 },
+ "click",
+ { selectionchangeOnDocument: 1 }
+ );
+ isCollapsed();
+
+ // Clicking there again should do nothing
+ await testWithSynthesizingMouse(
+ `Clicking same position again ${
+ aDescription
+ } should not change selection`,
+ aElement,
+ { x: 50 },
+ "click",
+ {}
+ );
+ isCollapsed();
+
+ // Selecting a region, and canceling the selectstart should mean that the
+ // selection remains collapsed
+ await testWithSynthesizingMouse(
+ `Pressing left mouse button on different character to move caret ${
+ aDescription
+ } should cause only selection change`,
+ aElement,
+ { x: 75 },
+ "mousedown",
+ { selectionchangeOnDocument: 1 }
+ );
+ isCollapsed();
+ cancel = true;
+ selectstartTarget = aSelectstartTarget;
+ await testWithSynthesizingMouse(
+ `Moving mouse to right to extend selection but selectstart event will be prevented default ${
+ aDescription
+ } should start to select and change selection`,
+ aElement,
+ { x: 100 },
+ "mousemove",
+ { selectstartOnDocument: 1, selectionchangeOnDocument: 1 }
+ );
+ isCollapsed();
+ await testWithSynthesizingMouse(
+ `Releasing the left mouse button after dragging but selectstart was prevented the default ${
+ aDescription
+ } should not change selection`,
+ aElement,
+ { x: 100 },
+ "mouseup",
+ {}
+ );
+ isCollapsed();
+ }
+
+ // Should work both on normal
+ await testWithSynthesizingMouseDrag(
+ "on the text node in the non-editable <div>",
+ elt("inner"),
+ elt("inner").firstChild
+ );
+ // and contenteditable fields
+ await testWithSynthesizingMouseDrag(
+ 'on the text node in the editable <div contenteditable="true">',
+ elt("ce"),
+ elt("ce").firstChild
+ );
+ // and fields with elements in them
+ await testWithSynthesizingMouseDrag(
+ "on the text node in the non-editable <div>'s child",
+ elt("normal"),
+ elt("inner").firstChild
+ );
+
+ await testWithSynthesizingMouse(
+ "Clicking in the text node in the `<div>` should change selection",
+ elt("inner"),
+ { x: 50 },
+ "click",
+ { selectionchangeOnDocument: 1 }
+ );
+ isCollapsed();
+
+ reset();
+ // Select all should fire both selectstart and change
+ selectstartTarget = document.body;
+ await testWithSynthesizingKey(
+ "Select All when no editor has focus should start to select and select all content",
+ "a", { accelKey: true },
+ { selectstartOnDocument: 1, selectionchangeOnDocument: 1 }
+ );
+ isNotCollapsed();
+
+ // Clear the selection
+ await testWithSynthesizingMouse(
+ "Clicking in the non-editable <div> should clear selection",
+ elt("inner"),
+ { x: 50 },
+ "click",
+ { selectionchangeOnDocument: 1 }
+ );
+ isCollapsed();
+
+ // Even if we already have a selection
+ await testWithSynthesizingMouse(
+ "Pressing the left mouse button in non-editable <div> should change selection",
+ elt("inner"),
+ { x: 75 },
+ "mousedown",
+ { selectionchangeOnDocument: 1 }
+ );
+ isCollapsed();
+ selectstartTarget = elt("inner").firstChild;
+ await testWithSynthesizingMouse(
+ "Dragging mouse to right to extend selection should start and change selection",
+ elt("inner"),
+ { x: 100 },
+ "mousemove",
+ { selectstartOnDocument: 1, selectionchangeOnDocument: 1 }
+ );
+ isNotCollapsed();
+ await testWithSynthesizingMouse(
+ "Releasing the left mouse button should not change selection",
+ elt("inner"),
+ { x: 100 },
+ "mouseup",
+ {}
+ );
+ isNotCollapsed();
+
+ selectstartTarget = document.body;
+ await testWithSynthesizingKey(
+ "Select All when no editor has focus should start to select and select all content (again)",
+ "a",
+ { accelKey: true },
+ { selectstartOnDocument: 1, selectionchangeOnDocument: 1 }
+ );
+ isNotCollapsed();
+
+ // Clear the selection
+ await testWithSynthesizingMouse(
+ "Clicking in the non-editable <div> should clear selection (again)",
+ elt("inner"),
+ { x: 50 },
+ "click",
+ {selectionchangeOnDocument: 1 }
+ );
+ isCollapsed();
+
+ // Make sure that a synthesized selection change doesn't fire selectstart
+ getSelection().removeAllRanges();
+ await spin();
+ is(
+ selectstart,
+ 0,
+ "Selection.removeAllRanges() should not cause selectstart event"
+ );
+ is(
+ selectionchange,
+ 1,
+ "Selection.removeAllRanges() should cause selectionchange event"
+ );
+ reset();
+ isCollapsed();
+
+ await (async function test_Selection_selectNode() {
+ const range = document.createRange();
+ range.selectNode(elt("inner"));
+ getSelection().addRange(range);
+ await spin();
+ is(
+ selectstart,
+ 0,
+ "Selection.addRange() should not cause selectstart event"
+ );
+ is(
+ selectionchange,
+ 1,
+ "Selection.addRange() should cause selectionchange event"
+ );
+ reset();
+ isNotCollapsed();
+ })();
+
+ // Change the range, without replacing
+ await (async function test_Selection_getRangeAt_selectNode() {
+ getSelection().getRangeAt(0).selectNode(elt("ce"));
+ await spin();
+ is(
+ selectstart,
+ 0,
+ "Selection.getRangeAt(0).selectNode() should not cause selectstart event"
+ );
+ is(
+ selectionchange,
+ 1,
+ "Selection.getRangeAt(0).selectNode() should cause selectionchange event"
+ );
+ reset();
+ isNotCollapsed();
+ })();
+
+ // Remove the range
+ getSelection().removeAllRanges();
+ await spin();
+ is(
+ selectstart,
+ 0,
+ "Selection.removeAllRanges() should not cause selectstart event (again)"
+ );
+ is(
+ selectionchange,
+ 1,
+ "Selection.removeAllRanges() should cause selectionchange event (again)"
+ );
+ reset();
+ isCollapsed();
+
+ for (const textControl of [elt("input"), elt("textarea")]) {
+ await UpdateSelectEventsOnTextControlsPref({
+ selectstart: false,
+ selectionchange: false,
+ });
+
+ // Without the dom.select_events.textcontrols.enabled pref,
+ // pressing the mouse shouldn't do anything.
+ await testWithSynthesizingMouse(
+ `Pressing the left mouse button in <${
+ textControl.tagName.toLocaleLowerCase()
+ }> should change selection of the document`,
+ textControl,
+ { x: 50 },
+ "mousedown",
+ {
+ // XXX Bug 1721287: For some reason we fire 2 selectchange events
+ // on the body when switching from the <input> to the <textarea>.
+ selectionchangeOnDocument:
+ document.activeElement != textControl &&
+ (document.activeElement.tagName.toLocaleLowerCase() == "input" ||
+ document.activeElement.tagName.toLocaleLowerCase() == "textarea")
+ ? 2
+ : 1,
+ }
+ );
+
+ // Releasing the mouse shouldn't do anything
+ await testWithSynthesizingMouse(
+ `Releasing the left mouse button in <${
+ textControl.tagName.toLocaleLowerCase()
+ }> should not change any selection`,
+ textControl,
+ { x: 50 },
+ "mouseup",
+ {}
+ );
+
+ for (const selectstart of [1, 0]) {
+ await UpdateSelectEventsOnTextControlsPref({
+ selectstart,
+ selectionchange: true,
+ });
+
+ const selectstartEventSetting = `selectstart in text controls is ${
+ selectstart ? "enabled" : "disabled"
+ }`;
+
+ const isInput = textControl.tagName.toLocaleLowerCase() == "input";
+
+ await testWithSynthesizingMouse(
+ `Pressing the left mouse button in <${
+ textControl.tagName.toLocaleLowerCase()
+ }> should change selection (${selectstartEventSetting})`,
+ textControl,
+ { x: 40 },
+ "mousedown",
+ {
+ selectionchangeOnDocument: 1,
+ selectionchangeOnInput: isInput ? 1 : 0,
+ selectionchangeOnTextarea: isInput ? 0 : 1,
+ }
+ );
+
+ selectstartTarget = textControl;
+ await testWithSynthesizingMouse(
+ `Dragging mouse to right to extend selection in <${
+ textControl.tagName.toLocaleLowerCase()
+ }> should start to select and change selection (${
+ selectstartEventSetting
+ })`,
+ textControl,
+ { x: 100 },
+ "mousemove",
+ {
+ selectstartOnDocument: selectstart,
+ selectionchangeOnDocument: 1,
+ selectionchangeOnInput: isInput ? 1 : 0,
+ selectionchangeOnTextarea: isInput ? 0 : 1,
+ }
+ );
+
+ // Moving it more shouldn't trigger a start (move back to empty)
+ await testWithSynthesizingMouse(
+ `Dragging mouse to left to shrink selection in <${
+ textControl.tagName.toLocaleLowerCase()
+ }> should change selection (${selectstartEventSetting})`,
+ textControl,
+ { x: 75 },
+ "mousemove",
+ {
+ selectionchangeOnDocument: 1,
+ selectionchangeOnInput: isInput ? 1 : 0,
+ selectionchangeOnTextarea: isInput ? 0 : 1,
+ }
+ );
+ await testWithSynthesizingMouse(
+ `Dragging mouse to left to collapse selection in <${
+ textControl.tagName.toLocaleLowerCase()
+ }> should change selection (${selectstartEventSetting})`,
+ textControl,
+ { x: 40 },
+ "mousemove",
+ {
+ selectionchangeOnDocument: 1,
+ selectionchangeOnInput: isInput ? 1 : 0,
+ selectionchangeOnTextarea: isInput ? 0 : 1,
+ }
+ );
+
+ // Wiggling the mouse a little such that it doesn't select any
+ // characters shouldn't trigger a selection
+ await testWithSynthesizingMouse(
+ `Pressing the left mouse button at caret in <${
+ textControl.tagName.toLocaleLowerCase()
+ }> should not change selection (${selectstartEventSetting})`,
+ textControl,
+ {
+ x: 40,
+ y: 11,
+ },
+ "mousemove",
+ {}
+ );
+
+ // Moving the mouse again from an empty selection should trigger a
+ // selectstart
+ selectstartTarget = textControl;
+ await testWithSynthesizingMouse(
+ `Dragging mouse to left to extend selection in <${
+ textControl.tagName.toLocaleLowerCase()
+ }> should start to select and change selection (${
+ selectstartEventSetting
+ })`,
+ textControl,
+ { x: 25 },
+ "mousemove",
+ {
+ selectstartOnDocument: selectstart,
+ selectionchangeOnDocument: 1,
+ selectionchangeOnInput: isInput ? 1 : 0,
+ selectionchangeOnTextarea: isInput ? 0 : 1,
+ }
+ );
+
+ // Releasing the mouse shouldn't do anything
+ await testWithSynthesizingMouse(
+ `Releasing the left mouse button in <${
+ textControl.tagName.toLocaleLowerCase()
+ }> should not change selection (${selectstartEventSetting})`,
+ textControl,
+ { x: 25 },
+ "mouseup",
+ {}
+ );
+
+ // And neither should moving your mouse around when the mouse
+ // button isn't pressed
+ await testWithSynthesizingMouse(
+ `Just moving mouse to right in <${
+ textControl.tagName.toLocaleLowerCase()
+ }> should not start to select nor change selection (${
+ selectstartEventSetting
+ })`,
+ textControl,
+ { x: 50 },
+ "mousemove",
+ {}
+ );
+
+ // Clicking in an random location should move the selection, but
+ // not perform a selectstart
+ await testWithSynthesizingMouse(
+ `Clicking in <${
+ textControl.tagName.toLocaleLowerCase()
+ }> should change selection, but should not start selection (${
+ selectstartEventSetting
+ })`,
+ textControl,
+ { x: 50 },
+ "click",
+ {
+ selectionchangeOnDocument: 1,
+ selectionchangeOnInput: isInput ? 1 : 0,
+ selectionchangeOnTextarea: isInput ? 0 : 1,
+ }
+ );
+
+ // Clicking there again should do nothing
+ await testWithSynthesizingMouse(
+ `Clicking at caret in <${
+ textControl.tagName.toLocaleLowerCase()
+ }> should not change selection (${selectstartEventSetting})`,
+ textControl,
+ { x: 50 },
+ "click",
+ {}
+ );
+
+ // Selecting a region, and canceling the selectstart should mean that the
+ // selection remains collapsed
+ await testWithSynthesizingMouse(
+ `Pressing the left mouse button at different character in <${
+ textControl.tagName.toLocaleLowerCase()
+ }> should change selection (${selectstartEventSetting})`,
+ textControl,
+ { x: 75 },
+ "mousedown",
+ {
+ selectionchangeOnDocument: 1,
+ selectionchangeOnInput: isInput ? 1 : 0,
+ selectionchangeOnTextarea: isInput ? 0 : 1,
+ }
+ );
+ cancel = true;
+ selectstartTarget = textControl;
+ await testWithSynthesizingMouse(
+ `Dragging mouse to right to extend selection in <${
+ textControl.tagName.toLocaleLowerCase()
+ }> but the default of selectstart is prevented should cause selectstart and selectionchange events (${
+ selectstartEventSetting
+ })`,
+ textControl,
+ { x: 100 },
+ "mousemove",
+ {
+ selectstartOnDocument: selectstart,
+ selectionchangeOnDocument: 1,
+ selectionchangeOnInput: isInput ? 1 : 0,
+ selectionchangeOnTextarea: isInput ? 0 : 1,
+ }
+ );
+ await testWithSynthesizingMouse(
+ `Releasing the left mouse button in <${
+ textControl.tagName.toLocaleLowerCase()
+ }> should not cause changing selection (${selectstartEventSetting})`,
+ textControl,
+ { x: 100 },
+ "mouseup",
+ {}
+ );
+ }
+ }
+
+ // 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
+ for (const textControl of [elt("input"), elt("textarea")]) {
+ await (async function test_set_display_of_text_control_to_none() {
+ textControl.setAttribute("style", "display: none;");
+ await spin();
+ checkEventCounts(
+ `Setting display of <${
+ textControl.tagName.toLocaleLowerCase()
+ }> to none`,
+ "",
+ {}
+ );
+ reset();
+ })();
+
+ await (async function test_remove_display_none_of_text_control() {
+ textControl.setAttribute("style", "");
+ await spin();
+ checkEventCounts(
+ `Removing display:none of <${
+ textControl.tagName.toLocaleLowerCase()
+ }>`,
+ "",
+ {}
+ );
+ reset();
+ })();
+ }
+
+ // When selection is at the end of contentEditable's content,
+ // clearing the content should trigger selection events.
+ await (async function test_removing_contenteditable() {
+ const savedContent = elt("ce").innerHTML;
+ document.getSelection().setBaseAndExtent(elt("ce"), 1, elt("ce"), 1);
+ await spin();
+ reset();
+
+ elt("ce").firstChild.remove();
+ await spin();
+ checkEventCounts(
+ 'Removing <div contenteditable="true"> from the DOM tree',
+ "",
+ { selectionchangeOnDocument: 1 }
+ );
+
+ elt("ce").innerHTML = savedContent;
+ await spin();
+ reset();
+ })();
+ });
+ </script>
+ </body>
+</html>