Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions examples/cdp_mode/ReadMe.md
Original file line number Diff line number Diff line change
Expand Up @@ -506,6 +506,8 @@ sb.cdp.gui_click_and_hold(selector, timeframe=0.35)
sb.cdp.gui_hover_x_y(x, y)
sb.cdp.gui_hover_element(selector)
sb.cdp.gui_hover_and_click(hover_selector, click_selector)
sb.cdp.hover_element(selector)
sb.cdp.hover_and_click(hover_selector, click_selector)
sb.cdp.internalize_links()
sb.cdp.is_checked(selector)
sb.cdp.is_selected(selector)
Expand Down
2 changes: 1 addition & 1 deletion examples/cdp_mode/raw_canvas.py
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ def get_canvas_pixel_colors_at_top_left(sb):
url = "https://seleniumbase.io/other/canvas"
sb.activate_cdp_mode(url)
sb.assert_title_contains("Canvas")
sb.cdp.gui_click_with_offset("canvas", 0, 0, center=True)
sb.cdp.click_with_offset("canvas", 0, 0, center=True)
sb.sleep(1)
sb.uc_gui_press_key("ENTER")
sb.sleep(0.5)
2 changes: 1 addition & 1 deletion examples/cdp_mode/raw_demo_site.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@

# Hover & click a dropdown element and assert results
sb.cdp.assert_text("Automation Practice", "h3")
sb.cdp.gui_hover_and_click("#myDropdown", "#dropOption2")
sb.cdp.hover_and_click("#myDropdown", "#dropOption2")
sb.cdp.assert_text("Link Two Selected", "h3")

# Click a button and then verify the expected results
Expand Down
6 changes: 3 additions & 3 deletions examples/cdp_mode/raw_handle_alerts.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,15 +4,15 @@
with SB(uc=True, test=True) as sb:
url = "https://the-internet.herokuapp.com/javascript_alerts"
sb.activate_cdp_mode(url)
sb.cdp.gui_click_element('button[onclick="jsAlert()"]')
sb.click('button[onclick="jsAlert()"]')
sb.sleep(1)
sb.uc_gui_press_key("\n") # Accept Alert
sb.sleep(1)
sb.cdp.gui_click_element('button[onclick="jsConfirm()"]')
sb.click('button[onclick="jsConfirm()"]')
sb.sleep(1)
sb.uc_gui_press_key("ESC") # Dismiss Alert
sb.sleep(1)
sb.cdp.gui_click_element('button[onclick="jsPrompt()"]')
sb.click('button[onclick="jsPrompt()"]')
sb.sleep(1)
sb.uc_gui_write("Here is my prompt answer\n")
sb.sleep(1)
2 changes: 2 additions & 0 deletions help_docs/cdp_mode_methods.md
Original file line number Diff line number Diff line change
Expand Up @@ -144,6 +144,8 @@ sb.cdp.gui_click_and_hold(selector, timeframe=0.35)
sb.cdp.gui_hover_x_y(x, y)
sb.cdp.gui_hover_element(selector)
sb.cdp.gui_hover_and_click(hover_selector, click_selector)
sb.cdp.hover_element(selector)
sb.cdp.hover_and_click(hover_selector, click_selector)
sb.cdp.internalize_links()
sb.cdp.is_checked(selector)
sb.cdp.is_selected(selector)
Expand Down
1 change: 1 addition & 0 deletions help_docs/method_summary.md
Original file line number Diff line number Diff line change
Expand Up @@ -111,6 +111,7 @@ 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_element(selector, by="css selector", timeout=None)
# self.hover_on_element(selector, by="css selector", timeout=None)
# self.hover_over_element(selector, by="css selector", timeout=None)
self.hover_and_click(
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.45.5"
__version__ = "4.45.6"
6 changes: 6 additions & 0 deletions seleniumbase/core/browser_launcher.py
Original file line number Diff line number Diff line change
Expand Up @@ -846,6 +846,8 @@ def uc_open_with_cdp_mode(driver, url=None, **kwargs):
cdp.gui_hover_x_y = CDPM.gui_hover_x_y
cdp.gui_hover_element = CDPM.gui_hover_element
cdp.gui_hover_and_click = CDPM.gui_hover_and_click
cdp.hover_element = CDPM.hover_element
cdp.hover_and_click = CDPM.hover_and_click
cdp.internalize_links = CDPM.internalize_links
cdp.open_new_window = CDPM.open_new_window
cdp.switch_to_window = CDPM.switch_to_window
Expand Down Expand Up @@ -2736,6 +2738,7 @@ def _set_chrome_options(
chrome_options.add_argument("--disable-save-password-bubble")
chrome_options.add_argument("--disable-single-click-autofill")
chrome_options.add_argument("--allow-file-access-from-files")
chrome_options.add_argument("--disable-component-update")
chrome_options.add_argument("--disable-prompt-on-repost")
chrome_options.add_argument("--dns-prefetch-disable")
chrome_options.add_argument("--disable-translate")
Expand Down Expand Up @@ -2764,6 +2767,7 @@ def _set_chrome_options(
included_disabled_features.append("OptimizationHints")
included_disabled_features.append("OptimizationHintsFetching")
included_disabled_features.append("Translate")
included_disabled_features.append("ComponentUpdater")
included_disabled_features.append("OptimizationTargetPrediction")
included_disabled_features.append("OptimizationGuideModelDownloading")
included_disabled_features.append("DownloadBubble")
Expand Down Expand Up @@ -4789,6 +4793,7 @@ def get_local_driver(
if devtools and not headless:
edge_options.add_argument("--auto-open-devtools-for-tabs")
edge_options.add_argument("--allow-file-access-from-files")
edge_options.add_argument("--disable-component-update")
edge_options.add_argument("--allow-insecure-localhost")
edge_options.add_argument("--allow-running-insecure-content")
if user_agent:
Expand Down Expand Up @@ -4847,6 +4852,7 @@ def get_local_driver(
included_disabled_features.append("OptimizationHints")
included_disabled_features.append("OptimizationHintsFetching")
included_disabled_features.append("Translate")
included_disabled_features.append("ComponentUpdater")
included_disabled_features.append("OptimizationTargetPrediction")
included_disabled_features.append("OptimizationGuideModelDownloading")
included_disabled_features.append("InsecureDownloadWarnings")
Expand Down
25 changes: 25 additions & 0 deletions seleniumbase/core/sb_cdp.py
Original file line number Diff line number Diff line change
Expand Up @@ -2384,6 +2384,31 @@ def gui_hover_element(self, selector, timeframe=0.25):
self.__slow_mode_pause_if_set()
self.loop.run_until_complete(self.page.wait())

def hover_element(self, selector, timeframe=0.25):
element = self.select(selector)
gui_lock = FileLock(constants.MultiBrowser.PYAUTOGUILOCK)
with gui_lock:
self.bring_active_window_to_front()
self.sleep(0.02)
element.mouse_move()
self.sleep(timeframe)

def hover_and_click(self, hover_selector, click_selector):
if getattr(sb_config, "_cdp_mobile_mode", None):
self.select(click_selector).click()
return
hover_element = self.select(hover_selector)
gui_lock = FileLock(constants.MultiBrowser.PYAUTOGUILOCK)
with gui_lock:
self.bring_active_window_to_front()
self.sleep(0.02)
hover_element.mouse_move()
self.sleep(0.25)
try:
self.click(click_selector, timeout=0.5)
except Exception:
self.select(click_selector, timeout=2).click()

def gui_hover_and_click(self, hover_selector, click_selector):
if getattr(sb_config, "_cdp_mobile_mode", None):
self.select(click_selector).click()
Expand Down
59 changes: 10 additions & 49 deletions seleniumbase/fixtures/base_case.py
Original file line number Diff line number Diff line change
Expand Up @@ -1637,14 +1637,14 @@ def get_partial_link_text_attribute(
def click_link_text(self, link_text, timeout=None):
"""This method clicks link text on a page."""
self.__check_scope()
if self.__is_cdp_swap_needed():
self.cdp.find_element(link_text, timeout=timeout).click()
return
self.__skip_if_esc()
if not timeout:
timeout = settings.SMALL_TIMEOUT
if self.timeout_multiplier and timeout == settings.SMALL_TIMEOUT:
timeout = self.__get_new_timeout(timeout)
if self.__is_cdp_swap_needed():
self.cdp.find_element(link_text, timeout=timeout).click()
return
self.__skip_if_esc()
link_text = self.__get_type_checked_text(link_text)
if self.__is_cdp_swap_needed():
self.cdp.click_link(link_text)
Expand Down Expand Up @@ -2717,7 +2717,7 @@ def hover(self, selector, by="css selector", timeout=None):
original_by = by
selector, by = self.__recalculate_selector(selector, by)
if self.__is_cdp_swap_needed():
self.cdp.gui_hover_element(selector)
self.cdp.hover_element(selector)
return
self.wait_for_element_visible(
original_selector, by=original_by, timeout=timeout
Expand Down Expand Up @@ -2762,7 +2762,7 @@ def hover_and_click(
click_selector, click_by
)
if self.__is_cdp_swap_needed():
self.cdp.gui_hover_and_click(hover_selector, click_selector)
self.cdp.hover_and_click(hover_selector, click_selector)
return
dropdown_element = self.wait_for_element_visible(
original_selector, by=original_by, timeout=timeout
Expand Down Expand Up @@ -9291,81 +9291,42 @@ def input(
self, selector, text, by="css selector", timeout=None, retry=False
):
"""Same as self.update_text()"""
self.__check_scope()
if not timeout:
timeout = settings.LARGE_TIMEOUT
if self.timeout_multiplier and timeout == settings.LARGE_TIMEOUT:
timeout = self.__get_new_timeout(timeout)
selector, by = self.__recalculate_selector(selector, by)
self.update_text(selector, text, by=by, timeout=timeout, retry=retry)

def fill(
self, selector, text, by="css selector", timeout=None, retry=False
):
"""Same as self.update_text()"""
self.__check_scope()
if not timeout:
timeout = settings.LARGE_TIMEOUT
if self.timeout_multiplier and timeout == settings.LARGE_TIMEOUT:
timeout = self.__get_new_timeout(timeout)
selector, by = self.__recalculate_selector(selector, by)
self.update_text(selector, text, by=by, timeout=timeout, retry=retry)

def write(
self, selector, text, by="css selector", timeout=None, retry=False
):
"""Same as self.update_text()"""
self.__check_scope()
if not timeout:
timeout = settings.LARGE_TIMEOUT
if self.timeout_multiplier and timeout == settings.LARGE_TIMEOUT:
timeout = self.__get_new_timeout(timeout)
selector, by = self.__recalculate_selector(selector, by)
self.update_text(selector, text, by=by, timeout=timeout, retry=retry)

def click_link(self, link_text, timeout=None):
"""Same as self.click_link_text()"""
self.__check_scope()
if not timeout:
timeout = settings.SMALL_TIMEOUT
if self.timeout_multiplier and timeout == settings.SMALL_TIMEOUT:
timeout = self.__get_new_timeout(timeout)
self.click_link_text(link_text, timeout=timeout)

def click_partial_link(self, partial_link_text, timeout=None):
"""Same as self.click_partial_link_text()"""
self.__check_scope()
if not timeout:
timeout = settings.SMALL_TIMEOUT
if self.timeout_multiplier and timeout == settings.SMALL_TIMEOUT:
timeout = self.__get_new_timeout(timeout)
self.click_partial_link_text(partial_link_text, timeout=timeout)

def right_click(self, selector, by="css selector", timeout=None):
"""Same as self.context_click()"""
self.__check_scope()
if not timeout:
timeout = settings.SMALL_TIMEOUT
if self.timeout_multiplier and timeout == settings.SMALL_TIMEOUT:
timeout = self.__get_new_timeout(timeout)
self.context_click(selector, by=by, timeout=timeout)

def hover_element(self, selector, by="css selector", timeout=None):
"""Same as self.hover()"""
return self.hover(selector, by=by, timeout=timeout)

def hover_on_element(self, selector, by="css selector", timeout=None):
"""Same as self.hover()"""
self.__check_scope()
if not timeout:
timeout = settings.SMALL_TIMEOUT
if self.timeout_multiplier and timeout == settings.SMALL_TIMEOUT:
timeout = self.__get_new_timeout(timeout)
return self.hover(selector, by=by, timeout=timeout)

def hover_over_element(self, selector, by="css selector", timeout=None):
"""Same as self.hover()"""
self.__check_scope()
if not timeout:
timeout = settings.SMALL_TIMEOUT
if self.timeout_multiplier and timeout == settings.SMALL_TIMEOUT:
timeout = self.__get_new_timeout(timeout)
return self.hover(selector, by=by, timeout=timeout)

def wait_for_element_visible(
Expand Down
3 changes: 2 additions & 1 deletion seleniumbase/undetected/cdp_driver/config.py
Original file line number Diff line number Diff line change
Expand Up @@ -207,6 +207,7 @@ def __init__(
"--disable-top-sites",
"--disable-translate",
"--dns-prefetch-disable",
"--disable-component-update",
"--disable-renderer-backgrounding",
"--disable-dev-shm-usage",
]
Expand Down Expand Up @@ -264,7 +265,7 @@ def __call__(self):
"OptimizationTargetPrediction,OptimizationGuideModelDownloading,"
"SidePanelPinning,UserAgentClientHint,PrivacySandboxSettings4,"
"OptimizationHintsFetching,InterestFeedContentSuggestions,"
"Bluetooth,WebBluetooth,UnifiedWebBluetooth,"
"Bluetooth,WebBluetooth,UnifiedWebBluetooth,ComponentUpdater,"
"DisableLoadExtensionCommandLineSwitch,"
"WebAuthentication,PasskeyAuth"
]
Expand Down
35 changes: 19 additions & 16 deletions seleniumbase/undetected/cdp_driver/element.py
Original file line number Diff line number Diff line change
Expand Up @@ -501,8 +501,8 @@ async def mouse_click_async(
logger.warning("Could not calculate box model for %s", self)
return
logger.debug("Clicking on location: %.2f, %.2f" % center)
await asyncio.gather(
self.flash_async(0.25),
asyncio.create_task(self.flash_async(0.25))
asyncio.create_task(
self._tab.send(
cdp.input_.dispatch_mouse_event(
"mousePressed",
Expand All @@ -514,6 +514,8 @@ async def mouse_click_async(
click_count=1,
)
),
)
asyncio.create_task(
self._tab.send(
cdp.input_.dispatch_mouse_event(
"mouseReleased",
Expand Down Expand Up @@ -558,11 +560,13 @@ async def mouse_click_with_offset_async(
logger.debug("Clicking on location: %.2f, %.2f" % center_pos)
else:
logger.debug("Clicking on location: %.2f, %.2f" % (x_pos, y_pos))
await asyncio.gather(
asyncio.create_task(
self.flash_async(
x_offset=x_offset - int(width / 2),
y_offset=y_offset - int(height / 2),
x_offset=x_offset - (width / 2),
y_offset=y_offset - (height / 2),
),
)
asyncio.create_task(
self._tab.send(
cdp.input_.dispatch_mouse_event(
"mousePressed",
Expand All @@ -573,7 +577,9 @@ async def mouse_click_with_offset_async(
buttons=buttons,
click_count=1,
)
),
)
)
asyncio.create_task(
self._tab.send(
cdp.input_.dispatch_mouse_event(
"mouseReleased",
Expand Down Expand Up @@ -602,16 +608,13 @@ async def mouse_move_async(self):
*center,
self,
)
await self._tab.send(
cdp.input_.dispatch_mouse_event(
"mouseMoved", x=center[0], y=center[1]
)
)
await self._tab.sleep(0.05)
await self._tab.send(
cdp.input_.dispatch_mouse_event(
"mouseReleased", x=center[0], y=center[1]
)
await asyncio.gather(
self._tab.send(
cdp.input_.dispatch_mouse_event(
"mouseMoved", x=center[0], y=center[1]
)
),
self._tab.sleep(0.05),
)

async def mouse_drag_async(
Expand Down