summaryrefslogtreecommitdiffstats
path: root/testing/web-platform/tests/dom/events/scrolling/overscroll-deltas.html
blob: e13e9f1cce5949da74227a1f069f64baad1f517c (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
151
152
153
154
155
156
157
<!DOCTYPE HTML>
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<script src="/resources/testdriver.js"></script>
<script src="/resources/testdriver-actions.js"></script>
<script src="/resources/testdriver-vendor.js"></script>
<script src="scroll_support.js"></script>
<style>
  #hspacer {
    height: 100px;
    width: 100vw;
    top: 0;
    /* on the right edge of targetDiv */
    left: 200px;
    position: absolute;
  }

  #vspacer {
    height: 100vh;
    width: 100px;
    position: absolute;
  }

  #targetDiv {
    width: 200px;
    height: 200px;
    overflow: scroll;
  }

  #innerDiv {
    width: 400px;
    height: 400px;
  }
</style>

<body style="margin:0" onload=runTest()>
  <div id="targetDiv">
    <div id="innerDiv"></div>
  </div>
  <div id="hspacer"></div>
  <div id="vspacer"></div>
</body>

<script>
  var target_div = document.getElementById('targetDiv');
  var overscrolled_x_deltas = [];
  var overscrolled_y_deltas = [];
  var scrollend_received = false;

  function onOverscroll(event) {
    overscrolled_x_deltas.push(event.deltaX);
    overscrolled_y_deltas.push(event.deltaY);
  }

  async function resetScrollers(test) {
    await waitForScrollReset(test, target_div);
    await waitForScrollReset(test, document.scrollingElement);
  }

  function resetOverScrollDeltas() {
    overscrolled_x_deltas = [];
    overscrolled_y_deltas = [];
  }

  function waitForOverscrollEventWithMinDelta(target, min_x = 0, min_y = 0) {
    return new Promise((resolve) => {
      target.addEventListener("overscroll", (evt) => {
        if (evt.deltaX >= min_x && evt.deltaY >= min_y) {
          resolve();
        }
      });
    });
  }

  function unreachedScrollendListener() {
    assert_unreached('Unexpected scrollend event');
  }

  document.addEventListener("overscroll", onOverscroll);

  function runTest() {
    promise_test(async (t) => {
      await resetScrollers(t);
      await waitForCompositorCommit();
      resetOverScrollDeltas();

      assert_equals(document.scrollingElement.scrollTop, 0,
        "document should not be scrolled");

      let scrollend_promise = waitForScrollendEvent(t, target_div);
      let max_target_div_scroll_top = target_div.scrollHeight - target_div.clientHeight;
      target_div.scrollTop = target_div.scrollHeight;
      await scrollend_promise;
      assert_equals(target_div.scrollTop, max_target_div_scroll_top,
      "target_div should be fully scrolled down");

      // Even though we request 300 extra pixels of scroll, the API above doesn't
      // guarantee how much scroll delta will be generated - different browsers
      // can consume different amounts for "touch slop" (for example). Ensure the
      // overscroll reaches at least 250 pixels which is a fairly conservative
      // value.
      let overscroll_promise = waitForOverscrollEventWithMinDelta(document,
          /*min_x*/0, /*min_y*/250);
      scrollend_promise = waitForScrollendEvent(t, document, 2000);
      target_div.addEventListener("scrollend", unreachedScrollendListener);
      // Scroll target div vertically and wait for the doc to get scrollend event.
      await scrollElementDown(target_div, target_div.clientHeight + 300);
      await waitForCompositorCommit();
      await overscroll_promise;
      await scrollend_promise;

      target_div.removeEventListener("scrollend", unreachedScrollendListener);
      assert_greater_than(overscrolled_y_deltas.length, 0, "There should be at least one overscroll events when overscrolling.");
      assert_equals(overscrolled_x_deltas.filter(function (x) { return x != 0; }).length, 0, "The deltaX attribute must be 0 when there is no scrolling in x direction.");
      assert_less_than_equal(Math.max(...overscrolled_y_deltas), 300, "The deltaY attribute must be <= the number of pixels overscrolled (300)");
      assert_greater_than(document.scrollingElement.scrollTop, target_div.clientHeight - 1,
        "document is scrolled by the height of target_div");
    }, "testing, vertical");

    promise_test(async (t) => {
      await resetScrollers(t);
      await waitForCompositorCommit();
      resetOverScrollDeltas();

      assert_equals(document.scrollingElement.scrollLeft, 0,
        "document should not be scrolled");

      let scrollend_promise = waitForScrollendEvent(t, target_div);
      let max_target_div_scroll_left = target_div.scrollWidth - target_div.clientWidth;
      target_div.scrollLeft = target_div.scrollWidth;
      await scrollend_promise;
      assert_equals(target_div.scrollLeft, max_target_div_scroll_left,
        "target_div should be fully scrolled right");

      let overscroll_promise = waitForOverscrollEventWithMinDelta(document,
          /*min_x*/250, /*min_y*/ 0);
      scrollend_promise = waitForScrollendEvent(t, document, 2000);
      target_div.addEventListener("scrollend", unreachedScrollendListener);
      // Scroll target div horizontally and wait for the doc to get scrollend event.
      await scrollElementLeft(target_div, target_div.clientWidth + 300);
      await waitForCompositorCommit();
      await overscroll_promise;
      await scrollend_promise;

      target_div.removeEventListener("scrollend", unreachedScrollendListener);
      assert_greater_than(document.scrollingElement.scrollLeft, target_div.clientWidth - 1,
        "document is scrolled by the height of target_div");
      // TODO(bokan): It looks like Chrome inappropriately filters some scroll
      // events despite |overscroll-behavior| being set to none. The overscroll
      // amount here has been loosened but this should be fixed in Chrome.
      // https://crbug.com/1112183.
      assert_greater_than(overscrolled_x_deltas.length, 0, "There should be at least one overscroll events when overscrolling.");
      assert_equals(overscrolled_y_deltas.filter(function(x){ return x!=0; }).length, 0, "The deltaY attribute must be 0 when there is no scrolling in y direction.");
      assert_less_than_equal(Math.max(...overscrolled_x_deltas), 300, "The deltaX attribute must be <= number of pixels overscrolled (300)");
    }, "testing, horizontal");
  }
</script>