tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

mochitest_support_external.js (8835B)


      1 // This file supports translating W3C tests
      2 // to tests on auto MochiTest system with minimum changes.
      3 // Author: Maksim Lebedev <alessarik@gmail.com>
      4 
      5 /* eslint-disable mozilla/no-comparison-or-assignment-inside-ok */
      6 
      7 // Function allows to prepare our tests after load document
      8 addEventListener(
      9  "load",
     10  function (event) {
     11    console.log("OnLoad external document");
     12    prepareTest();
     13  },
     14  false
     15 );
     16 
     17 // Function allows to initialize prerequisites before testing
     18 function prepareTest() {
     19  SimpleTest.waitForExplicitFinish();
     20  SimpleTest.requestCompleteLog();
     21  startTest();
     22 }
     23 
     24 function setImplicitPointerCapture(capture, callback) {
     25  console.log("SET dom.w3c_pointer_events.implicit_capture as " + capture);
     26  SpecialPowers.pushPrefEnv(
     27    {
     28      set: [["dom.w3c_pointer_events.implicit_capture", capture]],
     29    },
     30    callback
     31  );
     32 }
     33 
     34 var utils = SpecialPowers.Ci.nsIDOMWindowUtils;
     35 
     36 // Mouse Event Helper Object
     37 var MouseEventHelper = (function () {
     38  return {
     39    MOUSE_ID: utils.DEFAULT_MOUSE_POINTER_ID,
     40    PEN_ID: utils.DEFAULT_PEN_POINTER_ID,
     41    // State
     42    // TODO: Separate this to support mouse and pen simultaneously.
     43    BUTTONS_STATE: utils.MOUSE_BUTTONS_NO_BUTTON,
     44 
     45    // Button
     46    BUTTON_NONE: -1, // Used by test framework only. (replaced before sending)
     47    BUTTON_LEFT: utils.MOUSE_BUTTON_LEFT_BUTTON,
     48    BUTTON_MIDDLE: utils.MOUSE_BUTTON_MIDDLE_BUTTON,
     49    BUTTON_RIGHT: utils.MOUSE_BUTTON_RIGHT_BUTTON,
     50 
     51    // Buttons
     52    BUTTONS_NONE: utils.MOUSE_BUTTONS_NO_BUTTON,
     53    BUTTONS_LEFT: utils.MOUSE_BUTTONS_LEFT_BUTTON,
     54    BUTTONS_MIDDLE: utils.MOUSE_BUTTONS_MIDDLE_BUTTON,
     55    BUTTONS_RIGHT: utils.MOUSE_BUTTONS_RIGHT_BUTTON,
     56    BUTTONS_4TH: utils.MOUSE_BUTTONS_4TH_BUTTON,
     57    BUTTONS_5TH: utils.MOUSE_BUTTONS_5TH_BUTTON,
     58 
     59    // Utils
     60    computeButtonsMaskFromButton(aButton) {
     61      // Since the range of button values is 0 ~ 2 (see nsIDOMWindowUtils.idl),
     62      // we can use an array to find out the desired mask.
     63      var mask = [
     64        this.BUTTONS_NONE, // -1 (MouseEventHelper.BUTTON_NONE)
     65        this.BUTTONS_LEFT, // 0
     66        this.BUTTONS_MIDDLE, // 1
     67        this.BUTTONS_RIGHT, // 2
     68      ][aButton + 1];
     69 
     70      ok(mask !== undefined, "Unrecognized button value caught!");
     71      return mask;
     72    },
     73 
     74    checkExitState() {
     75      ok(!this.BUTTONS_STATE, "Mismatched mousedown/mouseup caught.");
     76    },
     77  };
     78 })();
     79 
     80 function createMouseEvent(aEventType, aParams) {
     81  var eventObj = { type: aEventType };
     82 
     83  // Default to mouse.
     84  eventObj.inputSource =
     85    aParams && "inputSource" in aParams
     86      ? aParams.inputSource
     87      : MouseEvent.MOZ_SOURCE_MOUSE;
     88  // Compute pointerId
     89  eventObj.id =
     90    eventObj.inputSource === MouseEvent.MOZ_SOURCE_MOUSE
     91      ? MouseEventHelper.MOUSE_ID
     92      : MouseEventHelper.PEN_ID;
     93  // Check or generate a |button| value.
     94  var isButtonEvent = aEventType === "mouseup" || aEventType === "mousedown";
     95 
     96  // Set |button| to the default value first.
     97  eventObj.button = isButtonEvent
     98    ? MouseEventHelper.BUTTON_LEFT
     99    : MouseEventHelper.BUTTON_NONE;
    100 
    101  // |button| is passed, use and check it.
    102  if (aParams && "button" in aParams) {
    103    var hasButtonValue = aParams.button !== MouseEventHelper.BUTTON_NONE;
    104    ok(
    105      !isButtonEvent || hasButtonValue,
    106      "Inappropriate |button| value caught."
    107    );
    108    eventObj.button = aParams.button;
    109  }
    110 
    111  // Generate a |buttons| value and update buttons state
    112  var buttonsMask = MouseEventHelper.computeButtonsMaskFromButton(
    113    eventObj.button
    114  );
    115  switch (aEventType) {
    116    case "mousedown":
    117      MouseEventHelper.BUTTONS_STATE |= buttonsMask; // Set button flag.
    118      break;
    119    case "mouseup":
    120      MouseEventHelper.BUTTONS_STATE &= ~buttonsMask; // Clear button flag.
    121      break;
    122  }
    123  eventObj.buttons = MouseEventHelper.BUTTONS_STATE;
    124 
    125  // Replace the button value for mousemove events.
    126  // Since in widget level design, even when no button is pressed at all, the
    127  // value of WidgetMouseEvent.button is still 0, which is the same value as
    128  // the one for mouse left button.
    129  if (aEventType === "mousemove") {
    130    eventObj.button = MouseEventHelper.BUTTON_LEFT;
    131  }
    132  return eventObj;
    133 }
    134 
    135 // Helper function to send MouseEvent with different parameters
    136 function sendMouseEvent(int_win, elemId, mouseEventType, params) {
    137  var elem = int_win.document.getElementById(elemId);
    138  if (elem) {
    139    var rect = elem.getBoundingClientRect();
    140    var eventObj = createMouseEvent(mouseEventType, params);
    141 
    142    // Default to the center of the target element but we can still send to a
    143    // position outside of the target element.
    144    var offsetX =
    145      params && "offsetX" in params ? params.offsetX : rect.width / 2;
    146    var offsetY =
    147      params && "offsetY" in params ? params.offsetY : rect.height / 2;
    148 
    149    console.log(elemId, eventObj);
    150    synthesizeMouse(elem, offsetX, offsetY, eventObj, int_win);
    151  } else {
    152    is(!!elem, true, "Document should have element with id: " + elemId);
    153  }
    154 }
    155 
    156 // Helper function to send MouseEvent with position
    157 function sendMouseEventAtPoint(aWindow, aLeft, aTop, aMouseEventType, aParams) {
    158  var eventObj = createMouseEvent(aMouseEventType, aParams);
    159  console.log(eventObj);
    160  synthesizeMouseAtPoint(aLeft, aTop, eventObj, aWindow);
    161 }
    162 
    163 // Touch Event Helper Object
    164 var TouchEventHelper = {
    165  // State
    166  TOUCH_ID: utils.DEFAULT_TOUCH_POINTER_ID,
    167  TOUCH_STATE: false,
    168 
    169  // Utils
    170  checkExitState() {
    171    ok(!this.TOUCH_STATE, "Mismatched touchstart/touchend caught.");
    172  },
    173 };
    174 
    175 // Helper function to send TouchEvent with different parameters
    176 // TODO: Support multiple touch points to test more features such as
    177 // PointerEvent.isPrimary and pinch-zoom.
    178 function sendTouchEvent(int_win, elemId, touchEventType, params) {
    179  var elem = int_win.document.getElementById(elemId);
    180  if (elem) {
    181    var rect = elem.getBoundingClientRect();
    182    var eventObj = {
    183      type: touchEventType,
    184      id: TouchEventHelper.TOUCH_ID,
    185    };
    186 
    187    // Update touch state
    188    switch (touchEventType) {
    189      case "touchstart":
    190        TouchEventHelper.TOUCH_STATE = true; // Set touch flag.
    191        break;
    192      case "touchend":
    193      case "touchcancel":
    194        TouchEventHelper.TOUCH_STATE = false; // Clear touch flag.
    195        break;
    196    }
    197 
    198    // Default to the center of the target element but we can still send to a
    199    // position outside of the target element.
    200    var offsetX =
    201      params && "offsetX" in params ? params.offsetX : rect.width / 2;
    202    var offsetY =
    203      params && "offsetY" in params ? params.offsetY : rect.height / 2;
    204 
    205    console.log(elemId, eventObj);
    206    synthesizeTouch(elem, offsetX, offsetY, eventObj, int_win);
    207  } else {
    208    is(!!elem, true, "Document should have element with id: " + elemId);
    209  }
    210 }
    211 
    212 // Helper function to trigger drag and drop.
    213 async function doDragAndDrop(int_win, srcElemId, destElemId, params = {}) {
    214  params.srcElement = int_win.document.getElementById(srcElemId);
    215  params.destElement = int_win.document.getElementById(destElemId);
    216  params.srcWindow = int_win;
    217  params.destWindow = int_win;
    218  params.id = MouseEventHelper.MOUSE_ID;
    219  // This is basically for android which has a larger drag threshold.
    220  params.stepY = params.stepY || 25;
    221  await synthesizePlainDragAndDrop(params);
    222 }
    223 
    224 // Helper function to run Point Event test in a new tab.
    225 function runTestInNewWindow(aFile) {
    226  var testURL =
    227    location.href.substring(0, location.href.lastIndexOf("/") + 1) + aFile;
    228  var testWindow = window.open(testURL, "_blank");
    229  var testDone = false;
    230 
    231  // We start testing when receiving load event. Inject the mochitest helper js
    232  // to the test case after DOM elements are constructed and before the load
    233  // event is fired.
    234  testWindow.addEventListener(
    235    "DOMContentLoaded",
    236    function () {
    237      var e = testWindow.document.createElement("script");
    238      e.type = "text/javascript";
    239      e.src =
    240        "../".repeat(aFile.split("/").length - 1) +
    241        "mochitest_support_internal.js";
    242      testWindow.document.getElementsByTagName("head")[0].appendChild(e);
    243    },
    244    { once: true }
    245  );
    246 
    247  window.addEventListener("message", function (aEvent) {
    248    switch (aEvent.data.type) {
    249      case "START":
    250        // Update constants
    251        MouseEventHelper.MOUSE_ID = aEvent.data.message.mouseId;
    252        MouseEventHelper.PEN_ID = aEvent.data.message.penId;
    253        TouchEventHelper.TOUCH_ID = aEvent.data.message.touchId;
    254 
    255        executeTest(testWindow);
    256        break;
    257      case "RESULT":
    258        // Should not perform checking after SimpleTest.finish().
    259        if (!testDone) {
    260          ok(aEvent.data.result, aEvent.data.message);
    261        }
    262        break;
    263      case "FIN":
    264        testDone = true;
    265        MouseEventHelper.checkExitState();
    266        TouchEventHelper.checkExitState();
    267        testWindow.close();
    268        SimpleTest.finish();
    269        break;
    270    }
    271  });
    272 }