1<!DOCTYPE HTML>
2<meta name="timeout" content="long">
3<meta name="viewport" content="width=device-width,initial-scale=1,minimum-scale=1">
4<script src="/resources/testharness.js"></script>
5<script src="/resources/testharnessreport.js"></script>
6<script src="/resources/testdriver.js"></script>
7<script src="/resources/testdriver-actions.js"></script>
8<script src="/resources/testdriver-vendor.js"></script>
9<script src="scroll_support.js"></script>
10<style>
11html {
12  height: 3000px;
13  width: 3000px;
14}
15#targetDiv {
16  width: 200px;
17  height: 200px;
18  overflow: scroll;
19}
20
21#innerDiv {
22  width: 400px;
23  height: 400px;
24}
25</style>
26
27<body style="margin:0" onload=runTest()>
28<div id="targetDiv">
29  <div id="innerDiv">
30  </div>
31</div>
32</body>
33<script>
34var element_scrollend_arrived = false;
35var document_scrollend_arrived = false;
36
37function onElementScrollEnd(event) {
38  assert_false(event.cancelable);
39  assert_false(event.bubbles);
40  element_scrollend_arrived = true;
41}
42
43function onDocumentScrollEnd(event) {
44  assert_false(event.cancelable);
45  // scrollend events are bubbled when the target node is document.
46  assert_true(event.bubbles);
47  document_scrollend_arrived = true;
48}
49
50function callScrollFunction([scrollTarget, scrollFunction, args]) {
51  scrollTarget[scrollFunction](args);
52}
53
54function runTest() {
55  let root_element = document.scrollingElement;
56  let target_div = document.getElementById("targetDiv");
57  let inner_div = document.getElementById("innerDiv");
58
59  // Get expected position for root_element scrollIntoView.
60  root_element.scrollTo(10000, 10000);
61  let max_root_x = root_element.scrollLeft;
62  let max_root_y = root_element.scrollTop;
63  root_element.scrollTo(0, 0);
64
65  target_div.scrollTo(10000, 10000);
66  let max_element_x = target_div.scrollLeft;
67  let max_element_y = target_div.scrollTop;
68  target_div.scrollTo(0, 0);
69
70  promise_test (async (t) => {
71    await waitForCompositorCommit();
72    target_div.addEventListener("scrollend", onElementScrollEnd);
73    document.addEventListener("scrollend", onDocumentScrollEnd);
74
75    let test_cases = [
76      [target_div, max_element_x, max_element_y, [inner_div, "scrollIntoView", { inline: "end", block: "end", behavior: "auto" }]],
77      [target_div, 0, 0, [inner_div, "scrollIntoView", { inline: "start", block: "start", behavior: "smooth" }]],
78      [root_element, max_root_x, max_root_y, [root_element, "scrollIntoView", { inline: "end", block: "end", behavior: "smooth" }]],
79      [root_element, 0, 0, [root_element, "scrollIntoView", { inline: "start", block: "start", behavior: "smooth" }]]
80    ];
81
82    for(i = 0; i < test_cases.length; i++) {
83      let t = test_cases[i];
84      let target = t[0];
85      let expected_x = t[1];
86      let expected_y = t[2];
87      let scroll_datas = t[3];
88
89      callScrollFunction(scroll_datas);
90      await waitFor(() => { return element_scrollend_arrived || document_scrollend_arrived; }, target.tagName + ".scrollIntoView  did not receive scrollend event.");
91      if (target == root_element)
92        assert_false(element_scrollend_arrived);
93      else
94        assert_false(document_scrollend_arrived);
95      assert_equals(target.scrollLeft, expected_x, target.tagName + ".scrollIntoView scrollLeft");
96      assert_equals(target.scrollTop, expected_y, target.tagName + ".scrollIntoView scrollTop");
97
98      element_scrollend_arrived = false;
99      document_scrollend_arrived = false;
100    }
101  }, "Tests scrollend event for scrollIntoView.");
102
103  promise_test(async (t) => {
104    document.body.removeChild(target_div);
105    let out_div = document.createElement("div");
106    out_div.style = "width: 100px; height:100px; overflow:scroll; scroll-behavior:smooth;";
107    out_div.appendChild(target_div);
108    document.body.appendChild(out_div);
109    await waitForCompositorCommit();
110
111    element_scrollend_arrived = false;
112    document_scrollend_arrived = false;
113    inner_div.scrollIntoView({ inline: "end", block: "end", behavior: "auto" });
114    await waitFor(() => { return element_scrollend_arrived || document_scrollend_arrived; }, "Nested scrollIntoView did not receive scrollend event.");
115    assert_equals(root_element.scrollLeft, 0, "Nested scrollIntoView root_element scrollLeft");
116    assert_equals(root_element.scrollTop, 0, "Nested scrollIntoView root_element scrollTop");
117    assert_equals(out_div.scrollLeft, 100, "Nested scrollIntoView out_div scrollLeft");
118    assert_equals(out_div.scrollTop, 100, "Nested scrollIntoView out_div scrollTop");
119    assert_equals(target_div.scrollLeft, max_element_x, "Nested scrollIntoView target_div scrollLeft");
120    assert_equals(target_div.scrollTop, max_element_y, "Nested scrollIntoView target_div scrollTop");
121    assert_false(document_scrollend_arrived);
122  }, "Tests scrollend event for nested scrollIntoView.");
123}
124</script>
125