Bug 1368603 - Fix intermittent scrollbar drag test failure on Linux. r?botond
On Linux, when synthesizing mousemove events interleaved with button
press/release events, the caller is responsible for waiting for the
mousemove events be dispatched before attempting to synthesize the
press/release buttons, otherwise the events can be delivered by the OS
out of order. This updates a few tests to ensure this is done correctly.
MozReview-Commit-ID: 42HkqTCWToP
--- a/gfx/layers/apz/test/mochitest/apz_test_native_event_utils.js
+++ b/gfx/layers/apz/test/mochitest/apz_test_native_event_utils.js
@@ -340,18 +340,22 @@ function moveMouseAndScrollWheelOver(ele
} else {
synthesizeNativeWheelAndWaitForWheelEvent(element, dx, dy, 0, -10, testDriver);
}
});
}
// Synthesizes events to drag |element|'s vertical scrollbar by the distance
// specified, synthesizing a mousemove for each increment as specified.
-// Returns false if the element doesn't have a vertical scrollbar, or true after
-// all the events have been synthesized.
+// Returns false if the element doesn't have a vertical scrollbar. Otherwise,
+// returns a generator that should be invoked after the mousemoves have been
+// processed by the widget code, to end the scrollbar drag. Mousemoves being
+// processed by the widget code can be detected by listening for the mousemove
+// events in the caller, or for some other event that is triggered by the
+// mousemove, such as the scroll event resulting from the scrollbar drag.
function* dragVerticalScrollbar(element, testDriver, distance = 20, increment = 5) {
var boundingClientRect = element.getBoundingClientRect();
var verticalScrollbarWidth = boundingClientRect.width - element.clientWidth;
if (verticalScrollbarWidth == 0) {
return false;
}
var upArrowHeight = verticalScrollbarWidth; // assume square scrollbar buttons
@@ -364,13 +368,15 @@ function* dragVerticalScrollbar(element,
yield synthesizeNativeMouseEvent(element, mouseX, mouseY, nativeMouseMoveEventMsg(), testDriver);
// mouse down
yield synthesizeNativeMouseEvent(element, mouseX, mouseY, nativeMouseDownEventMsg(), testDriver);
// drag vertically by |increment| until we reach the specified distance
for (var y = increment; y < distance; y += increment) {
yield synthesizeNativeMouseEvent(element, mouseX, mouseY + y, nativeMouseMoveEventMsg(), testDriver);
}
yield synthesizeNativeMouseEvent(element, mouseX, mouseY + distance, nativeMouseMoveEventMsg(), testDriver);
- // and release
- yield synthesizeNativeMouseEvent(element, mouseX, mouseY + distance, nativeMouseUpEventMsg(), testDriver);
- return true;
+ // and return a generator to call afterwards to finish up the drag
+ return function*() {
+ dump("Finishing drag of #" + element.id + "\n");
+ yield synthesizeNativeMouseEvent(element, mouseX, mouseY + distance, nativeMouseUpEventMsg(), testDriver);
+ };
}
--- a/gfx/layers/apz/test/mochitest/apz_test_utils.js
+++ b/gfx/layers/apz/test/mochitest/apz_test_utils.js
@@ -232,16 +232,18 @@ function runSubtestsSeriallyInFreshWindo
test = aSubtests[testIndex];
if (onlyOneSubtest && onlyOneSubtest != test.file) {
SimpleTest.ok(true, "Skipping " + test.file + " because only " + onlyOneSubtest + " is being run");
setTimeout(function() { advanceSubtestExecution(); }, 0);
return;
}
+ SimpleTest.ok(true, "Starting subtest " + test.file);
+
if (typeof test.dp_suppression != 'undefined') {
// Normally during a test, the displayport will get suppressed during page
// load, and unsuppressed at a non-deterministic time during the test. The
// unsuppression can trigger a repaint which interferes with the test, so
// to avoid that we can force the displayport to be unsuppressed for the
// entire test which is more deterministic.
SpecialPowers.getDOMWindowUtils(window).respectDisplayPortSuppression(test.dp_suppression);
}
--- a/gfx/layers/apz/test/mochitest/helper_bug1326290.html
+++ b/gfx/layers/apz/test/mochitest/helper_bug1326290.html
@@ -19,27 +19,29 @@
}
</style>
<script type="text/javascript">
function* test(testDriver) {
var scrollableDiv = document.getElementById('scrollable');
scrollableDiv.addEventListener('scroll', () => setTimeout(testDriver, 0), {once: true});
- var scrolled = yield* dragVerticalScrollbar(scrollableDiv, testDriver);
- if (!scrolled) {
+ var dragFinisher = yield* dragVerticalScrollbar(scrollableDiv, testDriver);
+ if (!dragFinisher) {
ok(true, "No scrollbar, can't do this test");
return;
}
// the events above might be stuck in APZ input queue for a bit until the
// layer is activated, so we wait here until the scroll event listener is
// triggered.
yield;
+ yield* dragFinisher();
+
// Flush everything just to be safe
yield flushApzRepaints(testDriver);
// After dragging the scrollbar 20px on a 200px-high scrollable div, we should
// have scrolled approx 10% of the 2000px high content. There might have been
// scroll arrows and such so let's just have a minimum bound of 50px to be safe.
ok(scrollableDiv.scrollTop > 50, "Scrollbar drag resulted in a scroll position of " + scrollableDiv.scrollTop);
}
--- a/gfx/layers/apz/test/mochitest/helper_bug1331693.html
+++ b/gfx/layers/apz/test/mochitest/helper_bug1331693.html
@@ -8,27 +8,29 @@
<script type="application/javascript" src="apz_test_utils.js"></script>
<script type="application/javascript" src="/tests/SimpleTest/paint_listener.js"></script>
<script type="text/javascript">
function* test(testDriver) {
var scrollableDiv = document.getElementById('scrollable');
scrollableDiv.addEventListener('scroll', () => setTimeout(testDriver, 0), {once: true});
- var scrolled = yield* dragVerticalScrollbar(scrollableDiv, testDriver);
- if (!scrolled) {
+ var dragFinisher = yield* dragVerticalScrollbar(scrollableDiv, testDriver);
+ if (!dragFinisher) {
ok(true, "No scrollbar, can't do this test");
return;
}
// the events above might be stuck in APZ input queue for a bit until the
// layer is activated, so we wait here until the scroll event listener is
// triggered.
yield;
+ yield* dragFinisher();
+
// Flush everything just to be safe
yield flushApzRepaints(testDriver);
// After dragging the scrollbar 20px on a 200px-high scrollable div, we should
// have scrolled approx 10% of the 2000px high content. There might have been
// scroll arrows and such so let's just have a minimum bound of 50px to be safe.
ok(scrollableDiv.scrollTop > 50, "Scrollbar drag resulted in a scroll position of " + scrollableDiv.scrollTop);
}
--- a/gfx/layers/apz/test/mochitest/helper_bug1346632.html
+++ b/gfx/layers/apz/test/mochitest/helper_bug1346632.html
@@ -20,57 +20,40 @@
z-index: 1000;
overflow-y: scroll;
}
#fixed-content {
height: 2000px;
}
</style>
<script type="text/javascript">
-var root;
-var scrollPos;
-var haveScrolled = false;
-var generatedAll = false;
-
-// Be careful not to call subtestDone() until we've scrolled AND generated
-// all of the events.
-function maybeDone() {
- if (haveScrolled && generatedAll) {
- subtestDone();
- }
-}
-
-function scrolled(e) {
- // Test that we have scrolled
- ok(root.scrollTop > scrollPos, "document scrolled after dragging scrollbar");
- haveScrolled = true;
- maybeDone();
-}
-
function* test(testDriver) {
- root = document.scrollingElement;
- scrollPos = root.scrollTop;
- document.addEventListener('scroll', scrolled);
+ var root = document.scrollingElement;
+ var scrollPos = root.scrollTop;
+ document.addEventListener('scroll', () => {
+ ok(root.scrollTop > scrollPos, "document scrolled after dragging scrollbar");
+ setTimeout(testDriver, 0);
+ }, {once: true});
var scrollbarX = (window.innerWidth + root.clientWidth) / 2;
// Move the mouse to the scrollbar
yield synthesizeNativeMouseEvent(root, scrollbarX, 100, nativeMouseMoveEventMsg(), testDriver);
// mouse down
yield synthesizeNativeMouseEvent(root, scrollbarX, 100, nativeMouseDownEventMsg(), testDriver);
// drag vertically
yield synthesizeNativeMouseEvent(root, scrollbarX, 150, nativeMouseMoveEventMsg(), testDriver);
+ // wait for the scroll listener to fire, which will resume this function
+ yield;
// and release
yield synthesizeNativeMouseEvent(root, scrollbarX, 150, nativeMouseUpEventMsg(), testDriver);
-
- generatedAll = true;
- maybeDone();
}
waitUntilApzStable()
-.then(runContinuation(test));
+.then(runContinuation(test))
+.then(subtestDone);
</script>
</head>
<body>
<div id="fixed">
<p id="fixed-content"></p>
</div>
</body>
--- a/gfx/layers/apz/test/mochitest/helper_bug1462961.html
+++ b/gfx/layers/apz/test/mochitest/helper_bug1462961.html
@@ -12,27 +12,29 @@
function* test(testDriver) {
var scrollableDiv = document.getElementById('scrollable');
scrollableDiv.addEventListener('scroll', () => setTimeout(testDriver, 0), {once: true});
// Scroll down a small amount (10px). The bug in this case is that the
// scrollthumb remains a little "above" where it's supposed to be, so if the
// bug manifests here, then the thumb will remain at the top of the track
// and the scroll position will remain at 0.
- var scrolled = yield* dragVerticalScrollbar(scrollableDiv, testDriver, 10, 10);
- if (!scrolled) {
+ var dragFinisher = yield* dragVerticalScrollbar(scrollableDiv, testDriver, 10, 10);
+ if (!dragFinisher) {
ok(true, "No scrollbar, can't do this test");
return;
}
// the events above might be stuck in APZ input queue for a bit until the
// layer is activated, so we wait here until the scroll event listener is
// triggered.
yield;
+ yield* dragFinisher();
+
// Flush everything just to be safe
yield flushApzRepaints(testDriver);
// In this case we just want to make sure the scroll position moved from 0
// which indicates the thumb dragging worked properly.
ok(scrollableDiv.scrollTop > 0, "Scrollbar drag resulted in a scroll position of " + scrollableDiv.scrollTop);
}