summaryrefslogtreecommitdiffstats
path: root/gfx/layers/apz/test/mochitest/test_wheel_transactions.html
blob: f015ea20be2ab85b129934d5eecf1b814e778dfb (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
<!DOCTYPE HTML>
<html>
<!--
https://bugzilla.mozilla.org/show_bug.cgi?id=1175585
-->
<head>
  <title>Test for Bug 1175585</title>
  <script src="/tests/SimpleTest/SimpleTest.js"></script>
  <script src="/tests/SimpleTest/EventUtils.js"></script>
  <script src="/tests/SimpleTest/paint_listener.js"></script>
  <script type="application/javascript" src="apz_test_native_event_utils.js"></script>
  <script type="application/javascript" src="apz_test_utils.js"></script>
  <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
  <style>
  #outer-frame {
      height: 500px;
      overflow: scroll;
      background: repeating-linear-gradient(#CCC, #CCC 100px, #BBB 100px, #BBB 200px);
  }
  #inner-frame {
      margin-top: 25%;
      height: 200%;
      width: 75%;
      overflow: scroll;
  }
  #inner-content {
      height: 200%;
      width: 200%;
      background: repeating-linear-gradient(#EEE, #EEE 100px, #DDD 100px, #DDD 200px);
  }
  </style>
</head>
<body>
<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=1175585">APZ wheel transactions test</a>
<p id="display"></p>
<div id="outer-frame">
    <div id="inner-frame">
        <div id="inner-content"></div>
    </div>
</div>
<pre id="test">
<script type="application/javascript">

async function scrollWheelOver(element, deltaY) {
  await promiseNativeWheelAndWaitForScrollEvent(element, 10, 10, 0, deltaY);
}

async function test() {
  var outer = document.getElementById("outer-frame");
  var inner = document.getElementById("inner-frame");

  // Register a wheel event listener that records the target of
  // the last wheel event, so that we can make assertions about it.
  let lastWheelTarget;
  let firstWheelTarget;
  let wheelEventOccurred = false;
  var wheelTargetRecorder = function(e) {
    if (!wheelEventOccurred) {
      firstWheelTarget = e.target;
      wheelEventOccurred = true;
    }
    lastWheelTarget = e.target;
  };
  window.addEventListener("wheel", wheelTargetRecorder);

  // Scroll |outer| to the bottom.
  while (outer.scrollTop < outer.scrollTopMax) {
    await scrollWheelOver(outer, -10);
  }

  is(lastWheelTarget, firstWheelTarget,
     "target " + lastWheelTarget.id + " should be " + lastWheelTarget.id);
  window.removeEventListener("wheel", wheelTargetRecorder);

  // Immediately after, scroll it back up a bit.
  await scrollWheelOver(outer, 10);

  // Check that it was |outer| that scrolled back, and |inner| didn't
  // scroll at all, as all the above scrolls should be in the same
  // transaction.
  ok(outer.scrollTop < outer.scrollTopMax, "'outer' should have scrolled back a bit");
  is(inner.scrollTop, 0, "'inner' should not have scrolled");

  // The next part of the test is related to the transaction timeout.
  // Turn it down a bit so waiting for the timeout to elapse doesn't
  // slow down the test harness too much.
  var timeout = 5;
  await SpecialPowers.pushPrefEnv({"set": [["mousewheel.transaction.timeout", timeout]]});
  SimpleTest.requestFlakyTimeout("we are testing code that measures actual elapsed time between two events");

  // Scroll up a bit more. It's still |outer| scrolling because
  // |inner| is still scrolled all the way to the top.
  await scrollWheelOver(outer, 10);

  // Wait for the transaction timeout to elapse.
  // timeout * 5 is used to make it less likely that the timeout is less than
  // the system timestamp resolution
  await SpecialPowers.promiseTimeout(timeout * 5);

  // Now scroll down. The transaction having timed out, the event
  // should pick up a new target, and that should be |inner|.
  await scrollWheelOver(outer, -10);
  ok(inner.scrollTop > 0, "'inner' should have been scrolled");

  // Finally, test scroll handoff after a timeout.

  // Continue scrolling |inner| down to the bottom.
  var prevScrollTop = inner.scrollTop;
  while (inner.scrollTop < inner.scrollTopMax) {
    await scrollWheelOver(outer, -10);
    // Avoid a failure getting us into an infinite loop.
    ok(inner.scrollTop > prevScrollTop, "scrolling down should increase scrollTop");
    prevScrollTop = inner.scrollTop;
  }

  // Wait for the transaction timeout to elapse.
  // timeout * 5 is used to make it less likely that the timeout is less than
  // the system timestamp resolution
  await SpecialPowers.promiseTimeout(timeout * 5);

  // Continued downward scrolling should scroll |outer| to the bottom.
  prevScrollTop = outer.scrollTop;
  while (outer.scrollTop < outer.scrollTopMax) {
    await scrollWheelOver(outer, -10);
    // Avoid a failure getting us into an infinite loop.
    ok(outer.scrollTop > prevScrollTop, "scrolling down should increase scrollTop");
    prevScrollTop = outer.scrollTop;
  }
}

SimpleTest.waitForExplicitFinish();

// Disable smooth scrolling because it makes the test flaky (we don't have a good
// way of detecting when the scrolling is finished).
// Also, on macOS, force the native events to be wheel inputs rather than pan
// inputs since this test is specifically testing things related to wheel
// transactions.
pushPrefs([["general.smoothScroll", false],
           ["apz.test.mac.synth_wheel_input", true],
           ["mousewheel.transaction.timeout", 1500],
           ["dom.event.wheel-event-groups.enabled", true]])
.then(waitUntilApzStable)
.then(test)
.then(SimpleTest.finish, SimpleTest.finishWithFailure);

</script>
</pre>

</body>
</html>