seleniumbase 4.44.0__tar.gz → 4.44.2__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (161) hide show
  1. {seleniumbase-4.44.0/seleniumbase.egg-info → seleniumbase-4.44.2}/PKG-INFO +2 -2
  2. {seleniumbase-4.44.0 → seleniumbase-4.44.2}/seleniumbase/__version__.py +1 -1
  3. {seleniumbase-4.44.0 → seleniumbase-4.44.2}/seleniumbase/core/browser_launcher.py +13 -5
  4. {seleniumbase-4.44.0 → seleniumbase-4.44.2}/seleniumbase/core/detect_b_ver.py +39 -8
  5. {seleniumbase-4.44.0 → seleniumbase-4.44.2}/seleniumbase/core/sb_cdp.py +99 -27
  6. {seleniumbase-4.44.0 → seleniumbase-4.44.2}/seleniumbase/fixtures/base_case.py +7 -0
  7. {seleniumbase-4.44.0 → seleniumbase-4.44.2}/seleniumbase/undetected/cdp_driver/connection.py +2 -3
  8. {seleniumbase-4.44.0 → seleniumbase-4.44.2}/seleniumbase/undetected/cdp_driver/element.py +75 -18
  9. {seleniumbase-4.44.0 → seleniumbase-4.44.2/seleniumbase.egg-info}/PKG-INFO +2 -2
  10. {seleniumbase-4.44.0 → seleniumbase-4.44.2}/seleniumbase.egg-info/requires.txt +1 -1
  11. {seleniumbase-4.44.0 → seleniumbase-4.44.2}/setup.py +1 -1
  12. {seleniumbase-4.44.0 → seleniumbase-4.44.2}/.gitignore +0 -0
  13. {seleniumbase-4.44.0 → seleniumbase-4.44.2}/LICENSE +0 -0
  14. {seleniumbase-4.44.0 → seleniumbase-4.44.2}/MANIFEST.in +0 -0
  15. {seleniumbase-4.44.0 → seleniumbase-4.44.2}/README.md +0 -0
  16. {seleniumbase-4.44.0 → seleniumbase-4.44.2}/install.sh +0 -0
  17. {seleniumbase-4.44.0 → seleniumbase-4.44.2}/pyproject.toml +0 -0
  18. {seleniumbase-4.44.0 → seleniumbase-4.44.2}/pytest.ini +0 -0
  19. {seleniumbase-4.44.0 → seleniumbase-4.44.2}/requirements.txt +0 -0
  20. {seleniumbase-4.44.0 → seleniumbase-4.44.2}/sbase/__init__.py +0 -0
  21. {seleniumbase-4.44.0 → seleniumbase-4.44.2}/sbase/__main__.py +0 -0
  22. {seleniumbase-4.44.0 → seleniumbase-4.44.2}/sbase/steps.py +0 -0
  23. {seleniumbase-4.44.0 → seleniumbase-4.44.2}/seleniumbase/__init__.py +0 -0
  24. {seleniumbase-4.44.0 → seleniumbase-4.44.2}/seleniumbase/__main__.py +0 -0
  25. {seleniumbase-4.44.0 → seleniumbase-4.44.2}/seleniumbase/behave/__init__.py +0 -0
  26. {seleniumbase-4.44.0 → seleniumbase-4.44.2}/seleniumbase/behave/behave_helper.py +0 -0
  27. {seleniumbase-4.44.0 → seleniumbase-4.44.2}/seleniumbase/behave/behave_sb.py +0 -0
  28. {seleniumbase-4.44.0 → seleniumbase-4.44.2}/seleniumbase/behave/steps.py +0 -0
  29. {seleniumbase-4.44.0 → seleniumbase-4.44.2}/seleniumbase/common/__init__.py +0 -0
  30. {seleniumbase-4.44.0 → seleniumbase-4.44.2}/seleniumbase/common/decorators.py +0 -0
  31. {seleniumbase-4.44.0 → seleniumbase-4.44.2}/seleniumbase/common/encryption.py +0 -0
  32. {seleniumbase-4.44.0 → seleniumbase-4.44.2}/seleniumbase/common/exceptions.py +0 -0
  33. {seleniumbase-4.44.0 → seleniumbase-4.44.2}/seleniumbase/common/obfuscate.py +0 -0
  34. {seleniumbase-4.44.0 → seleniumbase-4.44.2}/seleniumbase/common/unobfuscate.py +0 -0
  35. {seleniumbase-4.44.0 → seleniumbase-4.44.2}/seleniumbase/config/__init__.py +0 -0
  36. {seleniumbase-4.44.0 → seleniumbase-4.44.2}/seleniumbase/config/ad_block_list.py +0 -0
  37. {seleniumbase-4.44.0 → seleniumbase-4.44.2}/seleniumbase/config/proxy_list.py +0 -0
  38. {seleniumbase-4.44.0 → seleniumbase-4.44.2}/seleniumbase/config/settings.py +0 -0
  39. {seleniumbase-4.44.0 → seleniumbase-4.44.2}/seleniumbase/console_scripts/__init__.py +0 -0
  40. {seleniumbase-4.44.0 → seleniumbase-4.44.2}/seleniumbase/console_scripts/logo_helper.py +0 -0
  41. {seleniumbase-4.44.0 → seleniumbase-4.44.2}/seleniumbase/console_scripts/rich_helper.py +0 -0
  42. {seleniumbase-4.44.0 → seleniumbase-4.44.2}/seleniumbase/console_scripts/run.py +0 -0
  43. {seleniumbase-4.44.0 → seleniumbase-4.44.2}/seleniumbase/console_scripts/sb_behave_gui.py +0 -0
  44. {seleniumbase-4.44.0 → seleniumbase-4.44.2}/seleniumbase/console_scripts/sb_caseplans.py +0 -0
  45. {seleniumbase-4.44.0 → seleniumbase-4.44.2}/seleniumbase/console_scripts/sb_commander.py +0 -0
  46. {seleniumbase-4.44.0 → seleniumbase-4.44.2}/seleniumbase/console_scripts/sb_install.py +0 -0
  47. {seleniumbase-4.44.0 → seleniumbase-4.44.2}/seleniumbase/console_scripts/sb_mkchart.py +0 -0
  48. {seleniumbase-4.44.0 → seleniumbase-4.44.2}/seleniumbase/console_scripts/sb_mkdir.py +0 -0
  49. {seleniumbase-4.44.0 → seleniumbase-4.44.2}/seleniumbase/console_scripts/sb_mkfile.py +0 -0
  50. {seleniumbase-4.44.0 → seleniumbase-4.44.2}/seleniumbase/console_scripts/sb_mkpres.py +0 -0
  51. {seleniumbase-4.44.0 → seleniumbase-4.44.2}/seleniumbase/console_scripts/sb_mkrec.py +0 -0
  52. {seleniumbase-4.44.0 → seleniumbase-4.44.2}/seleniumbase/console_scripts/sb_objectify.py +0 -0
  53. {seleniumbase-4.44.0 → seleniumbase-4.44.2}/seleniumbase/console_scripts/sb_print.py +0 -0
  54. {seleniumbase-4.44.0 → seleniumbase-4.44.2}/seleniumbase/console_scripts/sb_recorder.py +0 -0
  55. {seleniumbase-4.44.0 → seleniumbase-4.44.2}/seleniumbase/core/__init__.py +0 -0
  56. {seleniumbase-4.44.0 → seleniumbase-4.44.2}/seleniumbase/core/application_manager.py +0 -0
  57. {seleniumbase-4.44.0 → seleniumbase-4.44.2}/seleniumbase/core/capabilities_parser.py +0 -0
  58. {seleniumbase-4.44.0 → seleniumbase-4.44.2}/seleniumbase/core/colored_traceback.py +0 -0
  59. {seleniumbase-4.44.0 → seleniumbase-4.44.2}/seleniumbase/core/create_db_tables.sql +0 -0
  60. {seleniumbase-4.44.0 → seleniumbase-4.44.2}/seleniumbase/core/download_helper.py +0 -0
  61. {seleniumbase-4.44.0 → seleniumbase-4.44.2}/seleniumbase/core/encoded_images.py +0 -0
  62. {seleniumbase-4.44.0 → seleniumbase-4.44.2}/seleniumbase/core/jqc_helper.py +0 -0
  63. {seleniumbase-4.44.0 → seleniumbase-4.44.2}/seleniumbase/core/log_helper.py +0 -0
  64. {seleniumbase-4.44.0 → seleniumbase-4.44.2}/seleniumbase/core/mysql.py +0 -0
  65. {seleniumbase-4.44.0 → seleniumbase-4.44.2}/seleniumbase/core/proxy_helper.py +0 -0
  66. {seleniumbase-4.44.0 → seleniumbase-4.44.2}/seleniumbase/core/recorder_helper.py +0 -0
  67. {seleniumbase-4.44.0 → seleniumbase-4.44.2}/seleniumbase/core/report_helper.py +0 -0
  68. {seleniumbase-4.44.0 → seleniumbase-4.44.2}/seleniumbase/core/s3_manager.py +0 -0
  69. {seleniumbase-4.44.0 → seleniumbase-4.44.2}/seleniumbase/core/sb_driver.py +0 -0
  70. {seleniumbase-4.44.0 → seleniumbase-4.44.2}/seleniumbase/core/session_helper.py +0 -0
  71. {seleniumbase-4.44.0 → seleniumbase-4.44.2}/seleniumbase/core/settings_parser.py +0 -0
  72. {seleniumbase-4.44.0 → seleniumbase-4.44.2}/seleniumbase/core/style_sheet.py +0 -0
  73. {seleniumbase-4.44.0 → seleniumbase-4.44.2}/seleniumbase/core/testcase_manager.py +0 -0
  74. {seleniumbase-4.44.0 → seleniumbase-4.44.2}/seleniumbase/core/tour_helper.py +0 -0
  75. {seleniumbase-4.44.0 → seleniumbase-4.44.2}/seleniumbase/core/visual_helper.py +0 -0
  76. {seleniumbase-4.44.0 → seleniumbase-4.44.2}/seleniumbase/drivers/__init__.py +0 -0
  77. {seleniumbase-4.44.0 → seleniumbase-4.44.2}/seleniumbase/drivers/atlas_drivers/__init__.py +0 -0
  78. {seleniumbase-4.44.0 → seleniumbase-4.44.2}/seleniumbase/drivers/brave_drivers/__init__.py +0 -0
  79. {seleniumbase-4.44.0 → seleniumbase-4.44.2}/seleniumbase/drivers/cft_drivers/__init__.py +0 -0
  80. {seleniumbase-4.44.0 → seleniumbase-4.44.2}/seleniumbase/drivers/chs_drivers/__init__.py +0 -0
  81. {seleniumbase-4.44.0 → seleniumbase-4.44.2}/seleniumbase/drivers/comet_drivers/__init__.py +0 -0
  82. {seleniumbase-4.44.0 → seleniumbase-4.44.2}/seleniumbase/drivers/opera_drivers/__init__.py +0 -0
  83. {seleniumbase-4.44.0 → seleniumbase-4.44.2}/seleniumbase/extensions/__init__.py +0 -0
  84. {seleniumbase-4.44.0 → seleniumbase-4.44.2}/seleniumbase/extensions/ad_block.zip +0 -0
  85. {seleniumbase-4.44.0 → seleniumbase-4.44.2}/seleniumbase/extensions/disable_csp.zip +0 -0
  86. {seleniumbase-4.44.0 → seleniumbase-4.44.2}/seleniumbase/extensions/recorder.zip +0 -0
  87. {seleniumbase-4.44.0 → seleniumbase-4.44.2}/seleniumbase/extensions/sbase_ext.zip +0 -0
  88. {seleniumbase-4.44.0 → seleniumbase-4.44.2}/seleniumbase/fixtures/__init__.py +0 -0
  89. {seleniumbase-4.44.0 → seleniumbase-4.44.2}/seleniumbase/fixtures/constants.py +0 -0
  90. {seleniumbase-4.44.0 → seleniumbase-4.44.2}/seleniumbase/fixtures/css_to_xpath.py +0 -0
  91. {seleniumbase-4.44.0 → seleniumbase-4.44.2}/seleniumbase/fixtures/errors.py +0 -0
  92. {seleniumbase-4.44.0 → seleniumbase-4.44.2}/seleniumbase/fixtures/js_utils.py +0 -0
  93. {seleniumbase-4.44.0 → seleniumbase-4.44.2}/seleniumbase/fixtures/page_actions.py +0 -0
  94. {seleniumbase-4.44.0 → seleniumbase-4.44.2}/seleniumbase/fixtures/page_utils.py +0 -0
  95. {seleniumbase-4.44.0 → seleniumbase-4.44.2}/seleniumbase/fixtures/shared_utils.py +0 -0
  96. {seleniumbase-4.44.0 → seleniumbase-4.44.2}/seleniumbase/fixtures/unittest_helper.py +0 -0
  97. {seleniumbase-4.44.0 → seleniumbase-4.44.2}/seleniumbase/fixtures/words.py +0 -0
  98. {seleniumbase-4.44.0 → seleniumbase-4.44.2}/seleniumbase/fixtures/xpath_to_css.py +0 -0
  99. {seleniumbase-4.44.0 → seleniumbase-4.44.2}/seleniumbase/js_code/__init__.py +0 -0
  100. {seleniumbase-4.44.0 → seleniumbase-4.44.2}/seleniumbase/js_code/active_css_js.py +0 -0
  101. {seleniumbase-4.44.0 → seleniumbase-4.44.2}/seleniumbase/js_code/live_js.py +0 -0
  102. {seleniumbase-4.44.0 → seleniumbase-4.44.2}/seleniumbase/js_code/recorder_js.py +0 -0
  103. {seleniumbase-4.44.0 → seleniumbase-4.44.2}/seleniumbase/masterqa/__init__.py +0 -0
  104. {seleniumbase-4.44.0 → seleniumbase-4.44.2}/seleniumbase/masterqa/master_qa.py +0 -0
  105. {seleniumbase-4.44.0 → seleniumbase-4.44.2}/seleniumbase/plugins/__init__.py +0 -0
  106. {seleniumbase-4.44.0 → seleniumbase-4.44.2}/seleniumbase/plugins/base_plugin.py +0 -0
  107. {seleniumbase-4.44.0 → seleniumbase-4.44.2}/seleniumbase/plugins/basic_test_info.py +0 -0
  108. {seleniumbase-4.44.0 → seleniumbase-4.44.2}/seleniumbase/plugins/db_reporting_plugin.py +0 -0
  109. {seleniumbase-4.44.0 → seleniumbase-4.44.2}/seleniumbase/plugins/driver_manager.py +0 -0
  110. {seleniumbase-4.44.0 → seleniumbase-4.44.2}/seleniumbase/plugins/page_source.py +0 -0
  111. {seleniumbase-4.44.0 → seleniumbase-4.44.2}/seleniumbase/plugins/pytest_plugin.py +0 -0
  112. {seleniumbase-4.44.0 → seleniumbase-4.44.2}/seleniumbase/plugins/s3_logging_plugin.py +0 -0
  113. {seleniumbase-4.44.0 → seleniumbase-4.44.2}/seleniumbase/plugins/sb_manager.py +0 -0
  114. {seleniumbase-4.44.0 → seleniumbase-4.44.2}/seleniumbase/plugins/screen_shots.py +0 -0
  115. {seleniumbase-4.44.0 → seleniumbase-4.44.2}/seleniumbase/plugins/selenium_plugin.py +0 -0
  116. {seleniumbase-4.44.0 → seleniumbase-4.44.2}/seleniumbase/resources/__init__.py +0 -0
  117. {seleniumbase-4.44.0 → seleniumbase-4.44.2}/seleniumbase/translate/__init__.py +0 -0
  118. {seleniumbase-4.44.0 → seleniumbase-4.44.2}/seleniumbase/translate/chinese.py +0 -0
  119. {seleniumbase-4.44.0 → seleniumbase-4.44.2}/seleniumbase/translate/dutch.py +0 -0
  120. {seleniumbase-4.44.0 → seleniumbase-4.44.2}/seleniumbase/translate/french.py +0 -0
  121. {seleniumbase-4.44.0 → seleniumbase-4.44.2}/seleniumbase/translate/italian.py +0 -0
  122. {seleniumbase-4.44.0 → seleniumbase-4.44.2}/seleniumbase/translate/japanese.py +0 -0
  123. {seleniumbase-4.44.0 → seleniumbase-4.44.2}/seleniumbase/translate/korean.py +0 -0
  124. {seleniumbase-4.44.0 → seleniumbase-4.44.2}/seleniumbase/translate/master_dict.py +0 -0
  125. {seleniumbase-4.44.0 → seleniumbase-4.44.2}/seleniumbase/translate/portuguese.py +0 -0
  126. {seleniumbase-4.44.0 → seleniumbase-4.44.2}/seleniumbase/translate/russian.py +0 -0
  127. {seleniumbase-4.44.0 → seleniumbase-4.44.2}/seleniumbase/translate/spanish.py +0 -0
  128. {seleniumbase-4.44.0 → seleniumbase-4.44.2}/seleniumbase/translate/translator.py +0 -0
  129. {seleniumbase-4.44.0 → seleniumbase-4.44.2}/seleniumbase/undetected/__init__.py +0 -0
  130. {seleniumbase-4.44.0 → seleniumbase-4.44.2}/seleniumbase/undetected/cdp.py +0 -0
  131. {seleniumbase-4.44.0 → seleniumbase-4.44.2}/seleniumbase/undetected/cdp_driver/__init__.py +0 -0
  132. {seleniumbase-4.44.0 → seleniumbase-4.44.2}/seleniumbase/undetected/cdp_driver/_contradict.py +0 -0
  133. {seleniumbase-4.44.0 → seleniumbase-4.44.2}/seleniumbase/undetected/cdp_driver/browser.py +0 -0
  134. {seleniumbase-4.44.0 → seleniumbase-4.44.2}/seleniumbase/undetected/cdp_driver/cdp_util.py +0 -0
  135. {seleniumbase-4.44.0 → seleniumbase-4.44.2}/seleniumbase/undetected/cdp_driver/config.py +0 -0
  136. {seleniumbase-4.44.0 → seleniumbase-4.44.2}/seleniumbase/undetected/cdp_driver/tab.py +0 -0
  137. {seleniumbase-4.44.0 → seleniumbase-4.44.2}/seleniumbase/undetected/dprocess.py +0 -0
  138. {seleniumbase-4.44.0 → seleniumbase-4.44.2}/seleniumbase/undetected/options.py +0 -0
  139. {seleniumbase-4.44.0 → seleniumbase-4.44.2}/seleniumbase/undetected/patcher.py +0 -0
  140. {seleniumbase-4.44.0 → seleniumbase-4.44.2}/seleniumbase/undetected/reactor.py +0 -0
  141. {seleniumbase-4.44.0 → seleniumbase-4.44.2}/seleniumbase/undetected/webelement.py +0 -0
  142. {seleniumbase-4.44.0 → seleniumbase-4.44.2}/seleniumbase/utilities/__init__.py +0 -0
  143. {seleniumbase-4.44.0 → seleniumbase-4.44.2}/seleniumbase/utilities/selenium_grid/__init__.py +0 -0
  144. {seleniumbase-4.44.0 → seleniumbase-4.44.2}/seleniumbase/utilities/selenium_grid/download_selenium_server.py +0 -0
  145. {seleniumbase-4.44.0 → seleniumbase-4.44.2}/seleniumbase/utilities/selenium_grid/font_color +0 -0
  146. {seleniumbase-4.44.0 → seleniumbase-4.44.2}/seleniumbase/utilities/selenium_grid/grid-hub +0 -0
  147. {seleniumbase-4.44.0 → seleniumbase-4.44.2}/seleniumbase/utilities/selenium_grid/grid-node +0 -0
  148. {seleniumbase-4.44.0 → seleniumbase-4.44.2}/seleniumbase/utilities/selenium_grid/grid_hub.py +0 -0
  149. {seleniumbase-4.44.0 → seleniumbase-4.44.2}/seleniumbase/utilities/selenium_grid/grid_node.py +0 -0
  150. {seleniumbase-4.44.0 → seleniumbase-4.44.2}/seleniumbase/utilities/selenium_grid/register-grid-node.bat +0 -0
  151. {seleniumbase-4.44.0 → seleniumbase-4.44.2}/seleniumbase/utilities/selenium_grid/register-grid-node.sh +0 -0
  152. {seleniumbase-4.44.0 → seleniumbase-4.44.2}/seleniumbase/utilities/selenium_grid/start-grid-hub.bat +0 -0
  153. {seleniumbase-4.44.0 → seleniumbase-4.44.2}/seleniumbase/utilities/selenium_grid/start-grid-hub.sh +0 -0
  154. {seleniumbase-4.44.0 → seleniumbase-4.44.2}/seleniumbase/utilities/selenium_ide/__init__.py +0 -0
  155. {seleniumbase-4.44.0 → seleniumbase-4.44.2}/seleniumbase/utilities/selenium_ide/convert_ide.py +0 -0
  156. {seleniumbase-4.44.0 → seleniumbase-4.44.2}/seleniumbase.egg-info/SOURCES.txt +0 -0
  157. {seleniumbase-4.44.0 → seleniumbase-4.44.2}/seleniumbase.egg-info/dependency_links.txt +0 -0
  158. {seleniumbase-4.44.0 → seleniumbase-4.44.2}/seleniumbase.egg-info/entry_points.txt +0 -0
  159. {seleniumbase-4.44.0 → seleniumbase-4.44.2}/seleniumbase.egg-info/top_level.txt +0 -0
  160. {seleniumbase-4.44.0 → seleniumbase-4.44.2}/setup.cfg +0 -0
  161. {seleniumbase-4.44.0 → seleniumbase-4.44.2}/virtualenv_install.sh +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: seleniumbase
3
- Version: 4.44.0
3
+ Version: 4.44.2
4
4
  Summary: A complete web automation framework for end-to-end testing.
5
5
  Home-page: https://github.com/seleniumbase/SeleniumBase
6
6
  Author: Michael Mintz
@@ -186,7 +186,7 @@ Requires-Dist: pip-system-certs==4.0; platform_system == "Windows" and extra ==
186
186
  Provides-Extra: proxy
187
187
  Requires-Dist: proxy.py==2.4.3; extra == "proxy"
188
188
  Provides-Extra: psutil
189
- Requires-Dist: psutil==7.1.0; extra == "psutil"
189
+ Requires-Dist: psutil==7.1.2; extra == "psutil"
190
190
  Provides-Extra: pyautogui
191
191
  Requires-Dist: PyAutoGUI>=0.9.54; platform_system != "Linux" and extra == "pyautogui"
192
192
  Provides-Extra: selenium-stealth
@@ -1,2 +1,2 @@
1
1
  # seleniumbase package
2
- __version__ = "4.44.0"
2
+ __version__ = "4.44.2"
@@ -764,6 +764,7 @@ def uc_open_with_cdp_mode(driver, url=None, **kwargs):
764
764
  cdp.click_active_element = CDPM.click_active_element
765
765
  cdp.click_if_visible = CDPM.click_if_visible
766
766
  cdp.click_visible_elements = CDPM.click_visible_elements
767
+ cdp.click_with_offset = CDPM.click_with_offset
767
768
  cdp.mouse_click = CDPM.mouse_click
768
769
  cdp.get_parent = CDPM.get_parent
769
770
  cdp.remove_element = CDPM.remove_element
@@ -793,11 +794,13 @@ def uc_open_with_cdp_mode(driver, url=None, **kwargs):
793
794
  cdp.set_attributes = CDPM.set_attributes
794
795
  cdp.is_attribute_present = CDPM.is_attribute_present
795
796
  cdp.is_online = CDPM.is_online
797
+ cdp.solve_captcha = CDPM.solve_captcha
796
798
  cdp.gui_press_key = CDPM.gui_press_key
797
799
  cdp.gui_press_keys = CDPM.gui_press_keys
798
800
  cdp.gui_write = CDPM.gui_write
799
801
  cdp.gui_click_x_y = CDPM.gui_click_x_y
800
802
  cdp.gui_click_element = CDPM.gui_click_element
803
+ cdp.gui_click_with_offset = CDPM.gui_click_with_offset
801
804
  cdp.gui_click_captcha = CDPM.gui_click_captcha
802
805
  cdp.gui_drag_drop_points = CDPM.gui_drag_drop_points
803
806
  cdp.gui_drag_and_drop = CDPM.gui_drag_and_drop
@@ -2618,15 +2621,20 @@ def _set_chrome_options(
2618
2621
  if is_using_uc(undetectable, browser_name):
2619
2622
  chrome_options.add_argument("--disable-application-cache")
2620
2623
  chrome_options.add_argument("--disable-setuid-sandbox")
2621
- if not binary_location:
2624
+ if not binary_location:
2625
+ if os.path.exists("/bin/google-chrome"):
2626
+ binary_location = "/bin/google-chrome"
2627
+ elif os.path.exists("/usr/bin/google-chrome-stable"):
2628
+ binary_location = "/usr/bin/google-chrome-stable"
2629
+ elif os.path.exists("/usr/bin/google-chrome"):
2630
+ binary_location = "/usr/bin/google-chrome"
2631
+ elif os.path.exists("/usr/bin/google-chrome-stable"):
2632
+ binary_location = "/usr/bin/google-chrome-stable"
2633
+ else:
2622
2634
  br_app = "google-chrome"
2623
2635
  binary_loc = detect_b_ver.get_binary_location(br_app, True)
2624
2636
  if os.path.exists(binary_loc):
2625
2637
  binary_location = binary_loc
2626
- elif os.path.exists("/usr/bin/google-chrome-stable"):
2627
- binary_location = "/usr/bin/google-chrome-stable"
2628
- elif os.path.exists("/usr/bin/google-chrome"):
2629
- binary_location = "/usr/bin/google-chrome"
2630
2638
  extra_disabled_features = []
2631
2639
  if chromium_arg:
2632
2640
  # Can be a comma-separated list of Chromium args or a list
@@ -105,10 +105,22 @@ def chrome_on_linux_path(chromium_ok=False, browser_type=None):
105
105
  return ""
106
106
  if os_name() != OSType.LINUX:
107
107
  return ""
108
- paths = ["/bin/google-chrome", "/bin/google-chrome-stable"]
108
+ paths = [
109
+ "/bin/google-chrome",
110
+ "/bin/google-chrome-stable",
111
+ "/usr/bin/google-chrome",
112
+ "/usr/bin/google-chrome-stable"
113
+ ]
109
114
  for path in paths:
110
- if os.path.exists(path) and os.access(path, os.X_OK):
111
- return path
115
+ try:
116
+ if (
117
+ os.path.exists(path)
118
+ and os.access(path, os.R_OK)
119
+ and os.access(path, os.X_OK)
120
+ ):
121
+ return path
122
+ except Exception:
123
+ pass
112
124
  paths = os.environ["PATH"].split(os.pathsep)
113
125
  binaries = []
114
126
  binaries.append("google-chrome")
@@ -122,13 +134,32 @@ def chrome_on_linux_path(chromium_ok=False, browser_type=None):
122
134
  for binary in binaries:
123
135
  for path in paths:
124
136
  full_path = os.path.join(path, binary)
125
- if os.path.exists(full_path) and os.access(full_path, os.X_OK):
126
- return full_path
137
+ try:
138
+ if (
139
+ os.path.exists(full_path)
140
+ and os.access(full_path, os.R_OK)
141
+ and os.access(full_path, os.X_OK)
142
+ ):
143
+ return full_path
144
+ except Exception:
145
+ pass
127
146
  if chromium_ok:
128
- paths = ["/bin/chromium", "/bin/chromium-browser"]
147
+ paths = [
148
+ "/bin/chromium",
149
+ "/bin/chromium-browser",
150
+ "/usr/bin/chromium",
151
+ "/usr/bin/chromium-browser"
152
+ ]
129
153
  for path in paths:
130
- if os.path.exists(path) and os.access(path, os.X_OK):
131
- return path
154
+ try:
155
+ if (
156
+ os.path.exists(path)
157
+ and os.access(path, os.R_OK)
158
+ and os.access(path, os.X_OK)
159
+ ):
160
+ return path
161
+ except Exception:
162
+ pass
132
163
  return "/usr/bin/google-chrome"
133
164
 
134
165
 
@@ -64,6 +64,11 @@ class CDPMethods():
64
64
  )
65
65
  element.highlight_overlay = lambda: self.__highlight_overlay(element)
66
66
  element.mouse_click = lambda: self.__mouse_click(element)
67
+ element.click_with_offset = (
68
+ lambda *args, **kwargs: self.__mouse_click_with_offset_async(
69
+ element, *args, **kwargs
70
+ )
71
+ )
67
72
  element.mouse_drag = (
68
73
  lambda destination: self.__mouse_drag(element, destination)
69
74
  )
@@ -447,6 +452,15 @@ class CDPMethods():
447
452
  self.loop.run_until_complete(self.page.wait())
448
453
  return result
449
454
 
455
+ def __mouse_click_with_offset_async(self, element, *args, **kwargs):
456
+ result = (
457
+ self.loop.run_until_complete(
458
+ element.mouse_click_with_offset_async(*args, **kwargs)
459
+ )
460
+ )
461
+ self.loop.run_until_complete(self.page.wait())
462
+ return result
463
+
450
464
  def __mouse_drag(self, element, destination):
451
465
  return (
452
466
  self.loop.run_until_complete(element.mouse_drag_async(destination))
@@ -689,10 +703,16 @@ class CDPMethods():
689
703
  self.__slow_mode_pause_if_set()
690
704
  element = self.find_element(selector, timeout=timeout)
691
705
  element.scroll_into_view()
692
- if element.tag_name == "div" or element.tag_name == "input":
693
- element.mouse_click() # Simulated click (not PyAutoGUI)
706
+ tag_name = element.tag_name
707
+ if tag_name:
708
+ tag_name = tag_name.lower().strip()
709
+ if (
710
+ tag_name in ["a", "button", "canvas", "div", "input", "li", "span"]
711
+ and "contains(" not in selector
712
+ ):
713
+ element.mouse_click() # Simulated click (NOT PyAutoGUI)
694
714
  else:
695
- element.click()
715
+ element.click() # Standard CDP click
696
716
  self.__slow_mode_pause_if_set()
697
717
  self.loop.run_until_complete(self.page.wait())
698
718
 
@@ -738,7 +758,7 @@ class CDPMethods():
738
758
  element.scroll_into_view()
739
759
  element.click()
740
760
  click_count += 1
741
- time.sleep(0.042)
761
+ time.sleep(0.044)
742
762
  self.__slow_mode_pause_if_set()
743
763
  self.loop.run_until_complete(self.page.wait())
744
764
  except Exception:
@@ -1757,11 +1777,32 @@ class CDPMethods():
1757
1777
  self.__slow_mode_pause_if_set()
1758
1778
  self.loop.run_until_complete(self.page.wait())
1759
1779
 
1760
- def _on_a_cf_turnstile_page(self):
1761
- time.sleep(0.042)
1762
- source = self.get_page_source()
1780
+ def gui_click_with_offset(
1781
+ self, selector, x, y, timeframe=0.25, center=False
1782
+ ):
1783
+ """Click an element at an {X,Y}-offset location.
1784
+ {0,0} is the top-left corner of the element.
1785
+ If center==True, {0,0} becomes the center of the element.
1786
+ The timeframe is the time spent moving the mouse."""
1787
+ if center:
1788
+ px, py = self.get_gui_element_center(selector)
1789
+ self.gui_click_x_y(px + x, py + y, timeframe=timeframe)
1790
+ else:
1791
+ element_rect = self.get_gui_element_rect(selector)
1792
+ px = element_rect["x"]
1793
+ py = element_rect["y"]
1794
+ self.gui_click_x_y(px + x, py + y, timeframe=timeframe)
1795
+
1796
+ def click_with_offset(self, selector, x, y, center=False):
1797
+ element = self.find_element(selector)
1798
+ element.scroll_into_view()
1799
+ element.click_with_offset(x=x, y=y, center=center)
1800
+ self.__slow_mode_pause_if_set()
1801
+ self.loop.run_until_complete(self.page.wait())
1802
+
1803
+ def _on_a_cf_turnstile_page(self, source=None):
1763
1804
  if not source or len(source) < 400:
1764
- time.sleep(0.22)
1805
+ time.sleep(0.2)
1765
1806
  source = self.get_page_source()
1766
1807
  if (
1767
1808
  'data-callback="onCaptchaSuccess"' in source
@@ -1773,20 +1814,21 @@ class CDPMethods():
1773
1814
  return True
1774
1815
  return False
1775
1816
 
1776
- def _on_a_g_recaptcha_page(self):
1777
- time.sleep(0.042)
1778
- source = self.get_page_source()
1817
+ def _on_a_g_recaptcha_page(self, source=None):
1779
1818
  if not source or len(source) < 400:
1780
- time.sleep(0.22)
1819
+ time.sleep(0.2)
1781
1820
  source = self.get_page_source()
1782
1821
  if (
1783
1822
  'id="recaptcha-token"' in source
1784
1823
  or 'title="reCAPTCHA"' in source
1785
1824
  ):
1786
1825
  return True
1826
+ elif "/recaptcha/api.js" in source:
1827
+ time.sleep(1.6) # Still loading
1828
+ return True
1787
1829
  return False
1788
1830
 
1789
- def __gui_click_recaptcha(self):
1831
+ def __gui_click_recaptcha(self, use_cdp=False):
1790
1832
  selector = None
1791
1833
  if self.is_element_visible('iframe[title="reCAPTCHA"]'):
1792
1834
  selector = 'iframe[title="reCAPTCHA"]'
@@ -1797,19 +1839,39 @@ class CDPMethods():
1797
1839
  element_rect = self.get_gui_element_rect(selector, timeout=1)
1798
1840
  e_x = element_rect["x"]
1799
1841
  e_y = element_rect["y"]
1800
- x = e_x + 29
1801
- y = e_y + 35
1842
+ x_offset = 26
1843
+ y_offset = 35
1844
+ if shared_utils.is_windows():
1845
+ x_offset = 29
1846
+ x = e_x + x_offset
1847
+ y = e_y + y_offset
1802
1848
  sb_config._saved_cf_x_y = (x, y)
1803
1849
  time.sleep(0.08)
1804
- self.gui_click_x_y(x, y)
1850
+ if use_cdp:
1851
+ self.sleep(0.03)
1852
+ gui_lock = FileLock(constants.MultiBrowser.PYAUTOGUILOCK)
1853
+ with gui_lock: # Prevent issues with multiple processes
1854
+ self.bring_active_window_to_front()
1855
+ time.sleep(0.056)
1856
+ self.click_with_offset(selector, x_offset, y_offset)
1857
+ time.sleep(0.056)
1858
+ else:
1859
+ self.gui_click_x_y(x, y)
1860
+
1861
+ def solve_captcha(self):
1862
+ self.__click_captcha(use_cdp=True)
1805
1863
 
1806
1864
  def gui_click_captcha(self):
1807
- if self._on_a_cf_turnstile_page():
1808
- pass
1809
- elif self._on_a_g_recaptcha_page():
1810
- self.__gui_click_recaptcha()
1865
+ self.__click_captcha(use_cdp=False)
1866
+
1867
+ def __click_captcha(self, use_cdp=False):
1868
+ """Uses PyAutoGUI unless use_cdp == True"""
1869
+ self.sleep(0.056)
1870
+ source = self.get_page_source()
1871
+ if self._on_a_g_recaptcha_page(source):
1872
+ self.__gui_click_recaptcha(use_cdp)
1811
1873
  return
1812
- else:
1874
+ elif not self._on_a_cf_turnstile_page(source):
1813
1875
  return
1814
1876
  selector = None
1815
1877
  if (
@@ -1970,14 +2032,24 @@ class CDPMethods():
1970
2032
  element_rect = self.get_gui_element_rect(selector, timeout=1)
1971
2033
  e_x = element_rect["x"]
1972
2034
  e_y = element_rect["y"]
1973
- x = e_x + 32
1974
- if not shared_utils.is_windows():
1975
- y = e_y + 32
1976
- else:
1977
- y = e_y + 28
2035
+ x_offset = 32
2036
+ y_offset = 32
2037
+ if shared_utils.is_windows():
2038
+ y_offset = 28
2039
+ x = e_x + x_offset
2040
+ y = e_y + y_offset
1978
2041
  sb_config._saved_cf_x_y = (x, y)
1979
2042
  time.sleep(0.08)
1980
- self.gui_click_x_y(x, y)
2043
+ if use_cdp:
2044
+ self.sleep(0.03)
2045
+ gui_lock = FileLock(constants.MultiBrowser.PYAUTOGUILOCK)
2046
+ with gui_lock: # Prevent issues with multiple processes
2047
+ self.bring_active_window_to_front()
2048
+ time.sleep(0.056)
2049
+ self.click_with_offset(selector, x_offset, y_offset)
2050
+ time.sleep(0.056)
2051
+ else:
2052
+ self.gui_click_x_y(x, y)
1981
2053
 
1982
2054
  def __gui_drag_drop(self, x1, y1, x2, y2, timeframe=0.25, uc_lock=False):
1983
2055
  self.__install_pyautogui_if_missing()
@@ -5008,6 +5008,9 @@ class BaseCase(unittest.TestCase):
5008
5008
  self.get_new_driver(undetectable=True)
5009
5009
  self.driver.uc_open_with_cdp_mode(url, **kwargs)
5010
5010
  self.cdp = self.driver.cdp
5011
+ if hasattr(self.cdp, "solve_captcha"):
5012
+ self.solve_captcha = self.cdp.solve_captcha
5013
+ self.undetectable = True
5011
5014
 
5012
5015
  def activate_recorder(self):
5013
5016
  """Activate Recorder Mode on the current tab/window.
@@ -11452,6 +11455,7 @@ class BaseCase(unittest.TestCase):
11452
11455
  if cdp_swap_needed:
11453
11456
  if not self.cdp:
11454
11457
  self.cdp = self.driver.cdp
11458
+ self.undetectable = True
11455
11459
  return True
11456
11460
  else:
11457
11461
  return False
@@ -13970,6 +13974,9 @@ class BaseCase(unittest.TestCase):
13970
13974
  timeout=None,
13971
13975
  center=None,
13972
13976
  ):
13977
+ if self.__is_cdp_swap_needed():
13978
+ self.cdp.click_with_offset(selector, x, y, center=center)
13979
+ return
13973
13980
  self.wait_for_ready_state_complete()
13974
13981
  if self.__needs_minimum_wait():
13975
13982
  time.sleep(0.14)
@@ -7,7 +7,6 @@ import json
7
7
  import logging
8
8
  import sys
9
9
  import types
10
- from asyncio import iscoroutine, iscoroutinefunction
11
10
  from typing import (
12
11
  Optional,
13
12
  Generator,
@@ -666,8 +665,8 @@ class Listener:
666
665
  for callback in callbacks:
667
666
  try:
668
667
  if (
669
- iscoroutinefunction(callback)
670
- or iscoroutine(callback)
668
+ inspect.iscoroutinefunction(callback)
669
+ or inspect.iscoroutine(callback)
671
670
  ):
672
671
  try:
673
672
  await callback(event, self.connection)
@@ -484,17 +484,14 @@ class Element:
484
484
  buttons: typing.Optional[int] = 1,
485
485
  modifiers: typing.Optional[int] = 0,
486
486
  hold: bool = False,
487
- _until_event: typing.Optional[type] = None,
488
487
  ):
489
488
  """
490
489
  Native click (on element).
491
- Note: This likely does not work at the moment. Use click() instead.
492
490
  :param button: str (default = "left")
493
491
  :param buttons: which button (default 1 = left)
494
492
  :param modifiers: *(Optional)*
495
493
  Bit field representing pressed modifier keys.
496
494
  Alt=1, Ctrl=2, Meta/Command=4, Shift=8 (default: 0).
497
- :param _until_event: Internal. Event to wait for before returning.
498
495
  """
499
496
  try:
500
497
  center = (await self.get_position_async()).center
@@ -505,6 +502,7 @@ class Element:
505
502
  return
506
503
  logger.debug("Clicking on location: %.2f, %.2f" % center)
507
504
  await asyncio.gather(
505
+ self.flash_async(0.25),
508
506
  self._tab.send(
509
507
  cdp.input_.dispatch_mouse_event(
510
508
  "mousePressed",
@@ -528,10 +526,66 @@ class Element:
528
526
  )
529
527
  ),
530
528
  )
529
+
530
+ async def mouse_click_with_offset_async(
531
+ self,
532
+ x: typing.Union[float, int],
533
+ y: typing.Union[float, int],
534
+ center: bool = False,
535
+ button: str = "left",
536
+ buttons: typing.Optional[int] = 1,
537
+ modifiers: typing.Optional[int] = 0,
538
+ ):
539
+ x_offset = int(x)
540
+ y_offset = int(y)
531
541
  try:
532
- await self.flash_async()
533
- except BaseException:
534
- pass
542
+ position = (await self.get_position_async())
543
+ width = position.width
544
+ height = position.height
545
+ x_pos = position.left
546
+ y_pos = position.top
547
+ center_pos = (await self.get_position_async()).center
548
+ except AttributeError:
549
+ return
550
+ if not center_pos:
551
+ logger.warning("Could not calculate box model for %s", self)
552
+ return
553
+ if center:
554
+ x_pos = center_pos[0]
555
+ y_pos = center_pos[1]
556
+ width = 0
557
+ height = 0
558
+ logger.debug("Clicking on location: %.2f, %.2f" % center_pos)
559
+ else:
560
+ logger.debug("Clicking on location: %.2f, %.2f" % (x_pos, y_pos))
561
+ await asyncio.gather(
562
+ self.flash_async(
563
+ x_offset=x_offset - int(width / 2),
564
+ y_offset=y_offset - int(height / 2),
565
+ ),
566
+ self._tab.send(
567
+ cdp.input_.dispatch_mouse_event(
568
+ "mousePressed",
569
+ x=x_pos + x_offset,
570
+ y=y_pos + y_offset,
571
+ modifiers=modifiers,
572
+ button=cdp.input_.MouseButton(button),
573
+ buttons=buttons,
574
+ click_count=1,
575
+ )
576
+ ),
577
+ self._tab.send(
578
+ cdp.input_.dispatch_mouse_event(
579
+ "mouseReleased",
580
+ x=x_pos + x_offset,
581
+ y=y_pos + y_offset,
582
+ modifiers=modifiers,
583
+ button=cdp.input_.MouseButton(button),
584
+ buttons=buttons,
585
+ click_count=1,
586
+ )
587
+ ),
588
+ )
535
589
 
536
590
  async def mouse_move_async(self):
537
591
  """
@@ -664,7 +718,7 @@ class Element:
664
718
  return
665
719
  # await self.apply("""(el) => el.scrollIntoView(false)""")
666
720
 
667
- async def clear_input_async(self, _until_event: type = None):
721
+ async def clear_input_async(self):
668
722
  """Clears an input field."""
669
723
  try:
670
724
  await self.apply('function (element) { element.value = "" } ')
@@ -952,18 +1006,21 @@ class Element:
952
1006
  .replace(" ", "")
953
1007
  .replace("\n", "")
954
1008
  )
955
- arguments = [cdp.runtime.CallArgument(
956
- object_id=self._remote_object.object_id
957
- )]
958
- await self._tab.send(
959
- cdp.runtime.call_function_on(
960
- script,
961
- object_id=self._remote_object.object_id,
962
- arguments=arguments,
963
- await_promise=True,
964
- user_gesture=True,
1009
+ try:
1010
+ arguments = [cdp.runtime.CallArgument(
1011
+ object_id=self._remote_object.object_id
1012
+ )]
1013
+ await self._tab.send(
1014
+ cdp.runtime.call_function_on(
1015
+ script,
1016
+ object_id=self._remote_object.object_id,
1017
+ arguments=arguments,
1018
+ await_promise=True,
1019
+ user_gesture=True,
1020
+ )
965
1021
  )
966
- )
1022
+ except Exception:
1023
+ pass
967
1024
 
968
1025
  async def highlight_overlay_async(self):
969
1026
  """
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: seleniumbase
3
- Version: 4.44.0
3
+ Version: 4.44.2
4
4
  Summary: A complete web automation framework for end-to-end testing.
5
5
  Home-page: https://github.com/seleniumbase/SeleniumBase
6
6
  Author: Michael Mintz
@@ -186,7 +186,7 @@ Requires-Dist: pip-system-certs==4.0; platform_system == "Windows" and extra ==
186
186
  Provides-Extra: proxy
187
187
  Requires-Dist: proxy.py==2.4.3; extra == "proxy"
188
188
  Provides-Extra: psutil
189
- Requires-Dist: psutil==7.1.0; extra == "psutil"
189
+ Requires-Dist: psutil==7.1.2; extra == "psutil"
190
190
  Provides-Extra: pyautogui
191
191
  Requires-Dist: PyAutoGUI>=0.9.54; platform_system != "Linux" and extra == "pyautogui"
192
192
  Provides-Extra: selenium-stealth
@@ -177,7 +177,7 @@ pip-system-certs==4.0
177
177
  proxy.py==2.4.3
178
178
 
179
179
  [psutil]
180
- psutil==7.1.0
180
+ psutil==7.1.2
181
181
 
182
182
  [pyautogui]
183
183
 
@@ -307,7 +307,7 @@ setup(
307
307
  ],
308
308
  # pip install -e .[psutil]
309
309
  "psutil": [
310
- "psutil==7.1.0",
310
+ "psutil==7.1.2",
311
311
  ],
312
312
  # pip install -e .[pyautogui]
313
313
  # (Already a required dependency on Linux now.)
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes