Skip to content

Commit d441930

Browse files
committed
Improve Safari automation, Demo Mode, and Slow Mode
1 parent fe4394b commit d441930

File tree

1 file changed

+110
-34
lines changed

1 file changed

+110
-34
lines changed

seleniumbase/fixtures/base_case.py

Lines changed: 110 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,8 @@ def test_anything(self):
5454
logging.getLogger("urllib3").setLevel(logging.ERROR)
5555
urllib3.disable_warnings()
5656
LOGGER.setLevel(logging.WARNING)
57+
SSMD = constants.Values.SSMD # Smooth Scrolling
58+
JS_Exc = selenium_exceptions.JavascriptException
5759
ECI_Exception = selenium_exceptions.ElementClickInterceptedException
5860
ENI_Exception = selenium_exceptions.ElementNotInteractableException
5961

@@ -136,7 +138,7 @@ def click(self, selector, by=By.CSS_SELECTOR, timeout=None, delay=0):
136138
element = page_actions.wait_for_element_visible(
137139
self.driver, selector, by, timeout=timeout)
138140
self.__demo_mode_highlight_if_active(selector, by)
139-
if not self.demo_mode:
141+
if not self.demo_mode and not self.slow_mode:
140142
self.__scroll_to_element(element, selector, by)
141143
pre_action_url = self.driver.current_url
142144
if delay and delay > 0:
@@ -199,8 +201,10 @@ def slow_click(self, selector, by=By.CSS_SELECTOR, timeout=None):
199201
timeout = settings.SMALL_TIMEOUT
200202
if self.timeout_multiplier and timeout == settings.SMALL_TIMEOUT:
201203
timeout = self.__get_new_timeout(timeout)
202-
if not self.demo_mode:
204+
if not self.demo_mode and not self.slow_mode:
203205
self.click(selector, by=by, timeout=timeout, delay=1.05)
206+
elif self.slow_mode:
207+
self.click(selector, by=by, timeout=timeout, delay=0.65)
204208
else:
205209
# Demo Mode already includes a small delay
206210
self.click(selector, by=by, timeout=timeout, delay=0.25)
@@ -215,7 +219,7 @@ def double_click(self, selector, by=By.CSS_SELECTOR, timeout=None):
215219
element = page_actions.wait_for_element_visible(
216220
self.driver, selector, by, timeout=timeout)
217221
self.__demo_mode_highlight_if_active(selector, by)
218-
if not self.demo_mode:
222+
if not self.demo_mode and not self.slow_mode:
219223
self.__scroll_to_element(element, selector, by)
220224
pre_action_url = self.driver.current_url
221225
try:
@@ -285,7 +289,7 @@ def update_text(self, selector, text, by=By.CSS_SELECTOR,
285289
element = self.wait_for_element_visible(
286290
selector, by=by, timeout=timeout)
287291
self.__demo_mode_highlight_if_active(selector, by)
288-
if not self.demo_mode:
292+
if not self.demo_mode and not self.slow_mode:
289293
self.__scroll_to_element(element, selector, by)
290294
try:
291295
element.clear()
@@ -353,7 +357,7 @@ def add_text(self, selector, text, by=By.CSS_SELECTOR, timeout=None):
353357
element = self.wait_for_element_visible(
354358
selector, by=by, timeout=timeout)
355359
self.__demo_mode_highlight_if_active(selector, by)
356-
if not self.demo_mode:
360+
if not self.demo_mode and not self.slow_mode:
357361
self.__scroll_to_element(element, selector, by)
358362
pre_action_url = self.driver.current_url
359363
try:
@@ -460,17 +464,23 @@ def get_user_agent(self):
460464

461465
def go_back(self):
462466
self.__last_page_load_url = None
463-
self.driver.back()
464-
if self.browser == "safari":
465-
self.driver.refresh()
467+
if self.browser != "safari":
468+
self.driver.back()
469+
else:
470+
self.sleep(0.05)
471+
self.execute_script("window.location=document.referrer;")
472+
self.sleep(0.05)
466473
self.wait_for_ready_state_complete()
467474
self.__demo_mode_pause_if_active()
468475

469476
def go_forward(self):
470477
self.__last_page_load_url = None
471-
self.driver.forward()
472-
if self.browser == "safari":
473-
self.driver.refresh()
478+
if self.browser != "safari":
479+
self.driver.forward()
480+
else:
481+
self.sleep(0.05)
482+
self.execute_script("window.history.forward();")
483+
self.sleep(0.05)
474484
self.wait_for_ready_state_complete()
475485
self.__demo_mode_pause_if_active()
476486

@@ -593,6 +603,23 @@ def click_link_text(self, link_text, timeout=None):
593603
self.open(self.__get_href_from_link_text(link_text))
594604
return
595605
if self.browser == "safari":
606+
if self.demo_mode:
607+
self.wait_for_link_text_present(link_text, timeout=timeout)
608+
try:
609+
self.__jquery_slow_scroll_to(link_text, by=By.LINK_TEXT)
610+
except Exception:
611+
pass
612+
o_bs = '' # original_box_shadow
613+
loops = settings.HIGHLIGHTS
614+
selector = self.convert_to_css_selector(
615+
link_text, by=By.LINK_TEXT)
616+
selector = self.__make_css_match_first_element_only(selector)
617+
try:
618+
selector = re.escape(selector)
619+
selector = self.__escape_quotes_if_needed(selector)
620+
self.__highlight_with_jquery(selector, loops, o_bs)
621+
except Exception:
622+
pass # JQuery probably couldn't load. Skip highlighting.
596623
self.__jquery_click(link_text, by=By.LINK_TEXT)
597624
return
598625
if not self.is_link_text_present(link_text):
@@ -1029,7 +1056,7 @@ def click_visible_elements(self, selector, by=By.CSS_SELECTOR, limit=0):
10291056
continue # ElementClickInterceptedException (Overlay likely)
10301057
except (StaleElementReferenceException, ENI_Exception):
10311058
self.wait_for_ready_state_complete()
1032-
time.sleep(0.03)
1059+
time.sleep(0.04)
10331060
try:
10341061
if element.is_displayed():
10351062
self.__scroll_to_element(element)
@@ -1057,7 +1084,7 @@ def click_nth_visible_element(self, selector, number, by=By.CSS_SELECTOR):
10571084
element.click()
10581085
except (StaleElementReferenceException, ENI_Exception):
10591086
self.wait_for_ready_state_complete()
1060-
time.sleep(0.05)
1087+
time.sleep(0.03)
10611088
self.__scroll_to_element(element)
10621089
element.click()
10631090

@@ -1371,7 +1398,7 @@ def __select_option(self, dropdown_selector, option,
13711398
Select(element).select_by_visible_text(option)
13721399
except (StaleElementReferenceException, ENI_Exception):
13731400
self.wait_for_ready_state_complete()
1374-
time.sleep(0.05)
1401+
time.sleep(0.03)
13751402
element = self.wait_for_element_present(
13761403
dropdown_selector, by=dropdown_by, timeout=timeout)
13771404
if option_by == "index":
@@ -1581,11 +1608,11 @@ def safe_execute_script(self, script):
15811608
it's important that the jQuery library has been loaded first.
15821609
This method will load jQuery if it wasn't already loaded. """
15831610
try:
1584-
self.execute_script(script)
1611+
return self.execute_script(script)
15851612
except Exception:
15861613
# The likely reason this fails is because: "jQuery is not defined"
15871614
self.activate_jquery() # It's a good thing we can define it here
1588-
self.execute_script(script)
1615+
return self.execute_script(script)
15891616

15901617
def set_window_rect(self, x, y, width, height):
15911618
self.driver.set_window_rect(x, y, width, height)
@@ -2047,10 +2074,18 @@ def highlight(self, selector, by=By.CSS_SELECTOR,
20472074
loops = settings.HIGHLIGHTS
20482075
if scroll:
20492076
try:
2050-
self.__slow_scroll_to_element(element)
2051-
except (StaleElementReferenceException, ENI_Exception):
2077+
if self.browser != "safari":
2078+
scroll_distance = js_utils.get_scroll_distance_to_element(
2079+
self.driver, element)
2080+
if abs(scroll_distance) > SSMD:
2081+
self.__jquery_slow_scroll_to(selector, by)
2082+
else:
2083+
self.__slow_scroll_to_element(element)
2084+
else:
2085+
self.__jquery_slow_scroll_to(selector, by)
2086+
except (StaleElementReferenceException, ENI_Exception, JS_Exc):
20522087
self.wait_for_ready_state_complete()
2053-
time.sleep(0.05)
2088+
time.sleep(0.03)
20542089
element = self.wait_for_element_visible(
20552090
selector, by=by, timeout=settings.SMALL_TIMEOUT)
20562091
self.__slow_scroll_to_element(element)
@@ -2071,7 +2106,7 @@ def highlight(self, selector, by=By.CSS_SELECTOR,
20712106
style = element.get_attribute('style')
20722107
except (StaleElementReferenceException, ENI_Exception):
20732108
self.wait_for_ready_state_complete()
2074-
time.sleep(0.05)
2109+
time.sleep(0.03)
20752110
element = self.wait_for_element_visible(
20762111
selector, by=By.CSS_SELECTOR, timeout=settings.SMALL_TIMEOUT)
20772112
style = element.get_attribute('style')
@@ -2110,7 +2145,7 @@ def press_up_arrow(self, selector="html", times=1, by=By.CSS_SELECTOR):
21102145
return
21112146
element = self.wait_for_element_present(selector)
21122147
self.__demo_mode_highlight_if_active(selector, by)
2113-
if not self.demo_mode:
2148+
if not self.demo_mode and not self.slow_mode:
21142149
self.__scroll_to_element(element, selector, by)
21152150
for i in range(int(times)):
21162151
try:
@@ -2131,7 +2166,7 @@ def press_down_arrow(self, selector="html", times=1, by=By.CSS_SELECTOR):
21312166
return
21322167
element = self.wait_for_element_present(selector)
21332168
self.__demo_mode_highlight_if_active(selector, by)
2134-
if not self.demo_mode:
2169+
if not self.demo_mode and not self.slow_mode:
21352170
self.__scroll_to_element(element, selector, by)
21362171
for i in range(int(times)):
21372172
try:
@@ -2152,7 +2187,7 @@ def press_left_arrow(self, selector="html", times=1, by=By.CSS_SELECTOR):
21522187
return
21532188
element = self.wait_for_element_present(selector)
21542189
self.__demo_mode_highlight_if_active(selector, by)
2155-
if not self.demo_mode:
2190+
if not self.demo_mode and not self.slow_mode:
21562191
self.__scroll_to_element(element, selector, by)
21572192
for i in range(int(times)):
21582193
try:
@@ -2173,7 +2208,7 @@ def press_right_arrow(self, selector="html", times=1, by=By.CSS_SELECTOR):
21732208
return
21742209
element = self.wait_for_element_present(selector)
21752210
self.__demo_mode_highlight_if_active(selector, by)
2176-
if not self.demo_mode:
2211+
if not self.demo_mode and not self.slow_mode:
21772212
self.__scroll_to_element(element, selector, by)
21782213
for i in range(int(times)):
21792214
try:
@@ -2201,7 +2236,7 @@ def scroll_to(self, selector, by=By.CSS_SELECTOR, timeout=None):
22012236
self.__scroll_to_element(element, selector, by)
22022237
except (StaleElementReferenceException, ENI_Exception):
22032238
self.wait_for_ready_state_complete()
2204-
time.sleep(0.05)
2239+
time.sleep(0.03)
22052240
element = self.wait_for_element_visible(
22062241
selector, by=by, timeout=timeout)
22072242
self.__scroll_to_element(element, selector, by)
@@ -2216,10 +2251,15 @@ def slow_scroll_to(self, selector, by=By.CSS_SELECTOR, timeout=None):
22162251
element = self.wait_for_element_visible(
22172252
selector, by=by, timeout=timeout)
22182253
try:
2219-
self.__slow_scroll_to_element(element)
2220-
except (StaleElementReferenceException, ENI_Exception):
2254+
scroll_distance = js_utils.get_scroll_distance_to_element(
2255+
self.driver, element)
2256+
if abs(scroll_distance) > SSMD:
2257+
self.__jquery_slow_scroll_to(selector, by)
2258+
else:
2259+
self.__slow_scroll_to_element(element)
2260+
except (StaleElementReferenceException, ENI_Exception, JS_Exc):
22212261
self.wait_for_ready_state_complete()
2222-
time.sleep(0.05)
2262+
time.sleep(0.03)
22232263
element = self.wait_for_element_visible(
22242264
selector, by=by, timeout=timeout)
22252265
self.__slow_scroll_to_element(element)
@@ -2266,7 +2306,7 @@ def js_click(self, selector, by=By.CSS_SELECTOR, all_matches=False):
22662306
selector, by=by, timeout=settings.SMALL_TIMEOUT)
22672307
if self.is_element_visible(selector, by=by):
22682308
self.__demo_mode_highlight_if_active(selector, by)
2269-
if not self.demo_mode:
2309+
if not self.demo_mode and not self.slow_mode:
22702310
self.__scroll_to_element(element, selector, by)
22712311
css_selector = self.convert_to_css_selector(selector, by=by)
22722312
css_selector = re.escape(css_selector)
@@ -2880,7 +2920,7 @@ def set_value(self, selector, text, by=By.CSS_SELECTOR, timeout=None):
28802920
orginal_selector = selector
28812921
css_selector = self.convert_to_css_selector(selector, by=by)
28822922
self.__demo_mode_highlight_if_active(orginal_selector, by)
2883-
if not self.demo_mode:
2923+
if not self.demo_mode and not self.slow_mode:
28842924
self.scroll_to(orginal_selector, by=by, timeout=timeout)
28852925
if type(text) is int or type(text) is float:
28862926
text = str(text)
@@ -5578,6 +5618,30 @@ def __js_click_all(self, selector, by=By.CSS_SELECTOR):
55785618
% css_selector)
55795619
self.execute_script(script)
55805620

5621+
def __jquery_slow_scroll_to(self, selector, by=By.CSS_SELECTOR):
5622+
selector, by = self.__recalculate_selector(selector, by)
5623+
element = self.wait_for_element_present(
5624+
selector, by=by, timeout=settings.SMALL_TIMEOUT)
5625+
dist = js_utils.get_scroll_distance_to_element(self.driver, element)
5626+
time_offset = 0
5627+
try:
5628+
if dist and abs(dist) > SSMD:
5629+
time_offset = int(float(abs(dist) - SSMD) / 12.5)
5630+
if time_offset > 950:
5631+
time_offset = 950
5632+
except Exception:
5633+
time_offset = 0
5634+
scroll_time_ms = 550 + time_offset
5635+
sleep_time = 0.625 + (float(time_offset) / 1000.0)
5636+
selector = self.convert_to_css_selector(selector, by=by)
5637+
selector = self.__make_css_match_first_element_only(selector)
5638+
scroll_script = (
5639+
"""jQuery([document.documentElement, document.body]).animate({
5640+
scrollTop: jQuery('%s').offset().top - 130}, %s);
5641+
""" % (selector, scroll_time_ms))
5642+
self.safe_execute_script(scroll_script)
5643+
self.sleep(sleep_time)
5644+
55815645
def __jquery_click(self, selector, by=By.CSS_SELECTOR):
55825646
""" Clicks an element using jQuery. Different from using pure JS. """
55835647
selector, by = self.__recalculate_selector(selector, by)
@@ -5762,17 +5826,24 @@ def __demo_mode_highlight_if_active(self, selector, by):
57625826
self.highlight(selector, by=by)
57635827
elif self.slow_mode:
57645828
# Just do the slow scroll part of the highlight() method
5829+
self.sleep(0.08)
57655830
selector, by = self.__recalculate_selector(selector, by)
57665831
element = self.wait_for_element_visible(
57675832
selector, by=by, timeout=settings.SMALL_TIMEOUT)
57685833
try:
5769-
self.__slow_scroll_to_element(element)
5834+
scroll_distance = js_utils.get_scroll_distance_to_element(
5835+
self.driver, element)
5836+
if abs(scroll_distance) > SSMD:
5837+
self.__jquery_slow_scroll_to(selector, by)
5838+
else:
5839+
self.__slow_scroll_to_element(element)
57705840
except (StaleElementReferenceException, ENI_Exception):
57715841
self.wait_for_ready_state_complete()
5772-
time.sleep(0.05)
5842+
time.sleep(0.03)
57735843
element = self.wait_for_element_visible(
57745844
selector, by=by, timeout=settings.SMALL_TIMEOUT)
57755845
self.__slow_scroll_to_element(element)
5846+
self.sleep(0.12)
57765847

57775848
def __scroll_to_element(self, element, selector=None, by=By.CSS_SELECTOR):
57785849
success = js_utils.scroll_to_element(self.driver, element)
@@ -5796,10 +5867,15 @@ def __highlight_with_assert_success(
57965867
# Don't highlight if can't convert to CSS_SELECTOR
57975868
return
57985869
try:
5799-
self.__slow_scroll_to_element(element)
5870+
scroll_distance = js_utils.get_scroll_distance_to_element(
5871+
self.driver, element)
5872+
if abs(scroll_distance) > SSMD:
5873+
self.__jquery_slow_scroll_to(selector, by)
5874+
else:
5875+
self.__slow_scroll_to_element(element)
58005876
except (StaleElementReferenceException, ENI_Exception):
58015877
self.wait_for_ready_state_complete()
5802-
time.sleep(0.05)
5878+
time.sleep(0.03)
58035879
element = self.wait_for_element_visible(
58045880
selector, by=by, timeout=settings.SMALL_TIMEOUT)
58055881
self.__slow_scroll_to_element(element)

0 commit comments

Comments
 (0)