Skip to content

Commit ef39342

Browse files
authored
Merge pull request #1503 from seleniumbase/fix-issue-with-hovering-over-elements
Fix two separate issues regarding hovering and Safari compatibility
2 parents 593b135 + d8830b1 commit ef39342

File tree

5 files changed

+92
-65
lines changed

5 files changed

+92
-65
lines changed

examples/test_apple_site.py

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,10 @@ def test_apple_developer_site_webdriver_instructions(self):
2323
self.assert_element("nav.documentation-nav")
2424
self.assert_text(title, "h1")
2525
self.assert_text("Enable WebDriver and run a test.", "div.abstract")
26-
self.highlight("div.content h2")
26+
if self.demo_mode:
27+
self.highlight("div.content h2")
28+
else:
29+
self.assert_element("div.content h2")
2730
h3 = "div.content h3:nth-of-type(%s)"
2831
self.assert_text("Make Sure You Have Safari’s WebDriver", h3 % "1")
2932
self.assert_text("Get the Correct Selenium Library", h3 % "2")

mkdocs_build/requirements.txt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ nltk==3.7
2424
tornado==6.2
2525
watchdog==2.1.9
2626
mkdocs==1.3.1
27-
mkdocs-material==8.4.2
27+
mkdocs-material==8.4.3
2828
mkdocs-exclude-search==0.6.4
2929
mkdocs-simple-hooks==0.1.5
3030
mkdocs-material-extensions==1.0.3

seleniumbase/__version__.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,2 @@
11
# seleniumbase package
2-
__version__ = "4.3.5"
2+
__version__ = "4.3.6"

seleniumbase/fixtures/base_case.py

Lines changed: 65 additions & 53 deletions
Original file line numberDiff line numberDiff line change
@@ -291,20 +291,19 @@ def click(
291291
pre_action_url = self.driver.current_url
292292
pre_window_count = len(self.driver.window_handles)
293293
try:
294-
if self.browser == "ie" and by == By.LINK_TEXT:
295-
# An issue with clicking Link Text on IE means using jquery
294+
if (
295+
by == By.LINK_TEXT
296+
and (
297+
self.browser == "ie" or self.browser == "safari"
298+
)
299+
):
296300
self.__jquery_click(selector, by=by)
297-
elif self.browser == "safari":
298-
if by == By.LINK_TEXT:
299-
self.__jquery_click(selector, by=by)
300-
else:
301-
self.__js_click(selector, by=by)
302301
else:
303302
href = None
304303
new_tab = False
305304
onclick = None
306305
try:
307-
if self.headless and element.tag_name == "a":
306+
if self.headless and element.tag_name.lower() == "a":
308307
# Handle a special case of opening a new tab (headless)
309308
href = element.get_attribute("href").strip()
310309
onclick = element.get_attribute("onclick")
@@ -343,11 +342,8 @@ def click(
343342
self.__scroll_to_element(element, selector, by)
344343
except Exception:
345344
pass
346-
if self.browser == "safari":
347-
if by == By.LINK_TEXT:
348-
self.__jquery_click(selector, by=by)
349-
else:
350-
self.__js_click(selector, by=by)
345+
if self.browser == "safari" and by == By.LINK_TEXT:
346+
self.__jquery_click(selector, by=by)
351347
else:
352348
element.click()
353349
except ENI_Exception:
@@ -364,7 +360,7 @@ def click(
364360
new_tab = False
365361
onclick = None
366362
try:
367-
if element.tag_name == "a":
363+
if element.tag_name.lower() == "a":
368364
# Handle a special case of opening a new tab (non-headless)
369365
href = element.get_attribute("href").strip()
370366
onclick = element.get_attribute("onclick")
@@ -1449,10 +1445,11 @@ def get_text(self, selector, by="css selector", timeout=None):
14491445
try:
14501446
element_text = element.text
14511447
if self.browser == "safari":
1452-
element_text = element.get_attribute("innerText")
1453-
if element.tag_name == "input":
1454-
element_text = element.get_property("value")
1455-
if element.tag_name == "textarea":
1448+
if element.tag_name.lower() in ["input", "textarea"]:
1449+
element_text = element.get_attribute("value")
1450+
else:
1451+
element_text = element.get_attribute("innerText")
1452+
elif element.tag_name.lower() in ["input", "textarea"]:
14561453
element_text = element.get_property("value")
14571454
except (StaleElementReferenceException, ENI_Exception):
14581455
self.wait_for_ready_state_complete()
@@ -1462,8 +1459,11 @@ def get_text(self, selector, by="css selector", timeout=None):
14621459
)
14631460
element_text = element.text
14641461
if self.browser == "safari":
1465-
element_text = element.get_attribute("innerText")
1466-
if element.tag_name == "input":
1462+
if element.tag_name.lower() in ["input", "textarea"]:
1463+
element_text = element.get_attribute("value")
1464+
else:
1465+
element_text = element.get_attribute("innerText")
1466+
elif element.tag_name.lower() in ["input", "textarea"]:
14671467
element_text = element.get_property("value")
14681468
return element_text
14691469

@@ -2128,21 +2128,18 @@ def hover_on_element(self, selector, by="css selector"):
21282128
original_selector = selector
21292129
original_by = by
21302130
selector, by = self.__recalculate_selector(selector, by)
2131-
if page_utils.is_xpath_selector(selector):
2132-
selector = self.convert_to_css_selector(selector, By.XPATH)
2133-
by = By.CSS_SELECTOR
21342131
self.wait_for_element_visible(
21352132
original_selector, by=original_by, timeout=settings.SMALL_TIMEOUT
21362133
)
21372134
self.__demo_mode_highlight_if_active(original_selector, original_by)
21382135
self.scroll_to(selector, by=by)
21392136
time.sleep(0.05) # Settle down from scrolling before hovering
21402137
if self.browser != "chrome":
2141-
return page_actions.hover_on_element(self.driver, selector)
2138+
return page_actions.hover_on_element(self.driver, selector, by)
21422139
# Using Chrome
21432140
# (Pure hover actions won't work on early chromedriver versions)
21442141
try:
2145-
return page_actions.hover_on_element(self.driver, selector)
2142+
return page_actions.hover_on_element(self.driver, selector, by)
21462143
except WebDriverException as e:
21472144
driver_capabilities = self.driver.capabilities
21482145
if "version" in driver_capabilities:
@@ -2191,8 +2188,6 @@ def hover_and_click(
21912188
hover_selector, hover_by = self.__recalculate_selector(
21922189
hover_selector, hover_by
21932190
)
2194-
hover_selector = self.convert_to_css_selector(hover_selector, hover_by)
2195-
hover_by = By.CSS_SELECTOR
21962191
original_click_selector = click_selector
21972192
click_selector, click_by = self.__recalculate_selector(
21982193
click_selector, click_by
@@ -2224,9 +2219,6 @@ def hover_and_click(
22242219
if self.mobile_emulator:
22252220
# On mobile, click to hover the element
22262221
dropdown_element.click()
2227-
elif self.browser == "safari":
2228-
# Use the workaround for hover-clicking on Safari
2229-
raise Exception("This Exception will be caught.")
22302222
else:
22312223
page_actions.hover_element(self.driver, dropdown_element)
22322224
except Exception:
@@ -2269,6 +2261,12 @@ def hover_and_click(
22692261
)
22702262
):
22712263
self.__switch_to_newest_window_if_not_blank()
2264+
elif self.browser == "safari":
2265+
# Release the hover by hovering elsewhere
2266+
try:
2267+
page_actions.hover_on_element(self.driver, "body")
2268+
except Exception:
2269+
pass
22722270
if self.demo_mode:
22732271
if self.driver.current_url != pre_action_url:
22742272
self.__demo_mode_pause_if_active()
@@ -2630,10 +2628,11 @@ def get_select_options(
26302628
raise Exception("The attribute must be in %s" % allowed_attributes)
26312629
selector, by = self.__recalculate_selector(selector, by)
26322630
element = self.wait_for_element(selector, by=by, timeout=timeout)
2633-
if element.tag_name != "select":
2631+
if element.tag_name.lower() != "select":
26342632
raise Exception(
26352633
'Element tag_name for get_select_options(selector) must be a '
2636-
'"select"! Actual tag_name found was: "%s"' % element.tag_name
2634+
'"select"! Actual tag_name found was: "%s"'
2635+
% element.tag_name.lower()
26372636
)
26382637
if by != "css selector":
26392638
selector = self.convert_to_css_selector(selector, by=by)
@@ -2717,9 +2716,13 @@ def load_html_string(self, html_string, new_page=True):
27172716
html_string = html_string.replace("\\ ", " ")
27182717

27192718
if new_page:
2720-
self.open("data:text/html,")
2719+
self.open("data:text/html,<head></head><body></body>")
27212720
inner_head = """document.getElementsByTagName("head")[0].innerHTML"""
27222721
inner_body = """document.getElementsByTagName("body")[0].innerHTML"""
2722+
try:
2723+
self.wait_for_element_present("body", timeout=1)
2724+
except Exception:
2725+
pass
27232726
if not found_body:
27242727
self.execute_script('''%s = \"%s\"''' % (inner_body, html_string))
27252728
elif found_body and not found_head:
@@ -5102,13 +5105,16 @@ def slow_scroll_to(self, selector, by="css selector", timeout=None):
51025105
original_selector, by=original_by, timeout=timeout
51035106
)
51045107
try:
5105-
scroll_distance = js_utils.get_scroll_distance_to_element(
5106-
self.driver, element
5107-
)
5108-
if abs(scroll_distance) > constants.Values.SSMD:
5109-
self.__jquery_slow_scroll_to(selector, by)
5108+
if self.browser != "safari":
5109+
scroll_distance = js_utils.get_scroll_distance_to_element(
5110+
self.driver, element
5111+
)
5112+
if abs(scroll_distance) > constants.Values.SSMD:
5113+
self.__jquery_slow_scroll_to(selector, by)
5114+
else:
5115+
self.__slow_scroll_to_element(element)
51105116
else:
5111-
self.__slow_scroll_to_element(element)
5117+
self.__jquery_slow_scroll_to(selector, by)
51125118
except Exception:
51135119
self.wait_for_ready_state_complete()
51145120
time.sleep(0.12)
@@ -6721,7 +6727,7 @@ def set_text(self, selector, text, by="css selector", timeout=None):
67216727
element = page_actions.wait_for_element_present(
67226728
self.driver, selector, by, timeout
67236729
)
6724-
if element.tag_name == "input" or element.tag_name == "textarea":
6730+
if element.tag_name.lower() in ["input", "textarea"]:
67256731
self.js_update_text(selector, text, by=by, timeout=timeout)
67266732
else:
67276733
self.set_text_content(selector, text, by=by, timeout=timeout)
@@ -6741,7 +6747,7 @@ def set_text_content(
67416747
element = page_actions.wait_for_element_present(
67426748
self.driver, selector, by, timeout
67436749
)
6744-
if element.tag_name == "input" or element.tag_name == "textarea":
6750+
if element.tag_name.lower() in ["input", "textarea"]:
67456751
self.js_update_text(selector, text, by=by, timeout=timeout)
67466752
return
67476753
orginal_selector = selector
@@ -12255,13 +12261,16 @@ def __demo_mode_highlight_if_active(self, selector, by):
1225512261
selector, by=by, timeout=settings.SMALL_TIMEOUT
1225612262
)
1225712263
try:
12258-
scroll_distance = js_utils.get_scroll_distance_to_element(
12259-
self.driver, element
12260-
)
12261-
if abs(scroll_distance) > constants.Values.SSMD:
12262-
self.__jquery_slow_scroll_to(selector, by)
12264+
if self.browser != "safari":
12265+
scroll_distance = js_utils.get_scroll_distance_to_element(
12266+
self.driver, element
12267+
)
12268+
if abs(scroll_distance) > constants.Values.SSMD:
12269+
self.__jquery_slow_scroll_to(selector, by)
12270+
else:
12271+
self.__slow_scroll_to_element(element)
1226312272
else:
12264-
self.__slow_scroll_to_element(element)
12273+
self.__jquery_slow_scroll_to(selector, by)
1226512274
except (StaleElementReferenceException, ENI_Exception):
1226612275
self.wait_for_ready_state_complete()
1226712276
time.sleep(0.12)
@@ -12295,13 +12304,16 @@ def __highlight_with_assert_success(
1229512304
selector, by=by, timeout=settings.SMALL_TIMEOUT
1229612305
)
1229712306
try:
12298-
scroll_distance = js_utils.get_scroll_distance_to_element(
12299-
self.driver, element
12300-
)
12301-
if abs(scroll_distance) > constants.Values.SSMD:
12302-
self.__jquery_slow_scroll_to(selector, by)
12307+
if self.browser != "safari":
12308+
scroll_distance = js_utils.get_scroll_distance_to_element(
12309+
self.driver, element
12310+
)
12311+
if abs(scroll_distance) > constants.Values.SSMD:
12312+
self.__jquery_slow_scroll_to(selector, by)
12313+
else:
12314+
self.__slow_scroll_to_element(element)
1230312315
else:
12304-
self.__slow_scroll_to_element(element)
12316+
self.__jquery_slow_scroll_to(selector, by)
1230512317
except Exception:
1230612318
self.wait_for_ready_state_complete()
1230712319
time.sleep(0.12)

seleniumbase/fixtures/page_actions.py

Lines changed: 21 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -127,10 +127,13 @@ def is_text_visible(driver, text, selector, by="css selector", browser=None):
127127
try:
128128
element = driver.find_element(by=by, value=selector)
129129
element_text = element.text
130-
if element.tag_name == "input" or element.tag_name == "textarea":
130+
if browser == "safari":
131+
if element.tag_name.lower() in ["input", "textarea"]:
132+
element_text = element.get_attribute("value")
133+
else:
134+
element_text = element.get_attribute("innerText")
135+
elif element.tag_name.lower() in ["input", "textarea"]:
131136
element_text = element.get_property("value")
132-
elif browser == "safari":
133-
element_text = element.get_attribute("innerText")
134137
return element.is_displayed() and text in element_text
135138
except Exception:
136139
return False
@@ -477,7 +480,10 @@ def wait_for_text_visible(
477480
try:
478481
element = driver.find_element(by=by, value=selector)
479482
is_present = True
480-
if element.tag_name == "input" or element.tag_name == "textarea":
483+
if (
484+
element.tag_name.lower() in ["input", "textarea"]
485+
and browser != "safari"
486+
):
481487
if (
482488
element.is_displayed()
483489
and text in element.get_property("value")
@@ -489,14 +495,17 @@ def wait_for_text_visible(
489495
element = None
490496
raise Exception()
491497
elif browser == "safari":
498+
text_attr = "innerText"
499+
if element.tag_name.lower() in ["input", "textarea"]:
500+
text_attr = "value"
492501
if (
493502
element.is_displayed()
494-
and text in element.get_attribute("innerText")
503+
and text in element.get_attribute(text_attr)
495504
):
496505
return element
497506
else:
498507
if element.is_displayed():
499-
full_text = element.get_attribute("innerText")
508+
full_text = element.get_attribute(text_attr)
500509
full_text = full_text.strip()
501510
element = None
502511
raise Exception()
@@ -582,7 +591,7 @@ def wait_for_exact_text_visible(
582591
try:
583592
element = driver.find_element(by=by, value=selector)
584593
is_present = True
585-
if element.tag_name == "input" or element.tag_name == "textarea":
594+
if element.tag_name.lower() in ["input", "textarea"]:
586595
if (
587596
element.is_displayed()
588597
and text.strip() == element.get_property("value").strip()
@@ -594,13 +603,16 @@ def wait_for_exact_text_visible(
594603
element = None
595604
raise Exception()
596605
elif browser == "safari":
606+
text_attr = "innerText"
607+
if element.tag_name.lower() in ["input", "textarea"]:
608+
text_attr = "value"
597609
if element.is_displayed() and (
598-
text.strip() == element.get_attribute("innerText").strip()
610+
text.strip() == element.get_attribute(text_attr).strip()
599611
):
600612
return element
601613
else:
602614
if element.is_displayed():
603-
actual_text = element.get_attribute("innerText")
615+
actual_text = element.get_attribute(text_attr)
604616
actual_text = actual_text.strip()
605617
element = None
606618
raise Exception()

0 commit comments

Comments
 (0)