test_click_scrolling.py (6685B)
1 # This Source Code Form is subject to the terms of the Mozilla Public 2 # License, v. 2.0. If a copy of the MPL was not distributed with this 3 # file, You can obtain one at http://mozilla.org/MPL/2.0/. 4 5 from urllib.parse import quote 6 7 from marionette_driver.by import By 8 from marionette_driver.errors import MoveTargetOutOfBoundsException 9 10 from marionette_harness import MarionetteTestCase 11 12 13 def inline(doc): 14 return "data:text/html;charset=utf-8,{}".format(quote(doc)) 15 16 17 class TestClickScrolling(MarionetteTestCase): 18 def setUp(self): 19 super(TestClickScrolling, self).setUp() 20 21 # Reset the scroll position for each test 22 self.marionette.execute_script("window.scrollTo(0, 0);") 23 24 def test_clicking_on_anchor_scrolls_page(self): 25 self.marionette.navigate( 26 inline( 27 """ 28 <a href="#content">Link to content</a> 29 <div id="content" style="margin-top: 205vh;">Text</div> 30 """ 31 ) 32 ) 33 34 # Focusing on to click, but not actually following, 35 # the link will scroll it in to view, which is a few 36 # pixels further than 0 37 self.marionette.find_element(By.CSS_SELECTOR, "a").click() 38 39 y_offset = self.marionette.execute_script( 40 """ 41 var pageY; 42 if (typeof(window.pageYOffset) == 'number') { 43 pageY = window.pageYOffset; 44 } else { 45 pageY = document.documentElement.scrollTop; 46 } 47 return pageY; 48 """ 49 ) 50 51 self.assertGreater(y_offset, 300) 52 53 def test_should_scroll_to_click_on_an_element_hidden_by_overflow(self): 54 test_html = self.marionette.absolute_url("click_out_of_bounds_overflow.html") 55 self.marionette.navigate(test_html) 56 57 link = self.marionette.find_element(By.ID, "link") 58 try: 59 link.click() 60 except MoveTargetOutOfBoundsException: 61 self.fail("Should not be out of bounds") 62 63 def test_should_not_scroll_elements_if_click_point_is_in_view(self): 64 test_html = self.marionette.absolute_url("element_outside_viewport.html") 65 66 for s in ["top", "right", "bottom", "left"]: 67 for p in ["50", "30"]: 68 self.marionette.navigate(test_html) 69 [scroll_x, scroll_y] = self.marionette.execute_script( 70 "return [window.scrollX, window.scrollY];" 71 ) 72 self.marionette.find_element(By.ID, "{0}-{1}".format(s, p)).click() 73 [new_scroll_x, new_scroll_y] = self.marionette.execute_script( 74 "return [window.scrollX, window.scrollY];" 75 ) 76 77 # Account for potential rounding errors. 78 # TODO It may be possible to remove the fuzzy check once 79 # bug 1852884 and bug 1774315 are fixed. 80 assert (scroll_x - 1) <= new_scroll_x <= (scroll_x + 1) 81 assert (scroll_y - 1) <= new_scroll_y <= (scroll_y + 1) 82 83 def test_do_not_scroll_again_if_element_is_already_in_view(self): 84 self.marionette.navigate( 85 inline( 86 """ 87 <div style="height: 200vh;"> 88 <button id="button1" style="margin-top: 105vh">Button1</button> 89 <button id="button2" style="position: relative; top: 5em">Button2</button> 90 </div> 91 """ 92 ) 93 ) 94 button1 = self.marionette.find_element(By.ID, "button1") 95 button2 = self.marionette.find_element(By.ID, "button2") 96 97 button2.click() 98 scroll_top = self.marionette.execute_script("return document.body.scrollTop;") 99 button1.click() 100 101 new_scroll_top = self.marionette.execute_script( 102 "return document.body.scrollTop;" 103 ) 104 # Account for potential rounding errors. 105 # TODO It may be possible to remove the fuzzy check once 106 # bug 1852884 and bug 1774315 are fixed. 107 assert (scroll_top - 1) <= new_scroll_top <= (scroll_top + 1) 108 109 def test_scroll_radio_button_into_view(self): 110 self.marionette.navigate( 111 inline( 112 """ 113 <input type="radio" id="radio" style="margin-top: 105vh;"> 114 """ 115 ) 116 ) 117 self.marionette.find_element(By.ID, "radio").click() 118 119 def test_overflow_scroll_do_not_scroll_elements_which_are_visible(self): 120 self.marionette.navigate( 121 inline( 122 """ 123 <ul style='overflow: scroll; height: 8em; line-height: 3em'> 124 <li></li> 125 <li id="desired">Text</li> 126 <li></li> 127 <li></li> 128 </ul> 129 """ 130 ) 131 ) 132 133 list_el = self.marionette.find_element(By.TAG_NAME, "ul") 134 expected_y_offset = self.marionette.execute_script( 135 "return arguments[0].scrollTop;", script_args=(list_el,) 136 ) 137 138 item = list_el.find_element(By.ID, "desired") 139 item.click() 140 141 y_offset = self.marionette.execute_script( 142 "return arguments[0].scrollTop;", script_args=(list_el,) 143 ) 144 # Account for potential rounding errors. 145 # TODO It may be possible to remove the fuzzy check once 146 # bug 1852884 and bug 1774315 are fixed. 147 assert (expected_y_offset - 1) <= y_offset <= (expected_y_offset + 1) 148 149 def test_overflow_scroll_click_on_hidden_element(self): 150 self.marionette.navigate( 151 inline( 152 """ 153 Result: <span id="result"></span> 154 <ul style='overflow: scroll; width: 150px; height: 8em; line-height: 4em' 155 onclick="document.getElementById('result').innerText = event.target.id;"> 156 <li>line1</li> 157 <li>line2</li> 158 <li>line3</li> 159 <li id="line4">line4</li> 160 </ul> 161 """ 162 ) 163 ) 164 165 self.marionette.find_element(By.ID, "line4").click() 166 self.assertEqual("line4", self.marionette.find_element(By.ID, "result").text) 167 168 def test_overflow_scroll_vertically_for_click_point_outside_of_viewport(self): 169 self.marionette.navigate( 170 inline( 171 """ 172 Result: <span id="result"></span> 173 <div style='overflow: scroll; width: 100px; height: 100px; background-color: yellow;'> 174 <div id="inner" style="width: 100px; height: 300px; background-color: green;" 175 onclick="document.getElementById('result').innerText = event.type" ></div> 176 </div> 177 """ 178 ) 179 ) 180 181 self.marionette.find_element(By.ID, "inner").click() 182 self.assertEqual("click", self.marionette.find_element(By.ID, "result").text)