Bug 1661132 - Make test_bug596600.xhtml wait proper event after syntheisizing native mousemove event r=smaug
authorMasayuki Nakano <masayuki@d-toybox.com>
Wed, 24 Feb 2021 07:01:16 +0000
changeset 568579 b3eb91f0b5a7713390e5016f1f59e3a7f8d9a4f2
parent 568578 b770e6d93fbe9c5720e9301a8c15a16bc965607d
child 568580 705c898dae6b9c3b92b6a3e15992c55f43a0c6b5
push id137089
push usermasayuki@d-toybox.com
push dateWed, 24 Feb 2021 07:03:37 +0000
treeherderautoland@b3eb91f0b5a7 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerssmaug
bugs1661132, 596600
milestone88.0a1
first release with
nightly linux32
b3eb91f0b5a7 / 88.0a1 / 20210224100119 / files
nightly linux64
b3eb91f0b5a7 / 88.0a1 / 20210224100119 / files
nightly mac
b3eb91f0b5a7 / 88.0a1 / 20210224100119 / files
nightly win32
b3eb91f0b5a7 / 88.0a1 / 20210224100119 / files
nightly win64
b3eb91f0b5a7 / 88.0a1 / 20210224100119 / files
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
releases
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 1661132 - Make test_bug596600.xhtml wait proper event after syntheisizing native mousemove event r=smaug The test assumes that mousemove events are fired with waiting a tick after synthesizing native mousemove event. However, it's wrong since synthesizing native mousemove event may run after a tick for waiting safe time to synthesize a native event. Differential Revision: https://phabricator.services.mozilla.com/D106136
widget/tests/chrome.ini
widget/tests/test_bug596600.xhtml
--- a/widget/tests/chrome.ini
+++ b/widget/tests/chrome.ini
@@ -68,17 +68,17 @@ skip-if = toolkit != "cocoa"
 support-files = standalone_native_menu_window.xhtml
 [test_bug586713.xhtml]
 skip-if = toolkit != "cocoa"
 support-files = bug586713_window.xhtml
 [test_key_event_counts.xhtml]
 skip-if = toolkit != "cocoa"
 [test_bug596600.xhtml]
 support-files = file_bug596600.html
-skip-if = true # Bug 1661132 (disable on opt), and see inline comment in the test.  This is completely broken.
+skip-if = toolkit != "cocoa"
 [test_bug673301.xhtml]
 skip-if = toolkit != "cocoa"
 [test_secure_input.html]
 support-files = file_secure_input.html
 skip-if = toolkit != "cocoa"
 [test_native_key_bindings_mac.html]
 skip-if = toolkit != "cocoa" || verify
 [test_system_status_bar.xhtml]
--- a/widget/tests/test_bug596600.xhtml
+++ b/widget/tests/test_bug596600.xhtml
@@ -18,31 +18,16 @@
 </body>
 
 <script class="testbody" type="application/javascript">
 <![CDATA[
 
 const XUL_NS = "http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul";
 
 var gLeftWindow, gRightWindow, gBrowserElement;
-var gExpectedEvents = [];
-
-function moveMouseTo(x, y, andThen) {
-  // XXX This is really broken.  This test synthesizes native mouse move event
-  //     and wait a tick, but then, check event state even though it's not
-  //     been updated yet.  This must cause bug 1611033.
-  synthesizeNativeMouseEvent({
-    type: "mousemove",
-    screenX: x,
-    screenY: y,
-    scale: "inScreenPixels",
-    elementOnWidget: gLeftWindow.documentElement,
-  });
-  SimpleTest.executeSoon(andThen);
-}
 
 function openWindows() {
   gLeftWindow = window.browsingContext.topChromeWindow
                       .open('empty_window.xhtml', '_blank', 'chrome,screenX=50,screenY=50,width=200,height=200');
   SimpleTest.waitForFocus(function () {
     gRightWindow = window.browsingContext.topChromeWindow
                          .open('empty_window.xhtml', '', 'chrome,screenX=300,screenY=50,width=200,height=200');
     SimpleTest.waitForFocus(attachBrowserToLeftWindow, gRightWindow);
@@ -52,54 +37,65 @@ function openWindows() {
 function attachBrowserToLeftWindow() {
   gBrowserElement = gLeftWindow.document.createXULElement("browser");
   gBrowserElement.setAttribute("type", "content");
   gBrowserElement.setAttribute("src", "file_bug596600.html");
   gBrowserElement.style.width = "100px";
   gBrowserElement.style.height = "100px";
   gBrowserElement.style.margin = "50px";
   gLeftWindow.document.documentElement.appendChild(gBrowserElement);
-  gBrowserElement.addEventListener("load", function (e) {
-    test1();
+  gBrowserElement.addEventListener("load", async () => {
+    await test1();
+    await test2();
+    gRightWindow.close();
+    gLeftWindow.close();
+    SimpleTest.finish();
   }, { capture: true, once: true });
 }
 
-function test1() {
+async function test1() {
   // gRightWindow is active, gLeftWindow is inactive.
-  moveMouseTo(0, 0, function () {
-    var expectMouseOver = false, expectMouseOut = false;
-    function mouseOverListener(e) {
-      ok(expectMouseOver, "Got expected mouseover at " + e.screenX + ", " + e.screenY);
-      expectMouseOver = false;
-    }
-    function mouseOutListener(e) {
-      ok(expectMouseOut, "Got expected mouseout at " + e.screenX + ", " + e.screenY);
-      expectMouseOut = false;
-    }
-    gLeftWindow.addEventListener("mouseover", mouseOverListener);
-    gLeftWindow.addEventListener("mouseout", mouseOutListener);
+  info(`Synthesizing native "mousemove" event at top-left of the screen...`);
+  await promiseNativeMouseEvent({
+    type: "mousemove",
+    screenX: 0,
+    screenY: 0,
+    scale: "inScreenPixels",
+  });
+  await new Promise(resolve => SimpleTest.executeSoon(resolve));
 
-    // Move into the left window
-    expectMouseOver = true;
-    moveMouseTo(80, 80, function () {
-      ok(!expectMouseOver, "Should have got mouseover event");
+  // Move into the left window
+  info(`Synthesizing native "mousemove" event in the left window (but outside the content)...`);
+  await promiseNativeMouseEventAndWaitForEvent({
+    type: "mousemove",
+    target: gBrowserElement,
+    offsetX: -20,
+    offsetY: -20,
+    win: gLeftWindow,
+    scale: "screenPixelsPerCSSPixelNoOverride",
+    eventTypeToWait: "mouseover",
+    eventTargetToListen: gLeftWindow,
+  });
+  ok(true, `"mouseover" event is fired on the left window when cursor is moved into it`);
 
-      // Move over the browser
-      expectMouseOut = true;
-      moveMouseTo(150, 150, function () {
-        ok (!expectMouseOut, "Should have got mouseout event");
-        gLeftWindow.removeEventListener("mouseover", mouseOverListener);
-        gLeftWindow.removeEventListener("mouseout", mouseOutListener);
-        test2();
-      });
-    });
+  // Move over the browser
+  info(`Synthesizing native "mousemove" event on the content in the left window...`);
+  await promiseNativeMouseEventAndWaitForEvent({
+    type: "mousemove",
+    target: gBrowserElement,
+    atCenter: true,
+    win: gLeftWindow,
+    scale: "screenPixelsPerCSSPixelNoOverride",
+    eventTypeToWait: "mouseout",
+    eventTargetToListen: gLeftWindow,
   });
+  ok(true, `"mouseout" event is fired on the left window when cursor is moved into its child browser`);
 }
 
-function test2() {
+async function test2() {
   // Make the browser cover the whole window.
   gBrowserElement.style.margin = "0";
   gBrowserElement.style.width = gBrowserElement.style.height = "200px";
 
   // Add a box to the browser at the left edge.
   var doc = gBrowserElement.contentDocument;
   var box = doc.createElement("div");
   box.setAttribute("id", "box");
@@ -111,65 +107,86 @@ function test2() {
   box.style.backgroundColor = "green";
   doc.body.appendChild(box);
 
   ok(!box.matches(":hover"), "Box shouldn't be hovered (since the mouse isn't over it and since it's in a non-clickthrough browser in a background window)");
 
   // A function to waitForFocus and then wait for synthetic mouse
   // events to happen.  Note that those happen off the refresh driver,
   // and happen after animation frame requests.
-  function changeFocusAndAwaitSyntheticMouse(callback, winToFocus,
+  function changeFocusAndAwaitSyntheticMouse(winToFocus,
                                              elementToWatchForMouseEventOn) {
-     function mouseWatcher() {
-       elementToWatchForMouseEventOn.removeEventListener("mouseover",
-                                                         mouseWatcher);
-       elementToWatchForMouseEventOn.removeEventListener("mouseout",
-                                                         mouseWatcher);
-       SimpleTest.executeSoon(callback);
-     }
-     elementToWatchForMouseEventOn.addEventListener("mouseover",
-                                                    mouseWatcher);
-     elementToWatchForMouseEventOn.addEventListener("mouseout",
-                                                    mouseWatcher);
-     // Just pass a dummy function to waitForFocus; the mouseout/over listener
-     // will actually handle things for us.
-     SimpleTest.waitForFocus(function() {}, winToFocus);
+    return Promise.all([
+      new Promise(resolve => {
+        function mouseWatcher() {
+          elementToWatchForMouseEventOn.removeEventListener("mouseover",
+                                                            mouseWatcher);
+          elementToWatchForMouseEventOn.removeEventListener("mouseout",
+                                                            mouseWatcher);
+          SimpleTest.executeSoon(resolve);
+        }
+        elementToWatchForMouseEventOn.addEventListener("mouseover",
+                                                      mouseWatcher);
+        elementToWatchForMouseEventOn.addEventListener("mouseout",
+                                                      mouseWatcher);
+      }),
+      new Promise(resolve => SimpleTest.waitForFocus(resolve, winToFocus)),
+    ]);
   }
 
   // Move the mouse over the box.
-  moveMouseTo(100, 150, function () {
-    ok(!box.matches(":hover"), "Box shouldn't be hovered (since it's in a non-clickthrough browser in a background window)");
-    // Activate the left window.
-    changeFocusAndAwaitSyntheticMouse(function () {
-      ok(gBrowserElement.matches(":hover"), "browser should be hovered");
-      ok(box.matches(":hover"), "Box should be hovered");
-      // De-activate the window (by activating the right window).
-      changeFocusAndAwaitSyntheticMouse(function () {
-        ok(!gBrowserElement.matches(":hover"), "browser shouldn't be hovered");
-        ok(!box.matches(":hover"), "Box shouldn't be hovered");
-        // Re-activate it.
-        changeFocusAndAwaitSyntheticMouse(function () {
-          ok(gBrowserElement.matches(":hover"), "browser should be hovered");
-          ok(box.matches(":hover"), "Box should be hovered");
-          // Unhover box and browser by moving the mouse outside the window.
-          moveMouseTo(0, 150, function () {
-            ok(!gBrowserElement.matches(":hover"), "browser shouldn't be hovered");
-            ok(!box.matches(":hover"), "box shouldn't be hovered");
-            finalize();
-          });
-        }, gLeftWindow, box);
-      }, gRightWindow, box);
-    }, gLeftWindow, box);
+  info(`Synthesizing native "mousemove" event into the box...`);
+  await promiseNativeMouseEvent({
+    type: "mousemove",
+    target: box,
+    atCenter: true,
+    win: gLeftWindow,
+    scale: "screenPixelsPerCSSPixelNoOverride",
   });
-}
+  await new Promise(resolve =>
+    requestAnimationFrame(() => SimpleTest.executeSoon(resolve))
+  );
+  // XXX We cannot guarantee that the native mousemouse have already handled here.
+  ok(!box.matches(":hover"), "Box shouldn't be hovered (since it's in a non-clickthrough browser in a background window)");
+
+  // Activate the left window.
+  info("Waiting the left window activated...");
+  await changeFocusAndAwaitSyntheticMouse(gLeftWindow, box);
+  ok(gBrowserElement.matches(":hover"), "browser should be hovered");
+  ok(box.matches(":hover"), "Box should be hovered");
+
+  // De-activate the window (by activating the right window).
+  info("Waiting the right window activated...");
+  await changeFocusAndAwaitSyntheticMouse(gRightWindow, box);
+  ok(!gBrowserElement.matches(":hover"), "browser shouldn't be hovered");
+  ok(!box.matches(":hover"), "Box shouldn't be hovered");
 
-function finalize() {
-  gRightWindow.close();
-  gLeftWindow.close();
-  SimpleTest.finish();
+  // Re-activate it.
+  info("Waiting the left window activated again...");
+  await changeFocusAndAwaitSyntheticMouse(gLeftWindow, box);
+  ok(gBrowserElement.matches(":hover"), "browser should be hovered");
+  ok(box.matches(":hover"), "Box should be hovered");
+
+  // Unhover the box and the left window.
+  info(`Synthesizing native "mousemove" event outside the box and the left window...`);
+  await promiseNativeMouseEventAndWaitForEvent({
+    type: "mousemove",
+    screenX: 0,
+    screenY: 0,
+    scale: "inScreenPixels",
+    win: gLeftWindow,
+    eventTargetToListen: box,
+    eventTypeToWait: "mouseout",
+  });
+  await new Promise(resolve =>
+    requestAnimationFrame(() => SimpleTest.executeSoon(resolve))
+  );
+
+  ok(!gBrowserElement.matches(":hover"), "browser shouldn't be hovered");
+  ok(!box.matches(":hover"), "box shouldn't be hovered");
 }
 
 SimpleTest.waitForExplicitFinish();
 SimpleTest.waitForFocus(openWindows);
 
 ]]>
 </script>