summaryrefslogtreecommitdiffstats
path: root/comm/mail/test/browser/shared-modules/MouseEventHelpers.jsm
diff options
context:
space:
mode:
Diffstat (limited to 'comm/mail/test/browser/shared-modules/MouseEventHelpers.jsm')
-rw-r--r--comm/mail/test/browser/shared-modules/MouseEventHelpers.jsm226
1 files changed, 226 insertions, 0 deletions
diff --git a/comm/mail/test/browser/shared-modules/MouseEventHelpers.jsm b/comm/mail/test/browser/shared-modules/MouseEventHelpers.jsm
new file mode 100644
index 0000000000..cd0f9a09d4
--- /dev/null
+++ b/comm/mail/test/browser/shared-modules/MouseEventHelpers.jsm
@@ -0,0 +1,226 @@
+/* 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";
+
+const EXPORTED_SYMBOLS = [
+ "drag_n_drop_element",
+ "synthesize_drag_start",
+ "synthesize_drag_over",
+ "synthesize_drag_end",
+ "synthesize_drop",
+];
+
+var EventUtils = ChromeUtils.import(
+ "resource://testing-common/mozmill/EventUtils.jsm"
+);
+
+var { Assert } = ChromeUtils.importESModule(
+ "resource://testing-common/Assert.sys.mjs"
+);
+
+/**
+ * Execute a drag and drop session.
+ *
+ * @param {XULElement} aDragObject
+ * the element from which the drag session should be started.
+ * @param {} aDragWindow
+ * the window the aDragObject is in
+ * @param {XULElement} aDropObject
+ * the element at which the drag session should be ended.
+ * @param {} aDropWindow
+ * the window the aDropObject is in
+ * @param {} aRelDropX
+ * the relative x-position the element is dropped over the aDropObject
+ * in percent of the aDropObject width
+ * @param {} aRelDropY
+ * the relative y-position the element is dropped over the aDropObject
+ * in percent of the aDropObject height
+ * @param {XULElement} aListener
+ * the element who's drop target should be captured and returned.
+ */
+function drag_n_drop_element(
+ aDragObject,
+ aDragWindow,
+ aDropObject,
+ aDropWindow,
+ aRelDropX,
+ aRelDropY,
+ aListener
+) {
+ let dt = synthesize_drag_start(aDragWindow, aDragObject, aListener);
+ Assert.ok(dt, "Drag data transfer was undefined");
+
+ synthesize_drag_over(aDropWindow, aDropObject, dt);
+
+ let dropRect = aDropObject.getBoundingClientRect();
+ synthesize_drop(aDropWindow, aDropObject, dt, {
+ screenX: aDropObject.screenX + dropRect.width * aRelDropX,
+ screenY: aDropObject.screenY + dropRect.height * aRelDropY,
+ });
+}
+
+/**
+ * Starts a drag new session.
+ *
+ * @param {} aWindow
+ * @param {XULElement} aDispatcher
+ * the element from which the drag session should be started.
+ * @param {XULElement} aListener
+ * the element who's drop target should be captured and returned.
+ * @returns {nsIDataTransfer}
+ * returns the DataTransfer Object of captured by aListener.
+ */
+function synthesize_drag_start(aWindow, aDispatcher, aListener) {
+ let dt;
+
+ let trapDrag = function (event) {
+ if (!event.dataTransfer) {
+ throw new Error("no DataTransfer");
+ }
+
+ dt = event.dataTransfer;
+
+ event.preventDefault();
+ };
+
+ aListener.addEventListener("dragstart", trapDrag, true);
+
+ EventUtils.synthesizeMouse(aDispatcher, 5, 5, { type: "mousedown" }, aWindow);
+ EventUtils.synthesizeMouse(
+ aDispatcher,
+ 5,
+ 10,
+ { type: "mousemove" },
+ aWindow
+ );
+ EventUtils.synthesizeMouse(
+ aDispatcher,
+ 5,
+ 15,
+ { type: "mousemove" },
+ aWindow
+ );
+
+ aListener.removeEventListener("dragstart", trapDrag, true);
+
+ return dt;
+}
+
+/**
+ * Synthesizes a drag over event.
+ *
+ * @param {} aWindow
+ * @param {XULElement} aDispatcher
+ * the element from which the drag session should be started.
+ * @param {nsIDataTransfer} aDt
+ * the DataTransfer Object of captured by listener.
+ * @param {} aArgs
+ * arguments passed to the mouse event.
+ */
+function synthesize_drag_over(aWindow, aDispatcher, aDt, aArgs) {
+ _synthesizeDragEvent("dragover", aWindow, aDispatcher, aDt, aArgs);
+}
+
+/**
+ * Synthesizes a drag end event.
+ *
+ * @param {} aWindow
+ * @param {XULElement} aDispatcher
+ * the element from which the drag session should be started.
+ * @param {nsIDataTransfer} aDt
+ * the DataTransfer Object of captured by listener.
+ * @param {} aArgs
+ * arguments passed to the mouse event.
+ */
+function synthesize_drag_end(aWindow, aDispatcher, aListener, aDt, aArgs) {
+ _synthesizeDragEvent("dragend", aWindow, aListener, aDt, aArgs);
+
+ // Ensure drag has ended.
+ EventUtils.synthesizeMouse(aDispatcher, 5, 5, { type: "mousemove" }, aWindow);
+ EventUtils.synthesizeMouse(
+ aDispatcher,
+ 5,
+ 10,
+ { type: "mousemove" },
+ aWindow
+ );
+ EventUtils.synthesizeMouse(aDispatcher, 5, 5, { type: "mouseup" }, aWindow);
+}
+
+/**
+ * Synthesizes a drop event.
+ *
+ * @param {} aWindow
+ * @param {XULElement} aDispatcher
+ * the element from which the drag session should be started.
+ * @param {nsIDataTransfer} aDt
+ * the DataTransfer Object of captured by listener.
+ * @param {} aArgs
+ * arguments passed to the mouse event.
+ */
+function synthesize_drop(aWindow, aDispatcher, aDt, aArgs) {
+ _synthesizeDragEvent("drop", aWindow, aDispatcher, aDt, aArgs);
+
+ // Ensure drag has ended.
+ EventUtils.synthesizeMouse(aDispatcher, 5, 5, { type: "mousemove" }, aWindow);
+ EventUtils.synthesizeMouse(
+ aDispatcher,
+ 5,
+ 10,
+ { type: "mousemove" },
+ aWindow
+ );
+ EventUtils.synthesizeMouse(aDispatcher, 5, 5, { type: "mouseup" }, aWindow);
+}
+
+/**
+ * Private function: Synthesizes a specified drag event.
+ *
+ * @param {} aType
+ * the type of the drag event to be synthesiyzed.
+ * @param {} aWindow
+ * @param {XULElement} aDispatcher
+ * the element from which the drag session should be started.
+ * @param {nsIDataTransfer} aDt
+ * the DataTransfer Object of captured by listener.
+ * @param {} aArgs
+ * arguments passed to the mouse event.
+ */
+function _synthesizeDragEvent(aType, aWindow, aDispatcher, aDt, aArgs) {
+ let screenX;
+ if (aArgs && "screenX" in aArgs) {
+ screenX = aArgs.screenX;
+ } else {
+ screenX = aDispatcher.screenX;
+ }
+
+ let screenY;
+ if (aArgs && "screenY" in aArgs) {
+ screenY = aArgs.screenY;
+ } else {
+ screenY = aDispatcher.screenY;
+ }
+
+ let event = aWindow.document.createEvent("DragEvent");
+ event.initDragEvent(
+ aType,
+ true,
+ true,
+ aWindow,
+ 0,
+ screenX,
+ screenY,
+ 0,
+ 0,
+ false,
+ false,
+ false,
+ false,
+ 0,
+ null,
+ aDt
+ );
+ aDispatcher.dispatchEvent(event);
+}