diff --git a/examples/cdp_mode/ReadMe.md b/examples/cdp_mode/ReadMe.md
index c7031b8e4f5..95e3aa6a6ea 100644
--- a/examples/cdp_mode/ReadMe.md
+++ b/examples/cdp_mode/ReadMe.md
@@ -345,8 +345,6 @@ with SB(uc=True, test=True, locale_code="en", ad_block=True) as sb:
### 🐙 CDP Mode API / Methods
-(Some method args have been left out for simplicity. Eg: timeout
)
-
```python
sb.cdp.get(url)
sb.cdp.open(url)
@@ -354,16 +352,16 @@ sb.cdp.reload(ignore_cache=True, script_to_evaluate_on_load=None)
sb.cdp.refresh()
sb.cdp.get_event_loop()
sb.cdp.add_handler(event, handler)
-sb.cdp.find_element(selector)
-sb.cdp.find(selector)
-sb.cdp.locator(selector)
-sb.cdp.find_element_by_text(text, tag_name=None)
-sb.cdp.find_all(selector)
+sb.cdp.find_element(selector, best_match=False, timeout=None)
+sb.cdp.find(selector, best_match=False, timeout=None)
+sb.cdp.locator(selector, best_match=False, timeout=None)
+sb.cdp.find_element_by_text(text, tag_name=None, timeout=None)
+sb.cdp.find_all(selector, timeout=None)
sb.cdp.find_elements_by_text(text, tag_name=None)
-sb.cdp.select(selector)
-sb.cdp.select_all(selector)
-sb.cdp.find_elements(selector)
-sb.cdp.find_visible_elements(selector)
+sb.cdp.select(selector, timeout=None)
+sb.cdp.select_all(selector, timeout=None)
+sb.cdp.find_elements(selector, timeout=None)
+sb.cdp.find_visible_elements(selector, timeout=None)
sb.cdp.click_nth_element(selector, number)
sb.cdp.click_nth_visible_element(selector, number)
sb.cdp.click_link(link_text)
@@ -375,17 +373,17 @@ sb.cdp.get_all_cookies(*args, **kwargs)
sb.cdp.set_all_cookies(*args, **kwargs)
sb.cdp.save_cookies(*args, **kwargs)
sb.cdp.load_cookies(*args, **kwargs)
-sb.cdp.clear_cookies(*args, **kwargs)
+sb.cdp.clear_cookies()
sb.cdp.sleep(seconds)
sb.cdp.bring_active_window_to_front()
sb.cdp.bring_to_front()
sb.cdp.get_active_element()
sb.cdp.get_active_element_css()
-sb.cdp.click(selector)
+sb.cdp.click(selector, timeout=None)
sb.cdp.click_active_element()
sb.cdp.click_if_visible(selector)
sb.cdp.click_visible_elements(selector, limit=0)
-sb.cdp.mouse_click(selector)
+sb.cdp.mouse_click(selector, timeout=None)
sb.cdp.nested_click(parent_selector, selector)
sb.cdp.get_nested_element(parent_selector, selector)
sb.cdp.select_option_by_text(dropdown_selector, option)
@@ -396,10 +394,10 @@ sb.cdp.highlight_overlay(selector)
sb.cdp.remove_element(selector)
sb.cdp.remove_from_dom(selector)
sb.cdp.remove_elements(selector)
-sb.cdp.send_keys(selector, text)
-sb.cdp.press_keys(selector, text)
-sb.cdp.type(selector, text)
-sb.cdp.set_value(selector, text)
+sb.cdp.send_keys(selector, text, timeout=None)
+sb.cdp.press_keys(selector, text, timeout=None)
+sb.cdp.type(selector, text, timeout=None)
+sb.cdp.set_value(selector, text, timeout=None)
sb.cdp.evaluate(expression)
sb.cdp.js_dumps(obj_name)
sb.cdp.maximize()
@@ -420,11 +418,11 @@ sb.cdp.get_screen_rect()
sb.cdp.get_window_rect()
sb.cdp.get_window_size()
sb.cdp.get_window_position()
-sb.cdp.get_element_rect(selector)
-sb.cdp.get_element_size(selector)
-sb.cdp.get_element_position(selector)
-sb.cdp.get_gui_element_rect(selector)
-sb.cdp.get_gui_element_center(selector)
+sb.cdp.get_element_rect(selector, timeout=None)
+sb.cdp.get_element_size(selector, timeout=None)
+sb.cdp.get_element_position(selector, timeout=None)
+sb.cdp.get_gui_element_rect(selector, timeout=None)
+sb.cdp.get_gui_element_center(selector, timeout=None)
sb.cdp.get_document()
sb.cdp.get_flattened_document()
sb.cdp.get_element_attributes(selector)
@@ -452,19 +450,19 @@ sb.cdp.uncheck_if_checked(selector)
sb.cdp.unselect_if_selected(selector)
sb.cdp.is_element_present(selector)
sb.cdp.is_element_visible(selector)
-sb.cdp.wait_for_element_visible(selector)
-sb.cdp.assert_element(selector)
-sb.cdp.assert_element_visible(selector)
-sb.cdp.assert_element_present(selector)
-sb.cdp.assert_element_absent(selector)
-sb.cdp.assert_element_not_visible(selector)
+sb.cdp.wait_for_element_visible(selector, timeout=None)
+sb.cdp.assert_element(selector, timeout=None)
+sb.cdp.assert_element_visible(selector, timeout=None)
+sb.cdp.assert_element_present(selector, timeout=None)
+sb.cdp.assert_element_absent(selector, timeout=None)
+sb.cdp.assert_element_not_visible(selector, timeout=None)
sb.cdp.assert_element_attribute(selector, attribute, value=None)
sb.cdp.assert_title(title)
sb.cdp.assert_title_contains(substring)
sb.cdp.assert_url(url)
sb.cdp.assert_url_contains(substring)
-sb.cdp.assert_text(text, selector="html")
-sb.cdp.assert_exact_text(text, selector="html")
+sb.cdp.assert_text(text, selector="html", timeout=None)
+sb.cdp.assert_exact_text(text, selector="html", timeout=None)
sb.cdp.assert_true()
sb.cdp.assert_false()
sb.cdp.assert_equal(first, second)
diff --git a/examples/cdp_mode/raw_gettyimages.py b/examples/cdp_mode/raw_gettyimages.py
new file mode 100644
index 00000000000..d2cf0a4f732
--- /dev/null
+++ b/examples/cdp_mode/raw_gettyimages.py
@@ -0,0 +1,11 @@
+from seleniumbase import SB
+
+with SB(uc=True, test=True, locale_code="en", pls="none") as sb:
+ sb.activate_cdp_mode("https://www.gettyimages.com/")
+ sb.cdp.click('label:contains("Editorial")')
+ sb.cdp.press_keys("form input", "comic con 2024 sci fi panel\n")
+ sb.sleep(3)
+ items = sb.cdp.find_elements("figure picture img")
+ for item in items:
+ item.flash(color="44CC88")
+ sb.sleep(0.08)
diff --git a/examples/cdp_mode/raw_kohls.py b/examples/cdp_mode/raw_kohls.py
new file mode 100644
index 00000000000..a29fa7ca374
--- /dev/null
+++ b/examples/cdp_mode/raw_kohls.py
@@ -0,0 +1,25 @@
+from seleniumbase import SB
+
+with SB(uc=True, test=True, locale_code="en", ad_block=True) as sb:
+ url = "https://www.kohls.com/"
+ sb.activate_cdp_mode(url)
+ sb.sleep(2.5)
+ search = "Mickey Mouse 100 friends teal pillow"
+ required_text = "Mickey"
+ sb.cdp.press_keys('input[name="search"]', search + "\n")
+ sb.sleep(5)
+ for item in sb.cdp.find_elements("div.products-container-right"):
+ if "Sponsored" in item.text:
+ item.remove_from_dom()
+ sb.cdp.remove_elements("#tce-sticky-wrapper")
+ sb.cdp.remove_elements("li.sponsored-product")
+ sb.cdp.remove_elements("#tce-dec-ces-3-banner")
+ print('*** Kohls Search for "%s":' % search)
+ for item in sb.cdp.find_elements("ul.products a img"):
+ if item:
+ item.flash(color="44CC88")
+ title = item.get_attribute("title")
+ if title and required_text in title:
+ print("* " + title)
+ sb.sleep(0.1)
+ sb.sleep(1)
diff --git a/examples/cdp_mode/raw_req_mod.py b/examples/cdp_mode/raw_req_mod.py
index 560b14b6914..eaa5f8d142f 100644
--- a/examples/cdp_mode/raw_req_mod.py
+++ b/examples/cdp_mode/raw_req_mod.py
@@ -5,14 +5,13 @@
async def request_paused_handler(event, tab):
r = event.request
+ rid = event.request_id
is_image = ".png" in r.url or ".jpg" in r.url or ".gif" in r.url
if not is_image: # Let the data through
- tab.feed_cdp(mycdp.fetch.continue_request(request_id=event.request_id))
- else: # Modify the data (change the image)
- tab.feed_cdp(mycdp.fetch.continue_request(
- request_id=event.request_id,
- url="https://seleniumbase.io/other/with_frakes.jpg"
- ))
+ tab.feed_cdp(mycdp.fetch.continue_request(request_id=rid))
+ else: # Modify the data (Change the image URL)
+ new_url = "https://seleniumbase.io/other/with_frakes.jpg"
+ tab.feed_cdp(mycdp.fetch.continue_request(request_id=rid, url=new_url))
with SB(uc=True, test=True, locale_code="en", pls="none") as sb:
diff --git a/examples/cdp_mode/raw_theaters.py b/examples/cdp_mode/raw_theaters.py
new file mode 100644
index 00000000000..f67b082b268
--- /dev/null
+++ b/examples/cdp_mode/raw_theaters.py
@@ -0,0 +1,16 @@
+"""Simple web-scraping example in CDP Mode"""
+from seleniumbase import SB
+
+with SB(uc=True, test=True, locale_code="en", ad_block=True) as sb:
+ url = "https://architectureofcities.com/roman-theaters"
+ sb.activate_cdp_mode(url)
+ sb.cdp.click_if_visible("#cn-close-notice")
+ sb.sleep(2)
+ print("*** " + sb.cdp.get_text("h1") + " ***")
+ for item in sb.cdp.find_elements("h3"):
+ if item.text and "." in item.text:
+ item.flash(color="44CC88")
+ sb.cdp.scroll_down(34)
+ print("* " + item.text.replace(" ", " "))
+ sb.sleep(0.15)
+ sb.sleep(1)
diff --git a/examples/cdp_mode/raw_tiktok.py b/examples/cdp_mode/raw_tiktok.py
index 391a0e2a43f..98952a3c977 100644
--- a/examples/cdp_mode/raw_tiktok.py
+++ b/examples/cdp_mode/raw_tiktok.py
@@ -7,6 +7,6 @@
sb.cdp.click_if_visible('button:contains("Refresh")')
sb.sleep(1.5)
print(sb.cdp.get_text('h2[data-e2e="user-bio"]'))
- for i in range(50):
+ for i in range(54):
sb.cdp.scroll_down(12)
sb.sleep(1)
diff --git a/help_docs/method_summary.md b/help_docs/method_summary.md
index 6a27bde9f43..ccce5ae7562 100644
--- a/help_docs/method_summary.md
+++ b/help_docs/method_summary.md
@@ -13,275 +13,177 @@ For backwards compatibility, older versions of method names have remained to kee
self.open(url)
# Duplicates: self.open_url(url), self.visit(url), visit_url(url),
# self.goto(url), self.go_to(url)
-
self.get(url)
# If the url parameter is a URL: Perform self.open(url)
# Otherwise: return self.get_element(URL_AS_A_SELECTOR)
-
self.click(selector, by="css selector", timeout=None, delay=0, scroll=True)
-
self.slow_click(selector, by="css selector", timeout=None)
-
self.double_click(selector, by="css selector", timeout=None)
-
self.context_click(selector, by="css selector", timeout=None)
# Duplicates:
# self.right_click(selector, by="css selector", timeout=None)
-
self.click_chain(selectors_list, by="css selector", timeout=None, spacing=0)
-
self.type(selector, text, by="css selector", timeout=None)
# Duplicates:
# self.update_text(selector, text, by="css selector", timeout=None)
# self.input(selector, text, by="css selector", timeout=None)
# self.fill(selector, text, by="css selector", timeout=None)
# self.write(selector, text, by="css selector", timeout=None)
-
self.send_keys(selector, text, by="css selector", timeout=None)
# Duplicates:
# self.add_text(selector, text, by="css selector", timeout=None)
-
self.press_keys(selector, text, by="css selector", timeout=None)
-
self.submit(selector, by="css selector")
-
self.clear(selector, by="css selector", timeout=None)
-
self.focus(selector, by="css selector", timeout=None)
-
self.refresh()
-# Duplicates: self.refresh_page(), self.reload_page(), self.reload()
-
+# Duplicates:
+# self.refresh_page(), self.reload_page(), self.reload()
self.get_current_url()
-
self.get_origin()
-
self.get_page_source()
-
self.get_title()
-# Duplicates: self.get_page_title()
-
+# Duplicates:
+# self.get_page_title()
self.get_user_agent()
-
self.get_locale_code()
-
self.go_back()
-
self.go_forward()
-
self.open_start_page()
-
self.open_if_not_url(url)
-
self.is_element_present(selector, by="css selector")
-
self.is_element_visible(selector, by="css selector")
-
self.is_element_clickable(selector, by="css selector")
-
self.is_element_enabled(selector, by="css selector")
-
self.is_text_visible(text, selector="html", by="css selector")
-
self.is_exact_text_visible(text, selector="html", by="css selector")
-
self.is_non_empty_text_visible(selector="html", by="css selector")
-
self.is_attribute_present(selector, attribute, value=None, by="css selector")
-
self.is_link_text_visible(link_text)
-
self.is_partial_link_text_visible(partial_link_text)
-
self.is_link_text_present(link_text)
-
self.is_partial_link_text_present(link_text)
-
self.get_link_attribute(link_text, attribute, hard_fail=True)
# Duplicates:
# self.get_link_text_attribute(link_text, attribute, hard_fail=True)
-
self.get_partial_link_text_attribute(link_text, attribute, hard_fail=True)
-
self.click_link(link_text, timeout=None)
# Duplicates:
# self.click_link_text(link_text, timeout=None)
-
self.click_partial_link(partial_link_text, timeout=None)
# Duplicates:
# self.click_partial_link_text(partial_link_text, timeout=None)
-
self.get_text(selector="html", by="css selector", timeout=None)
-
self.get_attribute(selector, attribute, by="css selector", timeout=None, hard_fail=True)
-
self.set_attribute(selector, attribute, value, by="css selector", timeout=None, scroll=False)
-
self.set_attributes(selector, attribute, value, by="css selector")
# Duplicates:
# self.set_attribute_all(selector, attribute, value, by="css selector")
-
self.remove_attribute(selector, attribute, by="css selector", timeout=None)
-
self.remove_attributes(selector, attribute, by="css selector")
-
self.internalize_links()
-
self.get_property(selector, property, by="css selector", timeout=None)
-
self.get_text_content(selector="html", by="css selector", timeout=None)
-
self.get_property_value(selector, property, by="css selector", timeout=None)
-
self.get_image_url(selector, by="css selector", timeout=None)
-
self.find_elements(selector, by="css selector", limit=0)
# Duplicates:
# self.select_all(selector, by="css selector", limit=0)
-
self.find_visible_elements(selector, by="css selector", limit=0)
-
self.click_visible_elements(selector, by="css selector", limit=0, timeout=None)
-
self.click_nth_visible_element(selector, number, by="css selector", timeout=None)
-
self.click_if_visible(selector, by="css selector", timeout=0)
-
self.click_active_element()
-
self.click_with_offset(
selector, x, y, by="css selector", mark=None, timeout=None, center=None)
-
self.double_click_with_offset(
selector, x, y, by="css selector", mark=None, timeout=None, center=None)
-
self.is_checked(selector, by="css selector", timeout=None)
# Duplicates:
# self.is_selected(selector, by="css selector", timeout=None)
-
self.check_if_unchecked(selector, by="css selector")
# Duplicates:
# self.select_if_unselected(selector, by="css selector")
-
self.uncheck_if_checked(selector, by="css selector")
# Duplicates:
# self.unselect_if_selected(selector, by="css selector")
-
self.is_element_in_an_iframe(selector, by="css selector")
-
self.switch_to_frame_of_element(selector, by="css selector")
-
self.hover(selector, by="css selector", timeout=None)
# Duplicates:
# self.hover_on_element(selector, by="css selector", timeout=None)
# self.hover_over_element(selector, by="css selector", timeout=None)
-
self.hover_and_click(
hover_selector, click_selector,
hover_by="css selector", click_by="css selector",
timeout=None, js_click=False)
-
self.hover_and_js_click(
hover_selector, click_selector,
hover_by="css selector", click_by="css selector",
timeout=None)
-
self.hover_and_double_click(
hover_selector, click_selector,
hover_by="css selector", click_by="css selector",
timeout=None)
-
self.drag_and_drop(
drag_selector, drop_selector,
drag_by="css selector", drop_by="css selector",
timeout=None, jquery=False)
-
self.drag_and_drop_with_offset(
selector, x, y, by="css selector", timeout=None)
-
self.select_option_by_text(
dropdown_selector, option, dropdown_by="css selector", timeout=None)
-
self.select_option_by_index(
dropdown_selector, option, dropdown_by="css selector", timeout=None)
-
self.select_option_by_value(
dropdown_selector, option, dropdown_by="css selector", timeout=None)
-
self.get_select_options(
dropdown_selector, attribute="text", by="css selector", timeout=None)
-
self.load_html_string(html_string, new_page=True)
-
self.set_content(html_string, new_page=False)
-
self.load_html_file(html_file, new_page=True)
-
self.open_html_file(html_file)
-
self.execute_script(script, *args, **kwargs)
-
self.execute_cdp_cmd(script, *args, **kwargs)
-
self.execute_async_script(script, timeout=None)
-
self.safe_execute_script(script, *args, **kwargs)
-
self.get_element_at_x_y(x, y)
-
self.get_gui_element_rect(selector, by="css selector")
-
self.get_gui_element_center(selector, by="css selector")
-
self.get_screen_rect()
-
self.get_window_rect()
-
self.get_window_size()
-
self.get_window_position()
-
self.set_window_rect(x, y, width, height)
-
self.set_window_size(width, height)
-
self.set_window_position(x, y)
-
self.maximize_window()
-
self.minimize_window()
-
self.reset_window_size()
-
self.switch_to_frame(frame="iframe", timeout=None)
-
self.switch_to_default_content()
-
self.switch_to_parent_frame()
-
with self.frame_switch(frame, timeout=None):
# Indented Code Block for Context Manager (Must use "with")
-
self.set_content_to_frame(frame, timeout=None)
-
self.set_content_to_default(nested=False)
-# Duplicates: self.set_content_to_default_content(nested=False)
-
+# Duplicates:
+# self.set_content_to_default_content(nested=False)
self.set_content_to_parent()
-# Duplicates: self.set_content_to_parent_frame()
-
+# Duplicates:
+# self.set_content_to_parent_frame()
self.open_new_window(switch_to=True)
-# Duplicates: self.open_new_tab(switch_to=True)
-
+# Duplicates:
+# self.open_new_tab(switch_to=True)
self.switch_to_window(window, timeout=None)
-# Duplicates: self.switch_to_tab(tab, timeout=None)
-
+# Duplicates:
+# self.switch_to_tab(tab, timeout=None)
self.switch_to_default_window()
-# Duplicates: self.switch_to_default_tab()
-
+# Duplicates:
+# self.switch_to_default_tab()
self.switch_to_newest_window()
-# Duplicates: self.switch_to_newest_tab()
-
+# Duplicates:
+# self.switch_to_newest_tab()
self.get_new_driver(
browser=None,
headless=None,
@@ -340,323 +242,190 @@ self.get_new_driver(
d_height=None,
d_p_r=None,
)
-
self.switch_to_driver(driver)
-
self.switch_to_default_driver()
-
self.save_screenshot(name, folder=None, selector=None, by="css selector")
-
self.save_screenshot_to_logs(name=None, selector=None, by="css selector")
-
self.save_data_to_logs(data, file_name=None)
-
self.append_data_to_logs(data, file_name=None)
-
self.save_page_source(name, folder=None)
-
self.save_cookies(name="cookies.txt")
-
self.load_cookies(name="cookies.txt", expiry=False)
-
self.delete_all_cookies()
-# Duplicates: self.clear_all_cookies()
-
+# Duplicates:
+# self.clear_all_cookies()
self.delete_saved_cookies(name="cookies.txt")
-
self.get_saved_cookies(name="cookies.txt")
-
self.get_cookie(name)
-
self.get_cookies()
-
self.get_cookie_string()
-
self.add_cookie(cookie_dict, expiry=False)
-
self.add_cookies(cookies, expiry=False)
-
self.wait_for_ready_state_complete(timeout=None)
-
self.wait_for_angularjs(timeout=None)
-
self.sleep(seconds)
-# Duplicates: self.wait(seconds)
-
+# Duplicates:
+# self.wait(seconds)
self.install_addon(xpi_file)
-
self.activate_jquery()
-
self.activate_demo_mode()
-
self.deactivate_demo_mode()
-
self.activate_design_mode()
-
self.deactivate_design_mode()
-
self.activate_recorder()
-
self.save_recorded_actions()
-
self.bring_active_window_to_front()
-
self.bring_to_front(selector, by="css selector")
-
self.highlight_click(selector, by="css selector", loops=3, scroll=True, timeout=None)
-
self.highlight_type(selector, text, by="css selector", loops=3, scroll=True, timeout=None)
# Duplicates:
# 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.highlight_elements(selector, by="css selector", loops=4, scroll=True, limit=0)
-
self.press_up_arrow(selector="html", times=1, by="css selector")
-
self.press_down_arrow(selector="html", times=1, by="css selector")
-
self.press_left_arrow(selector="html", times=1, by="css selector")
-
self.press_right_arrow(selector="html", times=1, by="css selector")
-
self.scroll_to(selector, by="css selector", timeout=None)
-# Duplicates: self.scroll_to_element(selector, by="css selector")
-
+# Duplicates:
+# self.scroll_to_element(selector, by="css selector")
self.slow_scroll_to(selector, by="css selector", timeout=None)
-# Duplicates: self.slow_scroll_to_element(selector, by="css selector")
-
+# Duplicates:
+# self.slow_scroll_to_element(selector, by="css selector")
self.scroll_into_view(selector, by="css selector", timeout=None)
-
self.scroll_to_top()
-
self.scroll_to_bottom()
-
self.click_xpath(xpath)
-
self.js_click(selector, by="css selector", all_matches=False, timeout=None, scroll=True)
-
self.js_click_if_present(selector, by="css selector", timeout=0)
-
self.js_click_if_visible(selector, by="css selector", timeout=0)
-
self.js_click_all(selector, by="css selector", timeout=None)
-
self.jquery_click(selector, by="css selector", timeout=None)
-
self.jquery_click_all(selector, by="css selector", timeout=None)
-
self.hide_element(selector, by="css selector")
-
self.hide_elements(selector, by="css selector")
-
self.show_element(selector, by="css selector")
-
self.show_elements(selector, by="css selector")
-
self.remove_element(selector, by="css selector")
-
self.remove_elements(selector, by="css selector")
-
self.ad_block()
-# Duplicates: self.block_ads()
-
+# Duplicates:
+# self.block_ads()
self.show_file_choosers()
-
self.disable_beforeunload()
-
self.get_domain_url(url)
-
self.get_active_element_css()
-
self.get_beautiful_soup(source=None)
-
self.get_unique_links()
-
self.get_link_status_code(link, allow_redirects=False, timeout=5, verify=False)
-
self.assert_link_status_code_is_not_404(link)
-
self.assert_no_404_errors(multithreaded=True, timeout=None)
# Duplicates:
# self.assert_no_broken_links(multithreaded=True, timeout=None)
-
self.print_unique_links_with_status_codes()
-
self.get_pdf_text(
pdf, page=None, maxpages=None, password=None,
codec='utf-8', wrap=False, nav=False, override=False, caching=True)
-
self.assert_pdf_text(
pdf, text, page=None, maxpages=None, password=None,
codec='utf-8', wrap=True, nav=False, override=False, caching=True)
-
self.create_folder(folder)
-
self.choose_file(selector, file_path, by="css selector", timeout=None)
-
self.save_element_as_image_file(selector, file_name, folder=None, overlay_text="")
-
self.download_file(file_url, destination_folder=None)
-
self.save_file_as(file_url, new_file_name, destination_folder=None)
-
self.save_data_as(data, file_name, destination_folder=None)
-
self.append_data_to_file(data, file_name, destination_folder=None)
-
self.get_file_data(file_name, folder=None)
-
self.get_downloads_folder()
-
self.get_browser_downloads_folder()
-
self.get_downloaded_files(regex=None, browser=False)
-
self.get_path_of_downloaded_file(file, browser=False)
-
self.get_data_from_downloaded_file(file, timeout=None, browser=False)
-
self.is_downloaded_file_present(file, browser=False)
-
self.is_downloaded_file_regex_present(regex, browser=False)
-
self.delete_downloaded_file_if_present(file, browser=False)
-# Duplicates: self.delete_downloaded_file(file, browser=False)
-
+# Duplicates:
+# self.delete_downloaded_file(file, browser=False)
self.assert_downloaded_file(file, timeout=None, browser=False)
-
self.assert_downloaded_file_regex(regex, timeout=None, browser=False)
-
self.assert_data_in_downloaded_file(data, file, timeout=None, browser=False)
-
self.assert_true(expr, msg=None)
-
self.assert_false(expr, msg=None)
-
self.assert_equal(first, second, msg=None)
-
self.assert_not_equal(first, second, msg=None)
-
self.assert_in(first, second, msg=None)
-
self.assert_not_in(first, second, msg=None)
-
self.assert_raises(*args, **kwargs)
-
self.wait_for_attribute(selector, attribute, value=None, by="css selector", timeout=None)
-
self.assert_attribute(selector, attribute, value=None, by="css selector", timeout=None)
-
self.assert_title(title)
-
self.assert_title_contains(substring)
-
self.assert_url(url)
-
self.assert_url_contains(substring)
-
self.assert_no_js_errors(exclude=[])
-
self.inspect_html()
-
self.is_valid_url(url)
-
self.is_alert_present()
-
self.is_online()
-
self.is_chromium()
-
self.get_chrome_version()
-
self.get_chromium_version()
-
self.get_chromedriver_version()
-
self.get_chromium_driver_version()
-
self.get_mfa_code(totp_key=None)
# Duplicates:
# self.get_totp_code(totp_key=None)
# self.get_google_auth_password(totp_key=None)
# self.get_google_auth_code(totp_key=None)
-
self.enter_mfa_code(selector, totp_key=None, by="css selector", timeout=None)
# Duplicates:
# self.enter_totp_code(selector, totp_key=None, by="css selector", timeout=None)
-
self.convert_css_to_xpath(css)
-
self.convert_xpath_to_css(xpath)
-
self.convert_to_css_selector(selector, by)
-
self.set_value(selector, text, by="css selector", timeout=None, scroll=True)
-
self.js_update_text(selector, text, by="css selector", timeout=None)
# Duplicates:
# self.js_type(selector, text, by="css selector", timeout=None)
# self.set_text(selector, text, by="css selector", timeout=None)
-
self.set_text_content(selector, text, by="css selector", timeout=None, scroll=False)
-
self.jquery_update_text(selector, text, by="css selector", timeout=None)
# Duplicates:
# self.jquery_type(selector, text, by="css selector", timeout=None)
-
self.get_value(selector, by="css selector", timeout=None)
-
self.set_time_limit(time_limit)
-
self.set_default_timeout(timeout)
-
self.reset_default_timeout()
-
self.fail(msg=None)
-
self.skip(reason="")
############
self.start_recording_console_logs()
-
self.console_log_string(string)
-
self.console_log_script(script)
-
self.get_recorded_console_logs()
############
self.set_local_storage_item(key, value)
-
self.get_local_storage_item(key)
-
self.remove_local_storage_item(key)
-
self.clear_local_storage()
-# Duplicates: delete_local_storage()
-
+# Duplicates:
+# self.delete_local_storage()
self.get_local_storage_keys()
-
self.get_local_storage_items()
-
self.set_session_storage_item(key, value)
-
self.get_session_storage_item(key)
-
self.remove_session_storage_item(key)
-
self.clear_session_storage()
-# Duplicates: delete_session_storage()
-
+# Duplicates:
+# self.delete_session_storage()
self.get_session_storage_keys()
-
self.get_session_storage_items()
############
@@ -666,27 +435,19 @@ self.set_wire_proxy(string) # Requires "--wire"!
############
self.add_css_link(css_link)
-
self.add_js_link(js_link)
-
self.add_css_style(css_style)
-
self.add_js_code_from_link(js_link)
-
self.add_js_code(js_code)
-
self.add_meta_tag(http_equiv=None, content=None)
############
self.create_presentation(name=None, theme="default", transition="default")
-
self.add_slide(
content=None, image=None, code=None, iframe=None,
content2=None, notes=None, transition=None, name=None)
-
self.save_presentation(name=None, filename=None, show_notes=False, interval=0)
-
self.begin_presentation(name=None, filename=None, show_notes=False, interval=0)
############
@@ -695,95 +456,65 @@ self.create_pie_chart(
chart_name=None, title=None, subtitle=None,
data_name=None, unit=None, libs=True,
labels=True, legend=True)
-
self.create_bar_chart(
chart_name=None, title=None, subtitle=None,
data_name=None, unit=None, libs=True,
labels=True, legend=True)
-
self.create_column_chart(
chart_name=None, title=None, subtitle=None,
data_name=None, unit=None, libs=True,
labels=True, legend=True)
-
self.create_line_chart(
chart_name=None, title=None, subtitle=None,
data_name=None, unit=None, zero=False, libs=True,
labels=True, legend=True)
-
self.create_area_chart(
chart_name=None, title=None, subtitle=None,
data_name=None, unit=None, zero=False, libs=True,
labels=True, legend=True)
-
self.add_series_to_chart(data_name=None, chart_name=None)
-
self.add_data_point(label, value, color=None, chart_name=None)
-
self.save_chart(chart_name=None, filename=None, folder=None)
-
self.display_chart(chart_name=None, filename=None, interval=0)
-
self.extract_chart(chart_name=None)
############
self.create_tour(name=None, theme=None)
-
self.create_shepherd_tour(name=None, theme=None)
-
self.create_bootstrap_tour(name=None)
-
self.create_hopscotch_tour(name=None)
-
self.create_introjs_tour(name=None)
-
self.set_introjs_colors(theme_color=None, hover_color=None)
-
self.add_tour_step(message, selector=None, name=None, title=None, theme=None, alignment=None)
-
self.play_tour(name=None, interval=0)
# Duplicates:
# self.start_tour(name=None, interval=0):
-
self.export_tour(name=None, filename="my_tour.js", url=None)
############
self.activate_jquery_confirm()
-
self.set_jqc_theme(theme, color=None, width=None)
-
self.reset_jqc_theme()
-
self.get_jqc_button_input(message, buttons, options=None)
-
self.get_jqc_text_input(message, button=None, options=None)
-
self.get_jqc_form_inputs(message, buttons, options=None)
############
self.activate_messenger()
-
self.post_message(message, duration=None, pause=True, style="info")
-
self.post_message_and_highlight(message, selector, by="css selector")
-
self.post_success_message(message, duration=None, pause=True)
-
self.post_error_message(message, duration=None, pause=True)
-
self.set_messenger_theme(theme="default", location="default", max_messages="default")
############
self.generate_referral(start_page, destination_page, selector=None)
-
self.generate_traffic(start_page, destination_page, loops=1, selector=None)
-
self.generate_referral_chain(pages)
-
self.generate_traffic_chain(pages, loops=1)
############
@@ -793,11 +524,8 @@ self.get_element(selector, by="css selector", timeout=None)
# 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)
-
self.wait_for_query_selector(selector, by="css selector", timeout=None)
-
self.assert_element_present(selector, by="css selector", timeout=None)
-
self.assert_elements_present(*args, **kwargs)
############
@@ -806,11 +534,9 @@ self.find_element(selector, by="css selector", timeout=None)
# Duplicates:
# self.wait_for_element(selector, by="css selector", timeout=None)
# self.wait_for_element_visible(selector, by="css selector", timeout=None)
-
self.assert_element(selector, by="css selector", timeout=None)
# Duplicates:
# self.assert_element_visible(selector, by="css selector", timeout=None)
-
self.assert_elements(*args, **kwargs)
# Duplicates:
# self.assert_elements_visible(*args, **kwargs)
@@ -821,34 +547,27 @@ self.find_text(text, selector="html", by="css selector", timeout=None)
# Duplicates:
# self.wait_for_text(text, selector="html", by="css selector", timeout=None)
# self.wait_for_text_visible(text, selector="html", by="css selector", timeout=None)
-
self.find_exact_text(text, selector="html", by="css selector", timeout=None)
# Duplicates:
# self.wait_for_exact_text(text, selector="html", by="css selector", timeout=None)
# self.wait_for_exact_text_visible(text, selector="html", by="css selector", timeout=None)
-
self.find_non_empty_text(selector="html", by="css selector", timeout=None)
# Duplicates:
# self.wait_for_non_empty_text(selector="html", by="css selector", timeout=None)
# self.wait_for_non_empty_text_visible(selector="html", by="css selector", timeout=None)
-
self.assert_text(text, selector="html", by="css selector", timeout=None)
# Duplicates:
# self.assert_text_visible(text, selector="html", by="css selector", timeout=None)
-
self.assert_exact_text(text, selector="html", by="css selector", timeout=None)
############
self.wait_for_link_text_present(link_text, timeout=None)
-
self.wait_for_partial_link_text_present(link_text, timeout=None)
-
self.find_link_text(link_text, timeout=None)
# Duplicates:
# self.wait_for_link_text(link_text, timeout=None)
# self.wait_for_link_text_visible(link_text, timeout=None)
-
self.assert_link_text(link_text, timeout=None)
# Duplicates:
# self.assert_link(link_text, timeout=None)
@@ -858,7 +577,6 @@ self.assert_link_text(link_text, timeout=None)
self.find_partial_link_text(partial_link_text, timeout=None)
# Duplicates:
# self.wait_for_partial_link_text(partial_link_text, timeout=None)
-
self.assert_partial_link_text(partial_link_text, timeout=None)
############
@@ -866,7 +584,6 @@ self.assert_partial_link_text(partial_link_text, timeout=None)
self.wait_for_element_absent(selector, by="css selector", timeout=None)
# Duplicates:
# self.wait_for_element_not_present(selector, by="css selector", timeout=None)
-
self.assert_element_absent(selector, by="css selector", timeout=None)
# Duplicates:
# self.assert_element_not_present(selector, by="css selector", timeout=None)
@@ -878,26 +595,20 @@ self.wait_for_element_clickable(selector, by="css selector", timeout=None)
############
self.wait_for_element_not_visible(selector, by="css selector", timeout=None)
-
self.assert_element_not_visible(selector, by="css selector", timeout=None)
############
self.wait_for_text_not_visible(text, selector="html", by="css selector", timeout=None)
-
self.wait_for_exact_text_not_visible(text, selector="html", by="css selector", timeout=None)
-
self.assert_text_not_visible(text, selector="html", by="css selector", timeout=None)
-
self.assert_exact_text_not_visible(text, selector="html", by="css selector", timeout=None)
-
self.assert_non_empty_text(selector="html", by="css selector", timeout=None)
############
self.wait_for_attribute_not_present(
selector, attribute, value=None, by="css selector", timeout=None)
-
self.assert_attribute_not_present(
selector, attribute, value=None, by="css selector", timeout=None)
@@ -906,11 +617,9 @@ self.assert_attribute_not_present(
self.accept_alert(timeout=None)
# Duplicates:
# self.wait_for_and_accept_alert(timeout=None)
-
self.dismiss_alert(timeout=None)
# Duplicates:
# self.wait_for_and_dismiss_alert(timeout=None)
-
self.switch_to_alert(timeout=None)
# Duplicates:
# self.wait_for_and_switch_to_alert(timeout=None)
@@ -929,45 +638,38 @@ self.deferred_assert_element(selector, by="css selector", timeout=None, fs=False
# Duplicates:
# self.delayed_assert_element(
# selector, by="css selector", timeout=None, fs=False)
-
self.deferred_assert_element_present(selector, by="css selector", timeout=None, fs=False)
# Duplicates:
# self.delayed_assert_element_present(
# selector, by="css selector", timeout=None, fs=False)
-
self.deferred_assert_text(text, selector="html", by="css selector", timeout=None, fs=False)
# Duplicates:
# self.delayed_assert_text(
# text, selector="html", by="css selector", timeout=None, fs=False)
-
self.deferred_assert_exact_text(
text, selector="html", by="css selector", timeout=None, fs=False)
# Duplicates:
# self.delayed_assert_exact_text(
# text, selector="html", by="css selector", timeout=None, fs=False)
-
self.deferred_assert_non_empty_text(
selector="html", by="css selector", timeout=None, fs=False)
# Duplicates:
# self.delayed_assert_non_empty_text(
# selector="html", by="css selector", timeout=None, fs=False)
-
self.deferred_check_window(
name="default", level=0, baseline=False, check_domain=True, full_diff=False, fs=False)
# Duplicates:
# self.delayed_check_window(
# name="default", level=0, baseline=False,
# check_domain=True, full_diff=False, fs=False)
-
self.process_deferred_asserts(print_only=False)
-# Duplicates: self.process_delayed_asserts(print_only=False)
+# Duplicates:
+# self.process_delayed_asserts(print_only=False)
############
self.fail(msg=None) # Inherited from "unittest"
-
self._check_browser() # Fails test cleanly if the active window is closed
-
self._print(TEXT) # Calls Python's print() / Allows for translations
############
@@ -977,35 +679,22 @@ self._print(TEXT) # Calls Python's print() / Allows for translations
# (Mainly for CDP Mode) - (For all CDP methods, see the CDP Mode Docs)
self.activate_cdp_mode(url=None) # Activate CDP Mode on the given URL
-
self.reconnect(timeout=0.1) # disconnect() + sleep(timeout) + connect()
-
self.disconnect() # Stops the webdriver service to prevent detection
-
self.connect() # Starts the webdriver service to allow actions again
# (For regular UC Mode)
self.uc_open(url) # (Open in same tab with default reconnect_time)
-
self.uc_open_with_tab(url) # (New tab with default reconnect_time)
-
self.uc_open_with_reconnect(url, reconnect_time=None) # (New tab)
-
self.uc_open_with_disconnect(url, timeout=None) # New tab + sleep()
-
self.uc_click(selector) # A stealthy click for evading bot-detection
-
self.uc_gui_press_key(key) # Use PyAutoGUI to press the keyboard key
-
self.uc_gui_press_keys(keys) # Use PyAutoGUI to press a list of keys
-
self.uc_gui_write(text) # Similar to uc_gui_press_keys(), but faster
-
self.uc_gui_click_x_y(x, y, timeframe=0.25) # PyAutoGUI click screen
-
self.uc_gui_click_captcha(frame="iframe", retry=False, blind=False)
-
self.uc_gui_handle_captcha(frame="iframe")
############
@@ -1013,93 +702,49 @@ self.uc_gui_handle_captcha(frame="iframe")
# "driver"-specific methods added (or modified) by SeleniumBase
driver.default_get(url) # Because driver.get(url) works differently in UC Mode
-
driver.open(url) # Like driver.get(), but allows partial URLs without protocol
-
driver.click(selector)
-
driver.click_link(link_text)
-
driver.click_if_visible(selector)
-
driver.click_active_element()
-
driver.send_keys(selector, text)
-
driver.press_keys(selector, text)
-
driver.type(selector, text)
-
driver.submit(selector)
-
driver.assert_element(selector)
-
driver.assert_element_present(selector)
-
driver.assert_element_not_visible(selector)
-
driver.assert_text(text, selector)
-
driver.assert_exact_text(text, selector)
-
driver.find_element(selector)
-
driver.find_elements(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)
-
driver.wait_for_and_accept_alert()
-
driver.wait_for_and_dismiss_alert()
-
driver.is_element_present(selector)
-
driver.is_element_visible(selector)
-
driver.is_text_visible(text, selector)
-
driver.is_exact_text_visible(text, selector)
-
driver.is_attribute_present(selector, attribute)
-
driver.get_text(selector)
-
driver.js_click(selector)
-
driver.get_active_element_css()
-
driver.get_locale_code()
-
driver.get_origin()
-
driver.get_user_agent()
-
driver.highlight(selector)
-
driver.highlight_click(selector)
-
driver.highlight_if_visible(selector)
-
driver.sleep(seconds)
-
driver.locator(selector)
-
driver.get_attribute(selector, attribute)
-
driver.get_page_source()
-
driver.get_title()
-
driver.switch_to_frame(frame="iframe")
############
@@ -1107,35 +752,20 @@ driver.switch_to_frame(frame="iframe")
# "driver"-specific methods added (or modified) by SeleniumBase for UC Mode:
driver.get(url) # If UC Mode and site detects bots, then uc_open_with_tab(url)
-
driver.uc_open(url) # (Open in same tab with default reconnect_time)
-
driver.uc_open_with_tab(url) # (New tab with default reconnect_time)
-
driver.uc_open_with_reconnect(url, reconnect_time=None) # (New tab)
-
driver.uc_open_with_disconnect(url, timeout=None) # New tab + sleep()
-
driver.uc_activate_cdp_mode(url=None) # Activate CDP Mode on the given URL
-
driver.reconnect(timeout=0.1) # disconnect() + sleep(timeout) + connect()
-
driver.disconnect() # Stops the webdriver service to prevent detection
-
driver.connect() # Starts the webdriver service to allow actions again
-
driver.uc_click(selector) # A stealthy click for evading bot-detection
-
driver.uc_gui_press_key(key) # Use PyAutoGUI to press the keyboard key
-
driver.uc_gui_press_keys(keys) # Use PyAutoGUI to press a list of keys
-
driver.uc_gui_write(text) # Similar to uc_gui_press_keys(), but faster
-
driver.uc_gui_click_x_y(x, y, timeframe=0.25) # PyAutoGUI click screen
-
driver.uc_gui_click_captcha(frame="iframe", retry=False, blind=False)
-
driver.uc_gui_handle_captcha(frame="iframe")
```
diff --git a/mkdocs_build/requirements.txt b/mkdocs_build/requirements.txt
index d5962837b17..4608be4cd1e 100644
--- a/mkdocs_build/requirements.txt
+++ b/mkdocs_build/requirements.txt
@@ -2,14 +2,12 @@
# Minimum Python version: 3.9 (for generating docs only)
regex>=2024.11.6
-pymdown-extensions>=10.12
+pymdown-extensions>=10.13
pipdeptree>=2.24.0
python-dateutil>=2.8.2
Markdown==3.7
markdown2==2.5.2
-MarkupSafe==3.0.2
-Jinja2==3.1.4
-click==8.1.7
+click==8.1.8
ghp-import==2.1.0
watchdog==6.0.0
cairocffi==1.7.1
@@ -20,7 +18,7 @@ lxml==5.3.0
pyquery==2.0.1
readtime==3.0.0
mkdocs==1.6.1
-mkdocs-material==9.5.48
+mkdocs-material==9.5.49
mkdocs-exclude-search==0.6.6
mkdocs-simple-hooks==0.1.5
mkdocs-material-extensions==1.3.1
diff --git a/requirements.txt b/requirements.txt
index a52ab7e25da..806752a8c0d 100755
--- a/requirements.txt
+++ b/requirements.txt
@@ -3,7 +3,7 @@ packaging>=24.2
setuptools~=70.2;python_version<"3.10"
setuptools>=75.6.0;python_version>="3.10"
wheel>=0.45.1
-attrs>=24.2.0
+attrs>=24.3.0
certifi>=2024.12.14
exceptiongroup>=1.2.2
websockets~=13.1;python_version<"3.9"
@@ -14,7 +14,10 @@ mycdp>=1.1.0
pynose>=1.5.3
platformdirs>=4.3.6
typing-extensions>=4.12.2
-sbvirtualdisplay>=1.3.1
+sbvirtualdisplay>=1.4.0
+MarkupSafe==2.1.5;python_version<"3.9"
+MarkupSafe>=3.0.2;python_version>="3.9"
+Jinja2>=3.1.5
six>=1.17.0
parse>=1.20.2
parse-type>=0.6.4
@@ -26,9 +29,9 @@ tabcompleter>=1.4.0
pdbp>=1.6.1
idna==3.10
chardet==5.2.0
-charset-normalizer==3.4.0
+charset-normalizer==3.4.1
urllib3>=1.26.20,<2;python_version<"3.10"
-urllib3>=1.26.20,<2.3.0;python_version>="3.10"
+urllib3>=1.26.20,<2.4.0;python_version>="3.10"
requests==2.32.3
sniffio==1.3.1
h11==0.14.0
diff --git a/seleniumbase/__version__.py b/seleniumbase/__version__.py
index 46f03196f5e..5a2eda19a6a 100755
--- a/seleniumbase/__version__.py
+++ b/seleniumbase/__version__.py
@@ -1,2 +1,2 @@
# seleniumbase package
-__version__ = "4.33.11"
+__version__ = "4.33.12"
diff --git a/seleniumbase/core/log_helper.py b/seleniumbase/core/log_helper.py
index ceb9c531a29..bd1ebe25be9 100644
--- a/seleniumbase/core/log_helper.py
+++ b/seleniumbase/core/log_helper.py
@@ -15,6 +15,11 @@
py311_patch2 = constants.PatchPy311.PATCH
+def __is_cdp_swap_needed(driver):
+ """If the driver is disconnected, use a CDP method when available."""
+ return shared_utils.is_cdp_swap_needed(driver)
+
+
def log_screenshot(test_logpath, driver, screenshot=None, get=False):
screenshot_name = settings.SCREENSHOT_NAME
screenshot_path = os.path.join(test_logpath, screenshot_name)
@@ -356,7 +361,11 @@ def log_page_source(test_logpath, driver, source=None):
page_source = source
else:
try:
- page_source = driver.page_source
+ page_source = None
+ if __is_cdp_swap_needed(driver):
+ page_source = driver.cdp.get_page_source()
+ else:
+ page_source = driver.page_source
page_source = get_html_source_with_base_href(driver, page_source)
except Exception:
source = constants.Warnings.PAGE_SOURCE_UNDEFINED
@@ -448,7 +457,11 @@ def get_test_name(test):
def get_last_page(driver):
try:
- last_page = driver.current_url
+ last_page = None
+ if __is_cdp_swap_needed(driver):
+ last_page = driver.cdp.get_current_url()
+ else:
+ last_page = driver.current_url
except Exception:
last_page = "[WARNING! Browser Not Open!]"
if len(last_page) < 5:
diff --git a/seleniumbase/core/sb_cdp.py b/seleniumbase/core/sb_cdp.py
index 7cde2ee2f39..65a36be93e1 100644
--- a/seleniumbase/core/sb_cdp.py
+++ b/seleniumbase/core/sb_cdp.py
@@ -127,14 +127,14 @@ def get_event_loop(self):
def add_handler(self, event, handler):
self.page.add_handler(event, handler)
- def find_element(
- self, selector, best_match=False, timeout=settings.SMALL_TIMEOUT
- ):
+ def find_element(self, selector, best_match=False, timeout=None):
"""Similar to select(), but also finds elements by text content.
When using text-based searches, if best_match=False, then will
find the first element with the text. If best_match=True, then
if multiple elements have that text, then will use the element
with the closest text-length to the text being searched for."""
+ if not timeout:
+ timeout = settings.SMALL_TIMEOUT
self.__add_light_pause()
selector = self.__convert_to_css_if_xpath(selector)
early_failure = False
@@ -167,12 +167,12 @@ def find_element(
self.__slow_mode_pause_if_set()
return element
- def find_element_by_text(
- self, text, tag_name=None, timeout=settings.SMALL_TIMEOUT
- ):
+ def find_element_by_text(self, text, tag_name=None, timeout=None):
"""Returns an element by matching text.
Optionally, provide a tag_name to narrow down the search to an
element with the given tag. (Eg: a, button, div, script, span)"""
+ if not timeout:
+ timeout = settings.SMALL_TIMEOUT
self.__add_light_pause()
time_now = time.time()
self.assert_text(text, timeout=timeout)
@@ -218,7 +218,9 @@ def find_element_by_text(
% (text, tag_name, timeout, plural)
)
- def find_all(self, selector, timeout=settings.SMALL_TIMEOUT):
+ def find_all(self, selector, timeout=None):
+ if not timeout:
+ timeout = settings.SMALL_TIMEOUT
self.__add_light_pause()
selector = self.__convert_to_css_if_xpath(selector)
elements = self.loop.run_until_complete(
@@ -272,8 +274,10 @@ def find_elements_by_text(self, text, tag_name=None):
updated_elements.append(element)
return updated_elements
- def select(self, selector, timeout=settings.SMALL_TIMEOUT):
+ def select(self, selector, timeout=None):
"""Similar to find_element(), but without text-based search."""
+ if not timeout:
+ timeout = settings.SMALL_TIMEOUT
self.__add_light_pause()
selector = self.__convert_to_css_if_xpath(selector)
if (":contains(" in selector):
@@ -307,7 +311,9 @@ def select(self, selector, timeout=settings.SMALL_TIMEOUT):
self.__slow_mode_pause_if_set()
return element
- def select_all(self, selector, timeout=settings.SMALL_TIMEOUT):
+ def select_all(self, selector, timeout=None):
+ if not timeout:
+ timeout = settings.SMALL_TIMEOUT
self.__add_light_pause()
selector = self.__convert_to_css_if_xpath(selector)
elements = self.loop.run_until_complete(
@@ -319,10 +325,14 @@ def select_all(self, selector, timeout=settings.SMALL_TIMEOUT):
updated_elements.append(element)
return updated_elements
- def find_elements(self, selector, timeout=settings.SMALL_TIMEOUT):
+ def find_elements(self, selector, timeout=None):
+ if not timeout:
+ timeout = settings.SMALL_TIMEOUT
return self.select_all(selector, timeout=timeout)
- def find_visible_elements(self, selector, timeout=settings.SMALL_TIMEOUT):
+ def find_visible_elements(self, selector, timeout=None):
+ if not timeout:
+ timeout = settings.SMALL_TIMEOUT
visible_elements = []
elements = self.select_all(selector, timeout=timeout)
for element in elements:
@@ -587,12 +597,12 @@ def load_cookies(self, *args, **kwargs):
driver.cookies.load(*args, **kwargs)
)
- def clear_cookies(self, *args, **kwargs):
+ def clear_cookies(self):
driver = self.driver
if hasattr(driver, "cdp_base"):
driver = driver.cdp_base
return self.loop.run_until_complete(
- driver.cookies.clear(*args, **kwargs)
+ driver.cookies.clear()
)
def sleep(self, seconds):
@@ -616,7 +626,9 @@ def get_active_element_css(self):
self.page.evaluate(js_code)
)
- def click(self, selector, timeout=settings.SMALL_TIMEOUT):
+ def click(self, selector, timeout=None):
+ if not timeout:
+ timeout = settings.SMALL_TIMEOUT
self.__slow_mode_pause_if_set()
element = self.find_element(selector, timeout=timeout)
element.scroll_into_view()
@@ -672,8 +684,10 @@ def click_visible_elements(self, selector, limit=0):
except Exception:
break
- def mouse_click(self, selector, timeout=settings.SMALL_TIMEOUT):
+ def mouse_click(self, selector, timeout=None):
"""(Attempt simulating a mouse click)"""
+ if not timeout:
+ timeout = settings.SMALL_TIMEOUT
self.__slow_mode_pause_if_set()
element = self.find_element(selector, timeout=timeout)
element.scroll_into_view()
@@ -771,7 +785,9 @@ def remove_elements(self, selector):
with suppress(Exception):
self.loop.run_until_complete(self.page.evaluate(js_code))
- def send_keys(self, selector, text, timeout=settings.SMALL_TIMEOUT):
+ def send_keys(self, selector, text, timeout=None):
+ if not timeout:
+ timeout = settings.SMALL_TIMEOUT
self.__slow_mode_pause_if_set()
element = self.select(selector, timeout=timeout)
element.scroll_into_view()
@@ -781,8 +797,10 @@ def send_keys(self, selector, text, timeout=settings.SMALL_TIMEOUT):
self.__slow_mode_pause_if_set()
self.loop.run_until_complete(self.page.wait())
- def press_keys(self, selector, text, timeout=settings.SMALL_TIMEOUT):
+ def press_keys(self, selector, text, timeout=None):
"""Similar to send_keys(), but presses keys at human speed."""
+ if not timeout:
+ timeout = settings.SMALL_TIMEOUT
self.__slow_mode_pause_if_set()
element = self.select(selector, timeout=timeout)
element.scroll_into_view()
@@ -799,8 +817,10 @@ def press_keys(self, selector, text, timeout=settings.SMALL_TIMEOUT):
self.__slow_mode_pause_if_set()
self.loop.run_until_complete(self.page.wait())
- def type(self, selector, text, timeout=settings.SMALL_TIMEOUT):
+ def type(self, selector, text, timeout=None):
"""Similar to send_keys(), but clears the text field first."""
+ if not timeout:
+ timeout = settings.SMALL_TIMEOUT
self.__slow_mode_pause_if_set()
element = self.select(selector, timeout=timeout)
element.scroll_into_view()
@@ -812,8 +832,10 @@ def type(self, selector, text, timeout=settings.SMALL_TIMEOUT):
self.__slow_mode_pause_if_set()
self.loop.run_until_complete(self.page.wait())
- def set_value(self, selector, text, timeout=settings.SMALL_TIMEOUT):
+ def set_value(self, selector, text, timeout=None):
"""Similar to send_keys(), but clears the text field first."""
+ if not timeout:
+ timeout = settings.SMALL_TIMEOUT
self.__slow_mode_pause_if_set()
selector = self.__convert_to_css_if_xpath(selector)
element = self.select(selector, timeout=timeout)
@@ -1036,7 +1058,9 @@ def get_window_position(self):
coordinates["y"] = y if y else 0
return coordinates
- def get_element_rect(self, selector, timeout=settings.SMALL_TIMEOUT):
+ def get_element_rect(self, selector, timeout=None):
+ if not timeout:
+ timeout = settings.SMALL_TIMEOUT
selector = self.__convert_to_css_if_xpath(selector)
self.select(selector, timeout=timeout)
self.__add_light_pause()
@@ -1049,23 +1073,29 @@ def get_element_rect(self, selector, timeout=settings.SMALL_TIMEOUT):
)
return coordinates
- def get_element_size(self, selector):
- element_rect = self.get_element_rect(selector)
+ def get_element_size(self, selector, timeout=None):
+ if not timeout:
+ timeout = settings.SMALL_TIMEOUT
+ element_rect = self.get_element_rect(selector, timeout=timeout)
coordinates = {}
coordinates["width"] = element_rect["width"]
coordinates["height"] = element_rect["height"]
return coordinates
- def get_element_position(self, selector):
- element_rect = self.get_element_rect(selector)
+ def get_element_position(self, selector, timeout=None):
+ if not timeout:
+ timeout = settings.SMALL_TIMEOUT
+ element_rect = self.get_element_rect(selector, timeout=timeout)
coordinates = {}
coordinates["x"] = element_rect["x"]
coordinates["y"] = element_rect["y"]
return coordinates
- def get_gui_element_rect(self, selector):
+ def get_gui_element_rect(self, selector, timeout=None):
"""(Coordinates are relative to the screen. Not the window.)"""
- element_rect = self.get_element_rect(selector)
+ if not timeout:
+ timeout = settings.SMALL_TIMEOUT
+ element_rect = self.get_element_rect(selector, timeout=timeout)
e_width = element_rect["width"]
e_height = element_rect["height"]
window_rect = self.get_window_rect()
@@ -1079,9 +1109,11 @@ def get_gui_element_rect(self, selector):
y = y + window_rect["scrollY"]
return ({"height": e_height, "width": e_width, "x": x, "y": y})
- def get_gui_element_center(self, selector):
+ def get_gui_element_center(self, selector, timeout=None):
"""(Coordinates are relative to the screen. Not the window.)"""
- element_rect = self.get_gui_element_rect(selector)
+ if not timeout:
+ timeout = settings.SMALL_TIMEOUT
+ element_rect = self.get_gui_element_rect(selector, timeout=timeout)
e_width = element_rect["width"]
e_height = element_rect["height"]
e_x = element_rect["x"]
@@ -1629,9 +1661,9 @@ def is_element_visible(self, selector):
return True
return False
- def wait_for_element_visible(
- self, selector, timeout=settings.SMALL_TIMEOUT
- ):
+ def wait_for_element_visible(self, selector, timeout=None):
+ if not timeout:
+ timeout = settings.SMALL_TIMEOUT
try:
self.select(selector, timeout=timeout)
except Exception:
@@ -1642,8 +1674,10 @@ def wait_for_element_visible(
time.sleep(0.1)
raise Exception("Element {%s} was not visible!" % selector)
- def assert_element(self, selector, timeout=settings.SMALL_TIMEOUT):
+ def assert_element(self, selector, timeout=None):
"""Same as assert_element_visible()"""
+ if not timeout:
+ timeout = settings.SMALL_TIMEOUT
try:
self.select(selector, timeout=timeout)
except Exception:
@@ -1654,8 +1688,10 @@ def assert_element(self, selector, timeout=settings.SMALL_TIMEOUT):
time.sleep(0.1)
raise Exception("Element {%s} was not visible!" % selector)
- def assert_element_visible(self, selector, timeout=settings.SMALL_TIMEOUT):
+ def assert_element_visible(self, selector, timeout=None):
"""Same as assert_element()"""
+ if not timeout:
+ timeout = settings.SMALL_TIMEOUT
try:
self.select(selector, timeout=timeout)
except Exception:
@@ -1666,16 +1702,20 @@ def assert_element_visible(self, selector, timeout=settings.SMALL_TIMEOUT):
time.sleep(0.1)
raise Exception("Element {%s} was not visible!" % selector)
- def assert_element_present(self, selector, timeout=settings.SMALL_TIMEOUT):
+ def assert_element_present(self, selector, timeout=None):
"""Assert element is present in the DOM. (Visibility NOT required)"""
+ if not timeout:
+ timeout = settings.SMALL_TIMEOUT
try:
self.select(selector, timeout=timeout)
except Exception:
raise Exception("Element {%s} was not found!" % selector)
return True
- def assert_element_absent(self, selector, timeout=settings.SMALL_TIMEOUT):
+ def assert_element_absent(self, selector, timeout=None):
"""Assert element is not present in the DOM."""
+ if not timeout:
+ timeout = settings.SMALL_TIMEOUT
start_ms = time.time() * 1000.0
stop_ms = start_ms + (timeout * 1000.0)
for i in range(int(timeout * 10)):
@@ -1693,10 +1733,10 @@ def assert_element_absent(self, selector, timeout=settings.SMALL_TIMEOUT):
% (selector, timeout, plural)
)
- def assert_element_not_visible(
- self, selector, timeout=settings.SMALL_TIMEOUT
- ):
+ def assert_element_not_visible(self, selector, timeout=None):
"""Assert element is not visible on page. (May still be in DOM)"""
+ if not timeout:
+ timeout = settings.SMALL_TIMEOUT
start_ms = time.time() * 1000.0
stop_ms = start_ms + (timeout * 1000.0)
for i in range(int(timeout * 10)):
@@ -1791,9 +1831,9 @@ def assert_url_contains(self, substring):
if expected not in actual:
raise Exception(error % (expected, actual))
- def assert_text(
- self, text, selector="body", timeout=settings.SMALL_TIMEOUT
- ):
+ def assert_text(self, text, selector="body", timeout=None):
+ if not timeout:
+ timeout = settings.SMALL_TIMEOUT
start_ms = time.time() * 1000.0
stop_ms = start_ms + (timeout * 1000.0)
text = text.strip()
@@ -1816,9 +1856,9 @@ def assert_text(
% (text, selector, element.text_all)
)
- def assert_exact_text(
- self, text, selector="body", timeout=settings.SMALL_TIMEOUT
- ):
+ def assert_exact_text(self, text, selector="body", timeout=None):
+ if not timeout:
+ timeout = settings.SMALL_TIMEOUT
start_ms = time.time() * 1000.0
stop_ms = start_ms + (timeout * 1000.0)
text = text.strip()
diff --git a/seleniumbase/fixtures/base_case.py b/seleniumbase/fixtures/base_case.py
index d93fa380625..e8092ba0583 100644
--- a/seleniumbase/fixtures/base_case.py
+++ b/seleniumbase/fixtures/base_case.py
@@ -4492,7 +4492,8 @@ def save_page_source(self, name, folder=None):
@Params
name - The file name to save the current page's HTML to.
folder - The folder to save the file to. (Default = current folder)"""
- self.wait_for_ready_state_complete()
+ if not self.__is_cdp_swap_needed():
+ self.wait_for_ready_state_complete()
return page_actions.save_page_source(self.driver, name, folder)
def save_cookies(self, name="cookies.txt"):
@@ -4550,6 +4551,9 @@ def load_cookies(self, name="cookies.txt", expiry=False):
def delete_all_cookies(self):
"""Deletes all cookies in the web browser.
Does NOT delete the saved cookies file."""
+ if self.__is_cdp_swap_needed():
+ self.cdp.clear_cookies()
+ return
self.wait_for_ready_state_complete()
self.driver.delete_all_cookies()
if self.recorder_mode:
@@ -4561,7 +4565,6 @@ def delete_all_cookies(self):
def delete_saved_cookies(self, name="cookies.txt"):
"""Deletes the cookies file from the "saved_cookies" folder.
Does NOT delete the cookies from the web browser."""
- self.wait_for_ready_state_complete()
if name.endswith("/"):
raise Exception("Invalid filename for Cookies!")
if "/" in name:
@@ -4600,14 +4603,20 @@ def get_saved_cookies(self, name="cookies.txt"):
return json.loads(json_cookies)
def get_cookie(self, name):
+ self.__check_scope()
+ self._check_browser()
return self.driver.get_cookie(name)
def get_cookies(self):
+ self.__check_scope()
+ self._check_browser()
return self.driver.get_cookies()
def get_cookie_string(self):
+ self.__check_scope()
if self.__is_cdp_swap_needed():
return self.cdp.get_cookie_string()
+ self._check_browser()
return self.execute_script("return document.cookie;")
def add_cookie(self, cookie_dict, expiry=False):
@@ -4622,6 +4631,8 @@ def add_cookie(self, cookie_dict, expiry=False):
If expiry > 0: Set "expiry" to expiry minutes in the future.
If expiry == True: Set "expiry" to 24 hours in the future.
"""
+ self.__check_scope()
+ self._check_browser()
cookie = cookie_dict
if "domain" in cookie:
origin = self.get_origin()
@@ -4646,6 +4657,8 @@ def add_cookies(self, cookies, expiry=False):
If expiry > 0: Set "expiry" to expiry minutes in the future.
If expiry == True: Set "expiry" to 24 hours in the future.
"""
+ self.__check_scope()
+ self._check_browser()
origin = self.get_origin()
trim_origin = origin.split("://")[-1]
for cookie in cookies:
diff --git a/seleniumbase/fixtures/page_actions.py b/seleniumbase/fixtures/page_actions.py
index f754ad2b334..bb5bf055f0b 100644
--- a/seleniumbase/fixtures/page_actions.py
+++ b/seleniumbase/fixtures/page_actions.py
@@ -1342,7 +1342,8 @@ def save_page_source(driver, name, folder=None):
"""
from seleniumbase.core import log_helper
- _reconnect_if_disconnected(driver)
+ if not __is_cdp_swap_needed(driver):
+ _reconnect_if_disconnected(driver) # If disconnected without CDP
if not name.endswith(".html"):
name = name + ".html"
if folder:
@@ -1353,7 +1354,11 @@ def save_page_source(driver, name, folder=None):
html_file_path = os.path.join(file_path, name)
else:
html_file_path = name
- page_source = driver.page_source
+ page_source = None
+ if __is_cdp_swap_needed(driver):
+ page_source = driver.cdp.get_page_source()
+ else:
+ page_source = driver.page_source
html_file = codecs.open(html_file_path, "w+", "utf-8")
rendered_source = log_helper.get_html_source_with_base_href(
driver, page_source
diff --git a/setup.py b/setup.py
index 8a50ea512c7..01615ed533e 100755
--- a/setup.py
+++ b/setup.py
@@ -152,7 +152,7 @@
'setuptools~=70.2;python_version<"3.10"', # Newer ones had issues
'setuptools>=75.6.0;python_version>="3.10"',
'wheel>=0.45.1',
- 'attrs>=24.2.0',
+ 'attrs>=24.3.0',
"certifi>=2024.12.14",
"exceptiongroup>=1.2.2",
'websockets~=13.1;python_version<"3.9"',
@@ -163,7 +163,10 @@
"pynose>=1.5.3",
'platformdirs>=4.3.6',
'typing-extensions>=4.12.2',
- "sbvirtualdisplay>=1.3.1",
+ "sbvirtualdisplay>=1.4.0",
+ 'MarkupSafe==2.1.5;python_version<"3.9"',
+ 'MarkupSafe>=3.0.2;python_version>="3.9"',
+ "Jinja2>=3.1.5",
"six>=1.17.0",
'parse>=1.20.2',
'parse-type>=0.6.4',
@@ -175,9 +178,9 @@
"pdbp>=1.6.1",
"idna==3.10",
'chardet==5.2.0',
- 'charset-normalizer==3.4.0',
+ 'charset-normalizer==3.4.1',
'urllib3>=1.26.20,<2;python_version<"3.10"',
- 'urllib3>=1.26.20,<2.3.0;python_version>="3.10"',
+ 'urllib3>=1.26.20,<2.4.0;python_version>="3.10"',
'requests==2.32.3',
'sniffio==1.3.1',
'h11==0.14.0',