Skip to content

Commit

Permalink
Merge pull request #2586 from seleniumbase/more-methods-and-uc-mode-u…
Browse files Browse the repository at this point in the history
…pdates

More methods and UC Mode updates
  • Loading branch information
mdmintz authored Mar 9, 2024
2 parents 5bd9f74 + aaae4b4 commit 90ebcab
Show file tree
Hide file tree
Showing 15 changed files with 136 additions and 13 deletions.
2 changes: 1 addition & 1 deletion examples/raw_bing_captcha.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,4 +9,4 @@
sb.activate_demo_mode() # See asserts as they happen
sb.assert_element("svg#success-icon")
sb.assert_text("Success!", "span#success-text")
sb.highlight("div#success", loops=10)
sb.highlight("div#success")
4 changes: 3 additions & 1 deletion examples/raw_cdp_logging.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,9 @@

driver = Driver(uc=True, log_cdp=True)
try:
driver.get("https://seleniumbase.io/apps/invisible_recaptcha")
driver.uc_open_with_reconnect("https://seleniumbase.io/apps/turnstile")
driver.uc_switch_to_frame("iframe")
driver.uc_click("span.mark")
driver.sleep(3)
pprint(driver.get_log("performance"))
finally:
Expand Down
7 changes: 4 additions & 3 deletions examples/raw_nopecha.py
Original file line number Diff line number Diff line change
@@ -1,17 +1,18 @@
from seleniumbase import SB

with SB(uc=True, test=True) as sb:
sb.driver.uc_open_with_reconnect("https://nopecha.com/demo/turnstile", 5)
sb.driver.uc_open_with_reconnect("https://nopecha.com/demo/turnstile", 4)
sb.driver.uc_switch_to_frame("#example-container5 iframe")
sb.driver.uc_click("span.mark")
sb.driver.uc_click("span.mark", reconnect_time=1)

if sb.is_element_visible("#example-container0 iframe"):
sb.switch_to_frame("#example-container0 iframe")
if not sb.is_element_visible("circle.success-circle"):
sb.driver.uc_click("span.mark")
sb.driver.uc_click("span.mark", reconnect_time=1)
sb.switch_to_frame("#example-container0 iframe")
sb.assert_element("circle.success-circle")
sb.switch_to_parent_frame()

sb.switch_to_frame("#example-container5 iframe")
sb.assert_element("svg#success-icon", timeout=3)
sb.switch_to_parent_frame()
Expand Down
17 changes: 17 additions & 0 deletions examples/raw_robot.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
from seleniumbase import SB

with SB(enable_3d_apis=True, test=True) as sb:
sb.open("threejs.org/examples/#webgl_animation_skinning_morph")
sb.switch_to_frame("iframe#viewer")
sb.set_text_content("#info p", "Hi, I'm Michael Mintz")
sb.add_css_style("#info p{zoom: 2.54}")
sb.sleep(0.8)
sb.click('button:contains("Wave")')
sb.highlight("#info p")
sb.select_option_by_text("select", "Idle")
sb.click('button:contains("ThumbsUp")')
sb.set_text_content("#info p", "I created SeleniumBase")
sb.highlight("#info p")
sb.sleep(0.8)
sb.click('button:contains("Jump")')
sb.sleep(1.5)
4 changes: 3 additions & 1 deletion examples/raw_uc_mode.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,5 +7,7 @@
if not sb.is_text_visible("Username", '[for="user_login"]'):
sb.driver.uc_open_with_reconnect(url, 4)
sb.assert_text("Username", '[for="user_login"]', timeout=3)
sb.highlight('label[for="user_login"]', loops=3)
sb.assert_element('label[for="user_login"]')
sb.highlight('button:contains("Sign in")')
sb.highlight('h1:contains("GitLab.com")')
sb.post_message("SeleniumBase wasn't detected", duration=4)
2 changes: 1 addition & 1 deletion examples/test_3d_apis.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
from seleniumbase import BaseCase
BaseCase.main(__name__, __file__)
BaseCase.main(__name__, __file__, "--enable-3d-apis")


class ThreeJSTests(BaseCase):
Expand Down
15 changes: 15 additions & 0 deletions help_docs/method_summary.md
Original file line number Diff line number Diff line change
Expand Up @@ -370,6 +370,8 @@ self.highlight_type(selector, text, by="css selector", loops=3, scroll=True, tim
# self.highlight_update_text(
# selector, text, by="css selector", loops=3, scroll=True, timeout=None)

self.highlight_if_visible(selector, by="css selector", loops=4, scroll=True)

self.highlight(selector, by="css selector", loops=4, scroll=True, timeout=None)

self.press_up_arrow(selector="html", times=1, by="css selector")
Expand Down Expand Up @@ -742,6 +744,7 @@ self.generate_traffic_chain(pages, loops=1)

self.get_element(selector, by="css selector", timeout=None)
# Duplicates:
# self.wait_for_selector(selector, by="css selector", timeout=None)
# self.locator(selector, by="css selector", timeout=None)
# self.wait_for_element_present(selector, by="css selector", timeout=None)

Expand Down Expand Up @@ -957,6 +960,12 @@ driver.assert_exact_text(text, selector)

driver.wait_for_element(selector)

driver.wait_for_element_visible(selector)

driver.wait_for_element_present(selector)

driver.wait_for_selector(selector)

driver.wait_for_text(text, selector)

driver.wait_for_exact_text(text, selector)
Expand Down Expand Up @@ -991,6 +1000,8 @@ driver.highlight(selector)

driver.highlight_click(selector)

driver.highlight_if_visible(selector)

driver.sleep(seconds)

driver.locator(selector)
Expand All @@ -1015,6 +1026,10 @@ driver.uc_open_with_reconnect(url, reconnect_time=None)

driver.reconnect(timeout)

driver.disconnect()

driver.connect()

driver.uc_click(
selector, by="css selector",
timeout=settings.SMALL_TIMEOUT, reconnect_time=None)
Expand Down
2 changes: 1 addition & 1 deletion requirements.txt
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ pluggy==1.2.0;python_version<"3.8"
pluggy==1.4.0;python_version>="3.8"
py==1.11.0
pytest==7.4.4;python_version<"3.8"
pytest==8.0.2;python_version>="3.8"
pytest==8.1.1;python_version>="3.8"
pytest-html==2.0.1
pytest-metadata==3.0.0;python_version<"3.8"
pytest-metadata==3.1.1;python_version>="3.8"
Expand Down
2 changes: 1 addition & 1 deletion seleniumbase/__version__.py
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
# seleniumbase package
__version__ = "4.24.4"
__version__ = "4.24.5"
17 changes: 14 additions & 3 deletions seleniumbase/core/browser_launcher.py
Original file line number Diff line number Diff line change
Expand Up @@ -169,6 +169,9 @@ def extend_driver(driver):
driver.assert_text = DM.assert_text
driver.assert_exact_text = DM.assert_exact_text
driver.wait_for_element = DM.wait_for_element
driver.wait_for_element_visible = DM.wait_for_element_visible
driver.wait_for_element_present = DM.wait_for_element_present
driver.wait_for_selector = DM.wait_for_selector
driver.wait_for_text = DM.wait_for_text
driver.wait_for_exact_text = DM.wait_for_exact_text
driver.wait_for_and_accept_alert = DM.wait_for_and_accept_alert
Expand All @@ -186,6 +189,7 @@ def extend_driver(driver):
driver.get_user_agent = DM.get_user_agent
driver.highlight = DM.highlight
driver.highlight_click = DM.highlight_click
driver.highlight_if_visible = DM.highlight_if_visible
driver.sleep = time.sleep
driver.get_attribute = DM.get_attribute
driver.get_page_source = DM.get_page_source
Expand Down Expand Up @@ -458,27 +462,34 @@ def uc_click(
by = "css selector"
except Exception:
pass
element = driver.wait_for_element(selector, by=by, timeout=timeout)
element = driver.wait_for_selector(selector, by=by, timeout=timeout)
if not element.tag_name == "span": # Element must be "visible"
element = driver.wait_for_element(selector, by=by, timeout=timeout)
try:
element.uc_click(
driver, selector, by=by, reconnect_time=reconnect_time
)
except ElementClickInterceptedException:
time.sleep(0.16)
driver.js_click(selector, by=by, timeout=timeout)
if not reconnect_time:
driver.reconnect(0.1)
else:
driver.reconnect(reconnect_time)


def uc_switch_to_frame(driver, frame, reconnect_time=None):
from selenium.webdriver.remote.webelement import WebElement
if isinstance(frame, WebElement):
if not reconnect_time:
driver.reconnect(0.15)
driver.reconnect(0.1)
else:
driver.reconnect(reconnect_time)
driver.switch_to.frame(frame)
else:
iframe = driver.locator(frame)
if not reconnect_time:
driver.reconnect(0.15)
driver.reconnect(0.1)
else:
driver.reconnect(reconnect_time)
driver.switch_to.frame(iframe)
Expand Down
19 changes: 19 additions & 0 deletions seleniumbase/core/sb_driver.py
Original file line number Diff line number Diff line change
Expand Up @@ -97,6 +97,15 @@ def assert_exact_text(self, *args, **kwargs):
def wait_for_element(self, *args, **kwargs):
return page_actions.wait_for_element(self.driver, *args, **kwargs)

def wait_for_element_visible(self, *args, **kwargs):
return page_actions.wait_for_element(self.driver, *args, **kwargs)

def wait_for_element_present(self, *args, **kwargs):
return page_actions.wait_for_selector(self.driver, *args, **kwargs)

def wait_for_selector(self, *args, **kwargs):
return page_actions.wait_for_selector(self.driver, *args, **kwargs)

def wait_for_text(self, *args, **kwargs):
return page_actions.wait_for_text(self.driver, *args, **kwargs)

Expand Down Expand Up @@ -147,6 +156,8 @@ def get_user_agent(self, *args, **kwargs):
return js_utils.get_user_agent(self.driver, *args, **kwargs)

def highlight(self, *args, **kwargs):
if "scroll" in kwargs:
kwargs.pop("scroll")
w_args = kwargs.copy()
if "loops" in w_args:
w_args.pop("loops")
Expand All @@ -161,8 +172,16 @@ def highlight_click(self, *args, **kwargs):
self.highlight(*args, **kwargs)
if "loops" in kwargs:
kwargs.pop("loops")
if "scroll" in kwargs:
kwargs.pop("scroll")
page_actions.click(self.driver, *args, **kwargs)

def highlight_if_visible(
self, selector, by="css selector", loops=4, scroll=True
):
if self.is_element_visible(selector, by=by):
self.highlight(selector, by=by, loops=loops, scroll=scroll)

def switch_to_frame(self, frame):
if isinstance(frame, WebElement):
self.driver.switch_to.frame(frame)
Expand Down
13 changes: 13 additions & 0 deletions seleniumbase/fixtures/base_case.py
Original file line number Diff line number Diff line change
Expand Up @@ -5601,6 +5601,14 @@ def highlight_type(
self.__highlight(selector, by=by, loops=loops, scroll=scroll)
self.update_text(selector, text, by=by)

def highlight_if_visible(
self, selector, by="css selector", loops=4, scroll=True,
):
"""Highlights the element if the element is visible."""
self.__check_scope()
if self.is_element_visible(selector, by=by):
self.__highlight(selector, by=by, loops=loops, scroll=scroll)

def __highlight(
self, selector, by="css selector", loops=None, scroll=True
):
Expand Down Expand Up @@ -9089,6 +9097,11 @@ def locator(self, selector, by="css selector", timeout=None):
The element does not need be visible (it may be hidden)."""
return self.wait_for_element_present(selector, by=by, timeout=timeout)

def wait_for_selector(self, selector, by="css selector", timeout=None):
"""Same as wait_for_element_present() - returns the element.
The element does not need be visible (it may be hidden)."""
return self.wait_for_element_present(selector, by=by, timeout=timeout)

def wait_for_query_selector(
self, selector, by="css selector", timeout=None
):
Expand Down
21 changes: 21 additions & 0 deletions seleniumbase/fixtures/page_actions.py
Original file line number Diff line number Diff line change
Expand Up @@ -1752,6 +1752,27 @@ def wait_for_element(
)


def wait_for_selector(
driver,
selector,
by="css selector",
timeout=settings.LARGE_TIMEOUT,
):
original_selector = None
if page_utils.is_valid_by(by):
original_selector = selector
elif page_utils.is_valid_by(selector):
original_selector = by
selector, by = page_utils.recalculate_selector(selector, by)
return wait_for_element_present(
driver=driver,
selector=selector,
by=by,
timeout=timeout,
original_selector=original_selector,
)


def wait_for_text(
driver,
text,
Expand Down
22 changes: 22 additions & 0 deletions seleniumbase/undetected/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -442,6 +442,28 @@ def reconnect(self, timeout=0.1):
except Exception:
pass

def disconnect(self):
"""Stops the chromedriver service that runs in the background.
To use driver methods again, you MUST call driver.connect()"""
if hasattr(self, "service"):
try:
self.service.stop()
except Exception:
pass

def connect(self):
"""Starts the chromedriver service that runs in the background
and recreates the session."""
if hasattr(self, "service"):
try:
self.service.start()
except Exception:
pass
try:
self.start_session()
except Exception:
pass

def start_session(self, capabilities=None):
if not capabilities:
capabilities = self.options.to_capabilities()
Expand Down
2 changes: 1 addition & 1 deletion setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -187,7 +187,7 @@
'pluggy==1.4.0;python_version>="3.8"',
"py==1.11.0",
'pytest==7.4.4;python_version<"3.8"',
'pytest==8.0.2;python_version>="3.8"',
'pytest==8.1.1;python_version>="3.8"',
"pytest-html==2.0.1", # Newer ones had issues
'pytest-metadata==3.0.0;python_version<"3.8"',
'pytest-metadata==3.1.1;python_version>="3.8"',
Expand Down

0 comments on commit 90ebcab

Please sign in to comment.