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
This commit is contained in:
Masayuki Nakano 2021-02-24 07:01:16 +00:00
parent 36a819f0cc
commit b60a352c71
2 changed files with 107 additions and 90 deletions

View file

@ -73,7 +73,7 @@ support-files = bug586713_window.xhtml
skip-if = toolkit != "cocoa" skip-if = toolkit != "cocoa"
[test_bug596600.xhtml] [test_bug596600.xhtml]
support-files = file_bug596600.html 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] [test_bug673301.xhtml]
skip-if = toolkit != "cocoa" skip-if = toolkit != "cocoa"
[test_secure_input.html] [test_secure_input.html]

View file

@ -23,21 +23,6 @@
const XUL_NS = "http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"; const XUL_NS = "http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul";
var gLeftWindow, gRightWindow, gBrowserElement; 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() { function openWindows() {
gLeftWindow = window.browsingContext.topChromeWindow gLeftWindow = window.browsingContext.topChromeWindow
@ -57,44 +42,55 @@ function attachBrowserToLeftWindow() {
gBrowserElement.style.height = "100px"; gBrowserElement.style.height = "100px";
gBrowserElement.style.margin = "50px"; gBrowserElement.style.margin = "50px";
gLeftWindow.document.documentElement.appendChild(gBrowserElement); gLeftWindow.document.documentElement.appendChild(gBrowserElement);
gBrowserElement.addEventListener("load", function (e) { gBrowserElement.addEventListener("load", async () => {
test1(); await test1();
await test2();
gRightWindow.close();
gLeftWindow.close();
SimpleTest.finish();
}, { capture: true, once: true }); }, { capture: true, once: true });
} }
function test1() { async function test1() {
// gRightWindow is active, gLeftWindow is inactive. // gRightWindow is active, gLeftWindow is inactive.
moveMouseTo(0, 0, function () { info(`Synthesizing native "mousemove" event at top-left of the screen...`);
var expectMouseOver = false, expectMouseOut = false; await promiseNativeMouseEvent({
function mouseOverListener(e) { type: "mousemove",
ok(expectMouseOver, "Got expected mouseover at " + e.screenX + ", " + e.screenY); screenX: 0,
expectMouseOver = false; screenY: 0,
} scale: "inScreenPixels",
function mouseOutListener(e) { });
ok(expectMouseOut, "Got expected mouseout at " + e.screenX + ", " + e.screenY); await new Promise(resolve => SimpleTest.executeSoon(resolve));
expectMouseOut = false;
}
gLeftWindow.addEventListener("mouseover", mouseOverListener);
gLeftWindow.addEventListener("mouseout", mouseOutListener);
// Move into the left window // Move into the left window
expectMouseOver = true; info(`Synthesizing native "mousemove" event in the left window (but outside the content)...`);
moveMouseTo(80, 80, function () { await promiseNativeMouseEventAndWaitForEvent({
ok(!expectMouseOver, "Should have got mouseover event"); 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 // Move over the browser
expectMouseOut = true; info(`Synthesizing native "mousemove" event on the content in the left window...`);
moveMouseTo(150, 150, function () { await promiseNativeMouseEventAndWaitForEvent({
ok (!expectMouseOut, "Should have got mouseout event"); type: "mousemove",
gLeftWindow.removeEventListener("mouseover", mouseOverListener); target: gBrowserElement,
gLeftWindow.removeEventListener("mouseout", mouseOutListener); atCenter: true,
test2(); 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. // Make the browser cover the whole window.
gBrowserElement.style.margin = "0"; gBrowserElement.style.margin = "0";
gBrowserElement.style.width = gBrowserElement.style.height = "200px"; gBrowserElement.style.width = gBrowserElement.style.height = "200px";
@ -116,55 +112,76 @@ function test2() {
// A function to waitForFocus and then wait for synthetic mouse // A function to waitForFocus and then wait for synthetic mouse
// events to happen. Note that those happen off the refresh driver, // events to happen. Note that those happen off the refresh driver,
// and happen after animation frame requests. // and happen after animation frame requests.
function changeFocusAndAwaitSyntheticMouse(callback, winToFocus, function changeFocusAndAwaitSyntheticMouse(winToFocus,
elementToWatchForMouseEventOn) { elementToWatchForMouseEventOn) {
return Promise.all([
new Promise(resolve => {
function mouseWatcher() { function mouseWatcher() {
elementToWatchForMouseEventOn.removeEventListener("mouseover", elementToWatchForMouseEventOn.removeEventListener("mouseover",
mouseWatcher); mouseWatcher);
elementToWatchForMouseEventOn.removeEventListener("mouseout", elementToWatchForMouseEventOn.removeEventListener("mouseout",
mouseWatcher); mouseWatcher);
SimpleTest.executeSoon(callback); SimpleTest.executeSoon(resolve);
} }
elementToWatchForMouseEventOn.addEventListener("mouseover", elementToWatchForMouseEventOn.addEventListener("mouseover",
mouseWatcher); mouseWatcher);
elementToWatchForMouseEventOn.addEventListener("mouseout", elementToWatchForMouseEventOn.addEventListener("mouseout",
mouseWatcher); mouseWatcher);
// Just pass a dummy function to waitForFocus; the mouseout/over listener }),
// will actually handle things for us. new Promise(resolve => SimpleTest.waitForFocus(resolve, winToFocus)),
SimpleTest.waitForFocus(function() {}, winToFocus); ]);
} }
// Move the mouse over the box. // Move the mouse over the box.
moveMouseTo(100, 150, function () { 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)"); 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. // Activate the left window.
changeFocusAndAwaitSyntheticMouse(function () { info("Waiting the left window activated...");
await changeFocusAndAwaitSyntheticMouse(gLeftWindow, box);
ok(gBrowserElement.matches(":hover"), "browser should be hovered"); ok(gBrowserElement.matches(":hover"), "browser should be hovered");
ok(box.matches(":hover"), "Box should be hovered"); ok(box.matches(":hover"), "Box should be hovered");
// De-activate the window (by activating the right window). // De-activate the window (by activating the right window).
changeFocusAndAwaitSyntheticMouse(function () { info("Waiting the right window activated...");
await changeFocusAndAwaitSyntheticMouse(gRightWindow, box);
ok(!gBrowserElement.matches(":hover"), "browser shouldn't be hovered"); ok(!gBrowserElement.matches(":hover"), "browser shouldn't be hovered");
ok(!box.matches(":hover"), "Box shouldn't be hovered"); ok(!box.matches(":hover"), "Box shouldn't be hovered");
// Re-activate it. // Re-activate it.
changeFocusAndAwaitSyntheticMouse(function () { info("Waiting the left window activated again...");
await changeFocusAndAwaitSyntheticMouse(gLeftWindow, box);
ok(gBrowserElement.matches(":hover"), "browser should be hovered"); ok(gBrowserElement.matches(":hover"), "browser should be hovered");
ok(box.matches(":hover"), "Box 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 () { // 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(!gBrowserElement.matches(":hover"), "browser shouldn't be hovered");
ok(!box.matches(":hover"), "box shouldn't be hovered"); ok(!box.matches(":hover"), "box shouldn't be hovered");
finalize();
});
}, gLeftWindow, box);
}, gRightWindow, box);
}, gLeftWindow, box);
});
}
function finalize() {
gRightWindow.close();
gLeftWindow.close();
SimpleTest.finish();
} }
SimpleTest.waitForExplicitFinish(); SimpleTest.waitForExplicitFinish();