seleniumbase 4.49.0__tar.gz → 4.49.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 (163) hide show
  1. {seleniumbase-4.49.0/seleniumbase.egg-info → seleniumbase-4.49.2}/PKG-INFO +67 -31
  2. {seleniumbase-4.49.0 → seleniumbase-4.49.2}/README.md +58 -23
  3. {seleniumbase-4.49.0 → seleniumbase-4.49.2}/requirements.txt +3 -2
  4. {seleniumbase-4.49.0 → seleniumbase-4.49.2}/seleniumbase/__version__.py +1 -1
  5. {seleniumbase-4.49.0 → seleniumbase-4.49.2}/seleniumbase/core/browser_launcher.py +9 -0
  6. {seleniumbase-4.49.0 → seleniumbase-4.49.2}/seleniumbase/core/sb_cdp.py +18 -14
  7. {seleniumbase-4.49.0 → seleniumbase-4.49.2}/seleniumbase/core/sb_driver.py +18 -0
  8. {seleniumbase-4.49.0 → seleniumbase-4.49.2}/seleniumbase/fixtures/base_case.py +58 -3
  9. {seleniumbase-4.49.0 → seleniumbase-4.49.2}/seleniumbase/undetected/__init__.py +24 -0
  10. {seleniumbase-4.49.0 → seleniumbase-4.49.2}/seleniumbase/undetected/cdp_driver/browser.py +25 -0
  11. {seleniumbase-4.49.0 → seleniumbase-4.49.2}/seleniumbase/undetected/cdp_driver/tab.py +7 -0
  12. {seleniumbase-4.49.0 → seleniumbase-4.49.2/seleniumbase.egg-info}/PKG-INFO +67 -31
  13. {seleniumbase-4.49.0 → seleniumbase-4.49.2}/seleniumbase.egg-info/requires.txt +10 -6
  14. {seleniumbase-4.49.0 → seleniumbase-4.49.2}/setup.py +10 -14
  15. {seleniumbase-4.49.0 → seleniumbase-4.49.2}/.gitignore +0 -0
  16. {seleniumbase-4.49.0 → seleniumbase-4.49.2}/LICENSE +0 -0
  17. {seleniumbase-4.49.0 → seleniumbase-4.49.2}/MANIFEST.in +0 -0
  18. {seleniumbase-4.49.0 → seleniumbase-4.49.2}/install.sh +0 -0
  19. {seleniumbase-4.49.0 → seleniumbase-4.49.2}/pyproject.toml +0 -0
  20. {seleniumbase-4.49.0 → seleniumbase-4.49.2}/pytest.ini +0 -0
  21. {seleniumbase-4.49.0 → seleniumbase-4.49.2}/sbase/__init__.py +0 -0
  22. {seleniumbase-4.49.0 → seleniumbase-4.49.2}/sbase/__main__.py +0 -0
  23. {seleniumbase-4.49.0 → seleniumbase-4.49.2}/sbase/steps.py +0 -0
  24. {seleniumbase-4.49.0 → seleniumbase-4.49.2}/seleniumbase/__init__.py +0 -0
  25. {seleniumbase-4.49.0 → seleniumbase-4.49.2}/seleniumbase/__main__.py +0 -0
  26. {seleniumbase-4.49.0 → seleniumbase-4.49.2}/seleniumbase/behave/__init__.py +0 -0
  27. {seleniumbase-4.49.0 → seleniumbase-4.49.2}/seleniumbase/behave/behave_helper.py +0 -0
  28. {seleniumbase-4.49.0 → seleniumbase-4.49.2}/seleniumbase/behave/behave_sb.py +0 -0
  29. {seleniumbase-4.49.0 → seleniumbase-4.49.2}/seleniumbase/behave/steps.py +0 -0
  30. {seleniumbase-4.49.0 → seleniumbase-4.49.2}/seleniumbase/common/__init__.py +0 -0
  31. {seleniumbase-4.49.0 → seleniumbase-4.49.2}/seleniumbase/common/decorators.py +0 -0
  32. {seleniumbase-4.49.0 → seleniumbase-4.49.2}/seleniumbase/common/encryption.py +0 -0
  33. {seleniumbase-4.49.0 → seleniumbase-4.49.2}/seleniumbase/common/exceptions.py +0 -0
  34. {seleniumbase-4.49.0 → seleniumbase-4.49.2}/seleniumbase/common/obfuscate.py +0 -0
  35. {seleniumbase-4.49.0 → seleniumbase-4.49.2}/seleniumbase/common/unobfuscate.py +0 -0
  36. {seleniumbase-4.49.0 → seleniumbase-4.49.2}/seleniumbase/config/__init__.py +0 -0
  37. {seleniumbase-4.49.0 → seleniumbase-4.49.2}/seleniumbase/config/ad_block_list.py +0 -0
  38. {seleniumbase-4.49.0 → seleniumbase-4.49.2}/seleniumbase/config/proxy_list.py +0 -0
  39. {seleniumbase-4.49.0 → seleniumbase-4.49.2}/seleniumbase/config/settings.py +0 -0
  40. {seleniumbase-4.49.0 → seleniumbase-4.49.2}/seleniumbase/console_scripts/__init__.py +0 -0
  41. {seleniumbase-4.49.0 → seleniumbase-4.49.2}/seleniumbase/console_scripts/logo_helper.py +0 -0
  42. {seleniumbase-4.49.0 → seleniumbase-4.49.2}/seleniumbase/console_scripts/rich_helper.py +0 -0
  43. {seleniumbase-4.49.0 → seleniumbase-4.49.2}/seleniumbase/console_scripts/run.py +0 -0
  44. {seleniumbase-4.49.0 → seleniumbase-4.49.2}/seleniumbase/console_scripts/sb_behave_gui.py +0 -0
  45. {seleniumbase-4.49.0 → seleniumbase-4.49.2}/seleniumbase/console_scripts/sb_caseplans.py +0 -0
  46. {seleniumbase-4.49.0 → seleniumbase-4.49.2}/seleniumbase/console_scripts/sb_commander.py +0 -0
  47. {seleniumbase-4.49.0 → seleniumbase-4.49.2}/seleniumbase/console_scripts/sb_install.py +0 -0
  48. {seleniumbase-4.49.0 → seleniumbase-4.49.2}/seleniumbase/console_scripts/sb_mkchart.py +0 -0
  49. {seleniumbase-4.49.0 → seleniumbase-4.49.2}/seleniumbase/console_scripts/sb_mkdir.py +0 -0
  50. {seleniumbase-4.49.0 → seleniumbase-4.49.2}/seleniumbase/console_scripts/sb_mkfile.py +0 -0
  51. {seleniumbase-4.49.0 → seleniumbase-4.49.2}/seleniumbase/console_scripts/sb_mkpres.py +0 -0
  52. {seleniumbase-4.49.0 → seleniumbase-4.49.2}/seleniumbase/console_scripts/sb_mkrec.py +0 -0
  53. {seleniumbase-4.49.0 → seleniumbase-4.49.2}/seleniumbase/console_scripts/sb_objectify.py +0 -0
  54. {seleniumbase-4.49.0 → seleniumbase-4.49.2}/seleniumbase/console_scripts/sb_print.py +0 -0
  55. {seleniumbase-4.49.0 → seleniumbase-4.49.2}/seleniumbase/console_scripts/sb_recorder.py +0 -0
  56. {seleniumbase-4.49.0 → seleniumbase-4.49.2}/seleniumbase/core/__init__.py +0 -0
  57. {seleniumbase-4.49.0 → seleniumbase-4.49.2}/seleniumbase/core/application_manager.py +0 -0
  58. {seleniumbase-4.49.0 → seleniumbase-4.49.2}/seleniumbase/core/capabilities_parser.py +0 -0
  59. {seleniumbase-4.49.0 → seleniumbase-4.49.2}/seleniumbase/core/colored_traceback.py +0 -0
  60. {seleniumbase-4.49.0 → seleniumbase-4.49.2}/seleniumbase/core/create_db_tables.sql +0 -0
  61. {seleniumbase-4.49.0 → seleniumbase-4.49.2}/seleniumbase/core/detect_b_ver.py +0 -0
  62. {seleniumbase-4.49.0 → seleniumbase-4.49.2}/seleniumbase/core/download_helper.py +0 -0
  63. {seleniumbase-4.49.0 → seleniumbase-4.49.2}/seleniumbase/core/encoded_images.py +0 -0
  64. {seleniumbase-4.49.0 → seleniumbase-4.49.2}/seleniumbase/core/jqc_helper.py +0 -0
  65. {seleniumbase-4.49.0 → seleniumbase-4.49.2}/seleniumbase/core/log_helper.py +0 -0
  66. {seleniumbase-4.49.0 → seleniumbase-4.49.2}/seleniumbase/core/mysql.py +0 -0
  67. {seleniumbase-4.49.0 → seleniumbase-4.49.2}/seleniumbase/core/nest_asyncio.py +0 -0
  68. {seleniumbase-4.49.0 → seleniumbase-4.49.2}/seleniumbase/core/proxy_helper.py +0 -0
  69. {seleniumbase-4.49.0 → seleniumbase-4.49.2}/seleniumbase/core/recorder_helper.py +0 -0
  70. {seleniumbase-4.49.0 → seleniumbase-4.49.2}/seleniumbase/core/report_helper.py +0 -0
  71. {seleniumbase-4.49.0 → seleniumbase-4.49.2}/seleniumbase/core/s3_manager.py +0 -0
  72. {seleniumbase-4.49.0 → seleniumbase-4.49.2}/seleniumbase/core/session_helper.py +0 -0
  73. {seleniumbase-4.49.0 → seleniumbase-4.49.2}/seleniumbase/core/settings_parser.py +0 -0
  74. {seleniumbase-4.49.0 → seleniumbase-4.49.2}/seleniumbase/core/style_sheet.py +0 -0
  75. {seleniumbase-4.49.0 → seleniumbase-4.49.2}/seleniumbase/core/testcase_manager.py +0 -0
  76. {seleniumbase-4.49.0 → seleniumbase-4.49.2}/seleniumbase/core/tour_helper.py +0 -0
  77. {seleniumbase-4.49.0 → seleniumbase-4.49.2}/seleniumbase/core/visual_helper.py +0 -0
  78. {seleniumbase-4.49.0 → seleniumbase-4.49.2}/seleniumbase/drivers/__init__.py +0 -0
  79. {seleniumbase-4.49.0 → seleniumbase-4.49.2}/seleniumbase/drivers/atlas_drivers/__init__.py +0 -0
  80. {seleniumbase-4.49.0 → seleniumbase-4.49.2}/seleniumbase/drivers/brave_drivers/__init__.py +0 -0
  81. {seleniumbase-4.49.0 → seleniumbase-4.49.2}/seleniumbase/drivers/cft_drivers/__init__.py +0 -0
  82. {seleniumbase-4.49.0 → seleniumbase-4.49.2}/seleniumbase/drivers/chromium_drivers/__init__.py +0 -0
  83. {seleniumbase-4.49.0 → seleniumbase-4.49.2}/seleniumbase/drivers/chs_drivers/__init__.py +0 -0
  84. {seleniumbase-4.49.0 → seleniumbase-4.49.2}/seleniumbase/drivers/comet_drivers/__init__.py +0 -0
  85. {seleniumbase-4.49.0 → seleniumbase-4.49.2}/seleniumbase/drivers/opera_drivers/__init__.py +0 -0
  86. {seleniumbase-4.49.0 → seleniumbase-4.49.2}/seleniumbase/extensions/__init__.py +0 -0
  87. {seleniumbase-4.49.0 → seleniumbase-4.49.2}/seleniumbase/extensions/ad_block.zip +0 -0
  88. {seleniumbase-4.49.0 → seleniumbase-4.49.2}/seleniumbase/extensions/disable_csp.zip +0 -0
  89. {seleniumbase-4.49.0 → seleniumbase-4.49.2}/seleniumbase/extensions/recorder.zip +0 -0
  90. {seleniumbase-4.49.0 → seleniumbase-4.49.2}/seleniumbase/extensions/sbase_ext.zip +0 -0
  91. {seleniumbase-4.49.0 → seleniumbase-4.49.2}/seleniumbase/fixtures/__init__.py +0 -0
  92. {seleniumbase-4.49.0 → seleniumbase-4.49.2}/seleniumbase/fixtures/constants.py +0 -0
  93. {seleniumbase-4.49.0 → seleniumbase-4.49.2}/seleniumbase/fixtures/css_to_xpath.py +0 -0
  94. {seleniumbase-4.49.0 → seleniumbase-4.49.2}/seleniumbase/fixtures/errors.py +0 -0
  95. {seleniumbase-4.49.0 → seleniumbase-4.49.2}/seleniumbase/fixtures/js_utils.py +0 -0
  96. {seleniumbase-4.49.0 → seleniumbase-4.49.2}/seleniumbase/fixtures/page_actions.py +0 -0
  97. {seleniumbase-4.49.0 → seleniumbase-4.49.2}/seleniumbase/fixtures/page_utils.py +0 -0
  98. {seleniumbase-4.49.0 → seleniumbase-4.49.2}/seleniumbase/fixtures/shared_utils.py +0 -0
  99. {seleniumbase-4.49.0 → seleniumbase-4.49.2}/seleniumbase/fixtures/unittest_helper.py +0 -0
  100. {seleniumbase-4.49.0 → seleniumbase-4.49.2}/seleniumbase/fixtures/words.py +0 -0
  101. {seleniumbase-4.49.0 → seleniumbase-4.49.2}/seleniumbase/fixtures/xpath_to_css.py +0 -0
  102. {seleniumbase-4.49.0 → seleniumbase-4.49.2}/seleniumbase/js_code/__init__.py +0 -0
  103. {seleniumbase-4.49.0 → seleniumbase-4.49.2}/seleniumbase/js_code/active_css_js.py +0 -0
  104. {seleniumbase-4.49.0 → seleniumbase-4.49.2}/seleniumbase/js_code/live_js.py +0 -0
  105. {seleniumbase-4.49.0 → seleniumbase-4.49.2}/seleniumbase/js_code/recorder_js.py +0 -0
  106. {seleniumbase-4.49.0 → seleniumbase-4.49.2}/seleniumbase/masterqa/__init__.py +0 -0
  107. {seleniumbase-4.49.0 → seleniumbase-4.49.2}/seleniumbase/masterqa/master_qa.py +0 -0
  108. {seleniumbase-4.49.0 → seleniumbase-4.49.2}/seleniumbase/plugins/__init__.py +0 -0
  109. {seleniumbase-4.49.0 → seleniumbase-4.49.2}/seleniumbase/plugins/base_plugin.py +0 -0
  110. {seleniumbase-4.49.0 → seleniumbase-4.49.2}/seleniumbase/plugins/basic_test_info.py +0 -0
  111. {seleniumbase-4.49.0 → seleniumbase-4.49.2}/seleniumbase/plugins/db_reporting_plugin.py +0 -0
  112. {seleniumbase-4.49.0 → seleniumbase-4.49.2}/seleniumbase/plugins/driver_manager.py +0 -0
  113. {seleniumbase-4.49.0 → seleniumbase-4.49.2}/seleniumbase/plugins/page_source.py +0 -0
  114. {seleniumbase-4.49.0 → seleniumbase-4.49.2}/seleniumbase/plugins/pytest_plugin.py +0 -0
  115. {seleniumbase-4.49.0 → seleniumbase-4.49.2}/seleniumbase/plugins/s3_logging_plugin.py +0 -0
  116. {seleniumbase-4.49.0 → seleniumbase-4.49.2}/seleniumbase/plugins/sb_manager.py +0 -0
  117. {seleniumbase-4.49.0 → seleniumbase-4.49.2}/seleniumbase/plugins/screen_shots.py +0 -0
  118. {seleniumbase-4.49.0 → seleniumbase-4.49.2}/seleniumbase/plugins/selenium_plugin.py +0 -0
  119. {seleniumbase-4.49.0 → seleniumbase-4.49.2}/seleniumbase/resources/__init__.py +0 -0
  120. {seleniumbase-4.49.0 → seleniumbase-4.49.2}/seleniumbase/translate/__init__.py +0 -0
  121. {seleniumbase-4.49.0 → seleniumbase-4.49.2}/seleniumbase/translate/chinese.py +0 -0
  122. {seleniumbase-4.49.0 → seleniumbase-4.49.2}/seleniumbase/translate/dutch.py +0 -0
  123. {seleniumbase-4.49.0 → seleniumbase-4.49.2}/seleniumbase/translate/french.py +0 -0
  124. {seleniumbase-4.49.0 → seleniumbase-4.49.2}/seleniumbase/translate/italian.py +0 -0
  125. {seleniumbase-4.49.0 → seleniumbase-4.49.2}/seleniumbase/translate/japanese.py +0 -0
  126. {seleniumbase-4.49.0 → seleniumbase-4.49.2}/seleniumbase/translate/korean.py +0 -0
  127. {seleniumbase-4.49.0 → seleniumbase-4.49.2}/seleniumbase/translate/master_dict.py +0 -0
  128. {seleniumbase-4.49.0 → seleniumbase-4.49.2}/seleniumbase/translate/portuguese.py +0 -0
  129. {seleniumbase-4.49.0 → seleniumbase-4.49.2}/seleniumbase/translate/russian.py +0 -0
  130. {seleniumbase-4.49.0 → seleniumbase-4.49.2}/seleniumbase/translate/spanish.py +0 -0
  131. {seleniumbase-4.49.0 → seleniumbase-4.49.2}/seleniumbase/translate/translator.py +0 -0
  132. {seleniumbase-4.49.0 → seleniumbase-4.49.2}/seleniumbase/undetected/cdp.py +0 -0
  133. {seleniumbase-4.49.0 → seleniumbase-4.49.2}/seleniumbase/undetected/cdp_driver/__init__.py +0 -0
  134. {seleniumbase-4.49.0 → seleniumbase-4.49.2}/seleniumbase/undetected/cdp_driver/_contradict.py +0 -0
  135. {seleniumbase-4.49.0 → seleniumbase-4.49.2}/seleniumbase/undetected/cdp_driver/cdp_util.py +0 -0
  136. {seleniumbase-4.49.0 → seleniumbase-4.49.2}/seleniumbase/undetected/cdp_driver/config.py +0 -0
  137. {seleniumbase-4.49.0 → seleniumbase-4.49.2}/seleniumbase/undetected/cdp_driver/connection.py +0 -0
  138. {seleniumbase-4.49.0 → seleniumbase-4.49.2}/seleniumbase/undetected/cdp_driver/element.py +0 -0
  139. {seleniumbase-4.49.0 → seleniumbase-4.49.2}/seleniumbase/undetected/dprocess.py +0 -0
  140. {seleniumbase-4.49.0 → seleniumbase-4.49.2}/seleniumbase/undetected/options.py +0 -0
  141. {seleniumbase-4.49.0 → seleniumbase-4.49.2}/seleniumbase/undetected/patcher.py +0 -0
  142. {seleniumbase-4.49.0 → seleniumbase-4.49.2}/seleniumbase/undetected/reactor.py +0 -0
  143. {seleniumbase-4.49.0 → seleniumbase-4.49.2}/seleniumbase/undetected/webelement.py +0 -0
  144. {seleniumbase-4.49.0 → seleniumbase-4.49.2}/seleniumbase/utilities/__init__.py +0 -0
  145. {seleniumbase-4.49.0 → seleniumbase-4.49.2}/seleniumbase/utilities/selenium_grid/__init__.py +0 -0
  146. {seleniumbase-4.49.0 → seleniumbase-4.49.2}/seleniumbase/utilities/selenium_grid/download_selenium_server.py +0 -0
  147. {seleniumbase-4.49.0 → seleniumbase-4.49.2}/seleniumbase/utilities/selenium_grid/font_color +0 -0
  148. {seleniumbase-4.49.0 → seleniumbase-4.49.2}/seleniumbase/utilities/selenium_grid/grid-hub +0 -0
  149. {seleniumbase-4.49.0 → seleniumbase-4.49.2}/seleniumbase/utilities/selenium_grid/grid-node +0 -0
  150. {seleniumbase-4.49.0 → seleniumbase-4.49.2}/seleniumbase/utilities/selenium_grid/grid_hub.py +0 -0
  151. {seleniumbase-4.49.0 → seleniumbase-4.49.2}/seleniumbase/utilities/selenium_grid/grid_node.py +0 -0
  152. {seleniumbase-4.49.0 → seleniumbase-4.49.2}/seleniumbase/utilities/selenium_grid/register-grid-node.bat +0 -0
  153. {seleniumbase-4.49.0 → seleniumbase-4.49.2}/seleniumbase/utilities/selenium_grid/register-grid-node.sh +0 -0
  154. {seleniumbase-4.49.0 → seleniumbase-4.49.2}/seleniumbase/utilities/selenium_grid/start-grid-hub.bat +0 -0
  155. {seleniumbase-4.49.0 → seleniumbase-4.49.2}/seleniumbase/utilities/selenium_grid/start-grid-hub.sh +0 -0
  156. {seleniumbase-4.49.0 → seleniumbase-4.49.2}/seleniumbase/utilities/selenium_ide/__init__.py +0 -0
  157. {seleniumbase-4.49.0 → seleniumbase-4.49.2}/seleniumbase/utilities/selenium_ide/convert_ide.py +0 -0
  158. {seleniumbase-4.49.0 → seleniumbase-4.49.2}/seleniumbase.egg-info/SOURCES.txt +0 -0
  159. {seleniumbase-4.49.0 → seleniumbase-4.49.2}/seleniumbase.egg-info/dependency_links.txt +0 -0
  160. {seleniumbase-4.49.0 → seleniumbase-4.49.2}/seleniumbase.egg-info/entry_points.txt +0 -0
  161. {seleniumbase-4.49.0 → seleniumbase-4.49.2}/seleniumbase.egg-info/top_level.txt +0 -0
  162. {seleniumbase-4.49.0 → seleniumbase-4.49.2}/setup.cfg +0 -0
  163. {seleniumbase-4.49.0 → seleniumbase-4.49.2}/virtualenv_install.sh +0 -0
@@ -1,7 +1,7 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: seleniumbase
3
- Version: 4.49.0
4
- Summary: Stealthy automation (via CDP Mode) that passes every bot detection test with any Chromium browser you want. Includes a test framework.
3
+ Version: 4.49.2
4
+ Summary: A framework for stealthy Chromium automation with CDP Mode. Includes CAPTCHA-bypass, E2E Testing, and a Playwright integration.
5
5
  Home-page: https://github.com/seleniumbase/SeleniumBase
6
6
  Author: Michael Mintz
7
7
  Author-email: mdmintz@gmail.com
@@ -16,7 +16,7 @@ Project-URL: PyPI, https://pypi.org/project/seleniumbase/
16
16
  Project-URL: Source, https://github.com/seleniumbase/SeleniumBase
17
17
  Project-URL: Repository, https://github.com/seleniumbase/SeleniumBase
18
18
  Project-URL: Documentation, https://seleniumbase.io/
19
- Keywords: pytest,selenium,framework,automation,browser,testing,webdriver,seleniumbase,sbase,web-crawling,web-scraping,scraping,stealth,chromium,playwright,anti-detect,antidetect,undetected,bot-detection,fingerprint,recaptcha,cloudflare,turnstile,datadome,captcha,headless
19
+ Keywords: pytest,selenium,framework,automation,browser,testing,webdriver,seleniumbase,sbase,web-crawling,web-scraping,stealth,chromium,playwright,undetected,bot-detection,fingerprint,recaptcha,cloudflare,turnstile,datadome,captcha,headless
20
20
  Platform: Windows
21
21
  Platform: Linux
22
22
  Platform: Mac OS-X
@@ -65,7 +65,7 @@ Requires-Dist: setuptools~=70.2; python_version < "3.10"
65
65
  Requires-Dist: setuptools>=82.0.1; python_version >= "3.10"
66
66
  Requires-Dist: wheel>=0.47.0
67
67
  Requires-Dist: attrs>=26.1.0
68
- Requires-Dist: certifi>=2026.4.22
68
+ Requires-Dist: certifi>=2026.5.20
69
69
  Requires-Dist: exceptiongroup>=1.3.1
70
70
  Requires-Dist: websockets~=15.0.1; python_version < "3.10"
71
71
  Requires-Dist: websockets>=16.0; python_version >= "3.10"
@@ -84,12 +84,13 @@ Requires-Dist: six>=1.17.0
84
84
  Requires-Dist: parse>=1.22.0
85
85
  Requires-Dist: parse-type>=0.6.6
86
86
  Requires-Dist: colorama>=0.4.6
87
+ Requires-Dist: psutil>=7.2.2
87
88
  Requires-Dist: pyyaml>=6.0.3
88
89
  Requires-Dist: pygments>=2.20.0
89
90
  Requires-Dist: pyreadline3>=3.5.4; platform_system == "Windows"
90
91
  Requires-Dist: tabcompleter>=1.4.1
91
92
  Requires-Dist: pdbp>=1.8.2
92
- Requires-Dist: idna>=3.15
93
+ Requires-Dist: idna>=3.16
93
94
  Requires-Dist: charset-normalizer<4,>=3.4.7
94
95
  Requires-Dist: urllib3<2,>=1.26.20; python_version < "3.10"
95
96
  Requires-Dist: urllib3<3,>=2.7.0; python_version >= "3.10"
@@ -166,9 +167,9 @@ Requires-Dist: pip-system-certs==4.0; platform_system == "Windows" and extra ==
166
167
  Provides-Extra: proxy
167
168
  Requires-Dist: proxy.py==2.4.3; extra == "proxy"
168
169
  Provides-Extra: playwright
169
- Requires-Dist: playwright>=1.58.0; extra == "playwright"
170
- Provides-Extra: psutil
171
- Requires-Dist: psutil>=7.2.2; extra == "psutil"
170
+ Requires-Dist: playwright>=1.60.0; extra == "playwright"
171
+ Requires-Dist: greenlet>=3.2.5; python_version < "3.10" and extra == "playwright"
172
+ Requires-Dist: greenlet>=3.5.1; python_version >= "3.10" and extra == "playwright"
172
173
  Provides-Extra: pyautogui
173
174
  Requires-Dist: PyAutoGUI>=0.9.54; platform_system != "Linux" and extra == "pyautogui"
174
175
  Provides-Extra: selenium-stealth
@@ -208,19 +209,12 @@ Dynamic: summary
208
209
  <meta property="og:image" content="https://seleniumbase.github.io/cdn/img/mac_sb_logo_5b.png" />
209
210
  <link rel="icon" href="https://seleniumbase.github.io/img/logo7.png" />
210
211
 
211
- <h1>SeleniumBase</h1>
212
-
213
212
  <p align="center"><a href="https://github.com/seleniumbase/SeleniumBase/"><img src="https://seleniumbase.github.io/cdn/img/nice_logo_8t.png" alt="SeleniumBase" width="424" /></a></p>
214
213
 
215
214
  <p align="center"><a href="https://pypi.python.org/pypi/seleniumbase" target="_blank"><img src="https://img.shields.io/pypi/v/seleniumbase.svg?color=3399EE" alt="PyPI version" /></a> <a href="https://pepy.tech/projects/seleniumbase?timeRange=threeMonths&category=version&includeCIDownloads=true&granularity=daily&viewType=line&versions=*" target="_blank"><img src="https://static.pepy.tech/badge/seleniumbase" alt="SeleniumBase PyPI downloads" /></a> <a href="https://discord.gg/EdhQTn3EyE" target="_blank"><img src="https://img.shields.io/discord/727927627830001734?color=7289DA&label=Discord&logo=discord&logoColor=white"/></a><br /> <a href="https://github.com/seleniumbase/SeleniumBase/blob/master/LICENSE"><img src="https://img.shields.io/badge/license-MIT-22BBCC.svg" title="SeleniumBase" /></a> <a href="https://github.com/seleniumbase/SeleniumBase/actions" target="_blank"><img src="https://github.com/seleniumbase/SeleniumBase/workflows/CI%20build/badge.svg" alt="SeleniumBase GitHub Actions" /></a> <a href="https://seleniumbase.io"><img src="https://img.shields.io/badge/docs-seleniumbase.io-11BBAA.svg" alt="SeleniumBase Docs" /></a></p>
216
215
  <p align="center"></p>
217
216
 
218
- <h3 align="center">Stealthy automation that passes every bot detection test.</h3>
219
-
220
- <table align="center"><tr><td>
221
- <b>Verified using multiple different Chromium browsers:<br />Chrome, Chrome-for-Testing, Chromium, Edge, Brave.</b>
222
- </td></tr></table>
223
-
217
+ <h3 align="center">Stealthy Chromium Automation and E2E Testing.</h3>
224
218
 
225
219
  <p align="center">
226
220
  <a href="#python_installation">🚀 Start</a> |
@@ -240,7 +234,7 @@ Dynamic: summary
240
234
  <a href="https://seleniumbase.io/demo_page">📰 TestPage</a> |
241
235
  <a href="https://github.com/seleniumbase/SeleniumBase/blob/master/help_docs/uc_mode.md">👤 UC Mode</a> |
242
236
  <a href="https://github.com/seleniumbase/SeleniumBase/blob/master/examples/cdp_mode/ReadMe.md">🐙 CDP Mode</a> |
243
- <a href="https://github.com/seleniumbase/SeleniumBase/blob/master/examples/chart_maker/ReadMe.md">📶 Charts</a> |
237
+ <a href="https://github.com/seleniumbase/SeleniumBase/blob/master/examples/chart_maker/ReadMe.md">📶 Charts</a> |
244
238
  <a href="https://seleniumbase.io/devices/?url=seleniumbase.com">🖥️ Farm</a>
245
239
  <br />
246
240
  <a href="https://github.com/seleniumbase/SeleniumBase/blob/master/help_docs/how_it_works.md">👁️ How</a> |
@@ -258,11 +252,44 @@ Dynamic: summary
258
252
  <br />
259
253
  </p>
260
254
 
261
- 🐙 <a translate="no" href="https://github.com/seleniumbase/SeleniumBase/blob/master/examples/cdp_mode/ReadMe.md"><b>CDP Mode</b></a> bypasses bot-detection and handles CAPTCHAs by driving the browser directly through the <a href="https://chromedevtools.github.io/devtools-protocol/" translate="no">Chrome DevTools Protocol</a>. Includes <a href="https://github.com/seleniumbase/SeleniumBase/blob/master/examples/cdp_mode/playwright/ReadMe.md"><b><span translate="no">Stealthy Playwright Mode</span></b></a>, which extends these advanced anti-detection patches to Playwright scripts.
255
+ 🐙 <a translate="no" href="https://github.com/seleniumbase/SeleniumBase/blob/master/examples/cdp_mode/ReadMe.md"><b>CDP Mode</b></a> <b>bypasses bot-detection</b> and handles CAPTCHAs with the <a href="https://chromedevtools.github.io/devtools-protocol/" translate="no">Chrome DevTools Protocol</a>. Includes <a href="https://github.com/seleniumbase/SeleniumBase/blob/master/examples/cdp_mode/playwright/ReadMe.md"><b><span translate="no">Stealthy Playwright Mode</span></b></a>, which extends CDP Mode's anti-detection to <b>Playwright</b> scripts. <b><code>sb.solve_captcha()</code></b> handles CAPTCHAs that aren't bypassed automatically.
256
+
257
+ <b>Python sync version of SeleniumBase's CDP Mode: (<code>sb_cdp</code>)</b>
258
+
259
+ ```python
260
+ from seleniumbase import sb_cdp
261
+
262
+ sb = sb_cdp.Chrome()
263
+ sb.open("https://demo.fingerprint.com/playground")
264
+ sb.sleep(3)
265
+ sb.driver.quit()
266
+ ```
267
+
268
+ <b>Playwright can use SeleniumBase's stealth browser:</b>
262
269
 
263
- 📚 The [SeleniumBase/examples/](https://github.com/seleniumbase/SeleniumBase/tree/master/examples) folder includes over 100 ready-to-run examples. Examples that start with `test_` or end with `_test.py`/`_tests.py` are specifically designed to run with `pytest`. Other examples run directly with raw `python` (those files generally start with `raw_` to avoid confusion).
270
+ ```python
271
+ from playwright.sync_api import sync_playwright
272
+ from seleniumbase import sb_cdp
264
273
 
265
- 🥷 Stealthy examples are located in [SeleniumBase/examples/cdp_mode/](https://github.com/seleniumbase/SeleniumBase/tree/master/examples/cdp_mode).
274
+ sb = sb_cdp.Chrome()
275
+ endpoint_url = sb.get_endpoint_url()
276
+
277
+ with sync_playwright() as p:
278
+ browser = p.chromium.connect_over_cdp(endpoint_url)
279
+ page = browser.contexts[0].pages[0]
280
+ page.goto("https://browserscan.net/bot-detection")
281
+
282
+ sb.sleep(3)
283
+ sb.driver.quit()
284
+ ```
285
+
286
+ --------
287
+
288
+ 📚 The [SeleniumBase/examples/](https://github.com/seleniumbase/SeleniumBase/tree/master/examples) folder includes over 150 ready-to-run examples of E2E testing. Examples that start with `test_` or end with `_test.py`/`_tests.py` run with `pytest`. Other examples run directly with raw `python` (those generally start with `raw_` to avoid confusion).
289
+
290
+ 🥷 Stealthy CDP Mode examples are located in [./examples/cdp_mode/](https://github.com/seleniumbase/SeleniumBase/tree/master/examples/cdp_mode).
291
+
292
+ 🎭 Stealthy Playwright examples are located in [./examples/cdp_mode/playwright/](https://github.com/seleniumbase/SeleniumBase/blob/master/examples/cdp_mode/playwright/).
266
293
 
267
294
  --------
268
295
 
@@ -279,17 +306,17 @@ Dynamic: summary
279
306
  ```python
280
307
  from seleniumbase import sb_cdp
281
308
 
282
- url = "https://www.browserscan.net/bot-detection"
283
- sb = sb_cdp.Chrome(url, locale="en", ad_block=True)
284
- sb.flash("Test Results", duration=3, pause=1)
309
+ sb = sb_cdp.Chrome(locale="en", ad_block=True)
310
+ sb.open("https://browserscan.net/bot-detection")
311
+ sb.flash("Test Results", duration=1.5, pause=0.5)
285
312
  sb.assert_element('strong:contains("Normal")')
286
- print("Bot Not detected")
287
- sb.flash('strong:contains("Normal")', duration=3, pause=2)
313
+ print("Bot Not Detected")
314
+ sb.flash('strong:contains("Normal")', pause=1)
288
315
  ```
289
316
 
290
317
  <img src="https://seleniumbase.github.io/other/b_scan_results.jpg" width="628" alt="Stealthy architecture flowchart" />
291
318
 
292
- 📝 <a href="https://github.com/seleniumbase/SeleniumBase/blob/master/examples/cdp_mode/playwright/raw_browserscan_sync.py">This</a> also works as a drop-in replacement for Playwright (making it stealthy):
319
+ 📝 <a href="https://github.com/seleniumbase/SeleniumBase/blob/master/examples/cdp_mode/playwright/raw_browserscan_sync.py">This example</a> demonstrates the drop-in patch that makes Playwright stealthy:
293
320
 
294
321
  ```python
295
322
  from playwright.sync_api import sync_playwright
@@ -301,16 +328,19 @@ endpoint_url = sb.get_endpoint_url()
301
328
  with sync_playwright() as p:
302
329
  browser = p.chromium.connect_over_cdp(endpoint_url)
303
330
  page = browser.contexts[0].pages[0]
304
- page.goto("https://www.browserscan.net/bot-detection")
331
+ page.goto("https://browserscan.net/bot-detection")
305
332
  page.wait_for_timeout(500)
306
- sb.flash("Test Results", duration=3, pause=1)
333
+ sb.flash("Test Results", duration=1.5, pause=0.5)
307
334
  sb.assert_element('strong:contains("Normal")')
308
- sb.flash('strong:contains("Normal")', duration=3, pause=2)
335
+ print("Bot Not Detected")
336
+ sb.flash('strong:contains("Normal")', pause=1)
309
337
  ```
310
338
 
311
339
  --------
312
340
 
313
- For choosing which Chromium browser to use, you can set command-line options:
341
+ <h3 align="left">🌐 CLI Options for Supported Chromium Browsers</h3>
342
+
343
+ 💡 You can set which Chromium browser to use via command-line options:
314
344
 
315
345
  ```zsh
316
346
  python SCRIPT.py --use-chromium # Use the unbranded Chromium browser
@@ -319,7 +349,13 @@ python SCRIPT.py --edge # Use Microsoft Edge
319
349
  python SCRIPT.py --brave # Use Brave browser
320
350
  ```
321
351
 
322
- (Google Chrome is the default browser if not specified.)
352
+ Google Chrome is the default browser if not specified. Only unbranded Chromium and Chrome-for-Testing are installed automatically if not already installed.
353
+
354
+ You can also set the browser via method args, eg: `cft=True`, `use_chromium=True`, `browser="edge"`, `browser="brave"`, etc. Eg:
355
+
356
+ ```python
357
+ sb = sb_cdp.Chrome(url, use_chromium=True)
358
+ ```
323
359
 
324
360
  --------
325
361
 
@@ -7,19 +7,12 @@
7
7
  <meta property="og:image" content="https://seleniumbase.github.io/cdn/img/mac_sb_logo_5b.png" />
8
8
  <link rel="icon" href="https://seleniumbase.github.io/img/logo7.png" />
9
9
 
10
- <h1>SeleniumBase</h1>
11
-
12
10
  <p align="center"><a href="https://github.com/seleniumbase/SeleniumBase/"><img src="https://seleniumbase.github.io/cdn/img/nice_logo_8t.png" alt="SeleniumBase" width="424" /></a></p>
13
11
 
14
12
  <p align="center"><a href="https://pypi.python.org/pypi/seleniumbase" target="_blank"><img src="https://img.shields.io/pypi/v/seleniumbase.svg?color=3399EE" alt="PyPI version" /></a> <a href="https://pepy.tech/projects/seleniumbase?timeRange=threeMonths&category=version&includeCIDownloads=true&granularity=daily&viewType=line&versions=*" target="_blank"><img src="https://static.pepy.tech/badge/seleniumbase" alt="SeleniumBase PyPI downloads" /></a> <a href="https://discord.gg/EdhQTn3EyE" target="_blank"><img src="https://img.shields.io/discord/727927627830001734?color=7289DA&label=Discord&logo=discord&logoColor=white"/></a><br /> <a href="https://github.com/seleniumbase/SeleniumBase/blob/master/LICENSE"><img src="https://img.shields.io/badge/license-MIT-22BBCC.svg" title="SeleniumBase" /></a> <a href="https://github.com/seleniumbase/SeleniumBase/actions" target="_blank"><img src="https://github.com/seleniumbase/SeleniumBase/workflows/CI%20build/badge.svg" alt="SeleniumBase GitHub Actions" /></a> <a href="https://seleniumbase.io"><img src="https://img.shields.io/badge/docs-seleniumbase.io-11BBAA.svg" alt="SeleniumBase Docs" /></a></p>
15
13
  <p align="center"></p>
16
14
 
17
- <h3 align="center">Stealthy automation that passes every bot detection test.</h3>
18
-
19
- <table align="center"><tr><td>
20
- <b>Verified using multiple different Chromium browsers:<br />Chrome, Chrome-for-Testing, Chromium, Edge, Brave.</b>
21
- </td></tr></table>
22
-
15
+ <h3 align="center">Stealthy Chromium Automation and E2E Testing.</h3>
23
16
 
24
17
  <p align="center">
25
18
  <a href="#python_installation">🚀 Start</a> |
@@ -39,7 +32,7 @@
39
32
  <a href="https://seleniumbase.io/demo_page">📰 TestPage</a> |
40
33
  <a href="https://github.com/seleniumbase/SeleniumBase/blob/master/help_docs/uc_mode.md">👤 UC Mode</a> |
41
34
  <a href="https://github.com/seleniumbase/SeleniumBase/blob/master/examples/cdp_mode/ReadMe.md">🐙 CDP Mode</a> |
42
- <a href="https://github.com/seleniumbase/SeleniumBase/blob/master/examples/chart_maker/ReadMe.md">📶 Charts</a> |
35
+ <a href="https://github.com/seleniumbase/SeleniumBase/blob/master/examples/chart_maker/ReadMe.md">📶 Charts</a> |
43
36
  <a href="https://seleniumbase.io/devices/?url=seleniumbase.com">🖥️ Farm</a>
44
37
  <br />
45
38
  <a href="https://github.com/seleniumbase/SeleniumBase/blob/master/help_docs/how_it_works.md">👁️ How</a> |
@@ -57,11 +50,44 @@
57
50
  <br />
58
51
  </p>
59
52
 
60
- 🐙 <a translate="no" href="https://github.com/seleniumbase/SeleniumBase/blob/master/examples/cdp_mode/ReadMe.md"><b>CDP Mode</b></a> bypasses bot-detection and handles CAPTCHAs by driving the browser directly through the <a href="https://chromedevtools.github.io/devtools-protocol/" translate="no">Chrome DevTools Protocol</a>. Includes <a href="https://github.com/seleniumbase/SeleniumBase/blob/master/examples/cdp_mode/playwright/ReadMe.md"><b><span translate="no">Stealthy Playwright Mode</span></b></a>, which extends these advanced anti-detection patches to Playwright scripts.
53
+ 🐙 <a translate="no" href="https://github.com/seleniumbase/SeleniumBase/blob/master/examples/cdp_mode/ReadMe.md"><b>CDP Mode</b></a> <b>bypasses bot-detection</b> and handles CAPTCHAs with the <a href="https://chromedevtools.github.io/devtools-protocol/" translate="no">Chrome DevTools Protocol</a>. Includes <a href="https://github.com/seleniumbase/SeleniumBase/blob/master/examples/cdp_mode/playwright/ReadMe.md"><b><span translate="no">Stealthy Playwright Mode</span></b></a>, which extends CDP Mode's anti-detection to <b>Playwright</b> scripts. <b><code>sb.solve_captcha()</code></b> handles CAPTCHAs that aren't bypassed automatically.
54
+
55
+ <b>Python sync version of SeleniumBase's CDP Mode: (<code>sb_cdp</code>)</b>
56
+
57
+ ```python
58
+ from seleniumbase import sb_cdp
59
+
60
+ sb = sb_cdp.Chrome()
61
+ sb.open("https://demo.fingerprint.com/playground")
62
+ sb.sleep(3)
63
+ sb.driver.quit()
64
+ ```
65
+
66
+ <b>Playwright can use SeleniumBase's stealth browser:</b>
61
67
 
62
- 📚 The [SeleniumBase/examples/](https://github.com/seleniumbase/SeleniumBase/tree/master/examples) folder includes over 100 ready-to-run examples. Examples that start with `test_` or end with `_test.py`/`_tests.py` are specifically designed to run with `pytest`. Other examples run directly with raw `python` (those files generally start with `raw_` to avoid confusion).
68
+ ```python
69
+ from playwright.sync_api import sync_playwright
70
+ from seleniumbase import sb_cdp
63
71
 
64
- 🥷 Stealthy examples are located in [SeleniumBase/examples/cdp_mode/](https://github.com/seleniumbase/SeleniumBase/tree/master/examples/cdp_mode).
72
+ sb = sb_cdp.Chrome()
73
+ endpoint_url = sb.get_endpoint_url()
74
+
75
+ with sync_playwright() as p:
76
+ browser = p.chromium.connect_over_cdp(endpoint_url)
77
+ page = browser.contexts[0].pages[0]
78
+ page.goto("https://browserscan.net/bot-detection")
79
+
80
+ sb.sleep(3)
81
+ sb.driver.quit()
82
+ ```
83
+
84
+ --------
85
+
86
+ 📚 The [SeleniumBase/examples/](https://github.com/seleniumbase/SeleniumBase/tree/master/examples) folder includes over 150 ready-to-run examples of E2E testing. Examples that start with `test_` or end with `_test.py`/`_tests.py` run with `pytest`. Other examples run directly with raw `python` (those generally start with `raw_` to avoid confusion).
87
+
88
+ 🥷 Stealthy CDP Mode examples are located in [./examples/cdp_mode/](https://github.com/seleniumbase/SeleniumBase/tree/master/examples/cdp_mode).
89
+
90
+ 🎭 Stealthy Playwright examples are located in [./examples/cdp_mode/playwright/](https://github.com/seleniumbase/SeleniumBase/blob/master/examples/cdp_mode/playwright/).
65
91
 
66
92
  --------
67
93
 
@@ -78,17 +104,17 @@
78
104
  ```python
79
105
  from seleniumbase import sb_cdp
80
106
 
81
- url = "https://www.browserscan.net/bot-detection"
82
- sb = sb_cdp.Chrome(url, locale="en", ad_block=True)
83
- sb.flash("Test Results", duration=3, pause=1)
107
+ sb = sb_cdp.Chrome(locale="en", ad_block=True)
108
+ sb.open("https://browserscan.net/bot-detection")
109
+ sb.flash("Test Results", duration=1.5, pause=0.5)
84
110
  sb.assert_element('strong:contains("Normal")')
85
- print("Bot Not detected")
86
- sb.flash('strong:contains("Normal")', duration=3, pause=2)
111
+ print("Bot Not Detected")
112
+ sb.flash('strong:contains("Normal")', pause=1)
87
113
  ```
88
114
 
89
115
  <img src="https://seleniumbase.github.io/other/b_scan_results.jpg" width="628" alt="Stealthy architecture flowchart" />
90
116
 
91
- 📝 <a href="https://github.com/seleniumbase/SeleniumBase/blob/master/examples/cdp_mode/playwright/raw_browserscan_sync.py">This</a> also works as a drop-in replacement for Playwright (making it stealthy):
117
+ 📝 <a href="https://github.com/seleniumbase/SeleniumBase/blob/master/examples/cdp_mode/playwright/raw_browserscan_sync.py">This example</a> demonstrates the drop-in patch that makes Playwright stealthy:
92
118
 
93
119
  ```python
94
120
  from playwright.sync_api import sync_playwright
@@ -100,16 +126,19 @@ endpoint_url = sb.get_endpoint_url()
100
126
  with sync_playwright() as p:
101
127
  browser = p.chromium.connect_over_cdp(endpoint_url)
102
128
  page = browser.contexts[0].pages[0]
103
- page.goto("https://www.browserscan.net/bot-detection")
129
+ page.goto("https://browserscan.net/bot-detection")
104
130
  page.wait_for_timeout(500)
105
- sb.flash("Test Results", duration=3, pause=1)
131
+ sb.flash("Test Results", duration=1.5, pause=0.5)
106
132
  sb.assert_element('strong:contains("Normal")')
107
- sb.flash('strong:contains("Normal")', duration=3, pause=2)
133
+ print("Bot Not Detected")
134
+ sb.flash('strong:contains("Normal")', pause=1)
108
135
  ```
109
136
 
110
137
  --------
111
138
 
112
- For choosing which Chromium browser to use, you can set command-line options:
139
+ <h3 align="left">🌐 CLI Options for Supported Chromium Browsers</h3>
140
+
141
+ 💡 You can set which Chromium browser to use via command-line options:
113
142
 
114
143
  ```zsh
115
144
  python SCRIPT.py --use-chromium # Use the unbranded Chromium browser
@@ -118,7 +147,13 @@ python SCRIPT.py --edge # Use Microsoft Edge
118
147
  python SCRIPT.py --brave # Use Brave browser
119
148
  ```
120
149
 
121
- (Google Chrome is the default browser if not specified.)
150
+ Google Chrome is the default browser if not specified. Only unbranded Chromium and Chrome-for-Testing are installed automatically if not already installed.
151
+
152
+ You can also set the browser via method args, eg: `cft=True`, `use_chromium=True`, `browser="edge"`, `browser="brave"`, etc. Eg:
153
+
154
+ ```python
155
+ sb = sb_cdp.Chrome(url, use_chromium=True)
156
+ ```
122
157
 
123
158
  --------
124
159
 
@@ -5,7 +5,7 @@ setuptools~=70.2;python_version<"3.10"
5
5
  setuptools>=82.0.1;python_version>="3.10"
6
6
  wheel>=0.47.0
7
7
  attrs>=26.1.0
8
- certifi>=2026.4.22
8
+ certifi>=2026.5.20
9
9
  exceptiongroup>=1.3.1
10
10
  websockets~=15.0.1;python_version<"3.10"
11
11
  websockets>=16.0;python_version>="3.10"
@@ -24,12 +24,13 @@ six>=1.17.0
24
24
  parse>=1.22.0
25
25
  parse-type>=0.6.6
26
26
  colorama>=0.4.6
27
+ psutil>=7.2.2
27
28
  pyyaml>=6.0.3
28
29
  pygments>=2.20.0
29
30
  pyreadline3>=3.5.4;platform_system=="Windows"
30
31
  tabcompleter>=1.4.1
31
32
  pdbp>=1.8.2
32
- idna>=3.15
33
+ idna>=3.16
33
34
  charset-normalizer>=3.4.7,<4
34
35
  urllib3>=1.26.20,<2;python_version<"3.10"
35
36
  urllib3>=2.7.0,<3;python_version>="3.10"
@@ -1,2 +1,2 @@
1
1
  # seleniumbase package
2
- __version__ = "4.49.0"
2
+ __version__ = "4.49.2"
@@ -176,8 +176,11 @@ def extend_driver(
176
176
  driver.forward = DM.forward
177
177
  driver.refresh = DM.refresh
178
178
  driver.locator = DM.locator
179
+ driver.select = DM.select
180
+ driver.select_all = DM.select_all
179
181
  page = types.SimpleNamespace()
180
182
  page.open = DM.open_url
183
+ page.goto = DM.open_url
181
184
  page.click = DM.click
182
185
  page.click_link = DM.click_link
183
186
  page.click_if_visible = DM.click_if_visible
@@ -210,6 +213,8 @@ def extend_driver(
210
213
  page.find_element = DM.find_element
211
214
  page.find_elements = DM.find_elements
212
215
  page.locator = DM.locator
216
+ page.select = DM.select
217
+ page.select_all = DM.select_all
213
218
  page.get_current_url = DM.get_current_url
214
219
  page.get_page_source = DM.get_page_source
215
220
  page.get_title = DM.get_title
@@ -231,6 +236,7 @@ def extend_driver(
231
236
  js.highlight = DM.highlight
232
237
  driver.js = js
233
238
  driver.open = DM.open_url
239
+ driver.goto = DM.open_url
234
240
  driver.click = DM.click
235
241
  driver.click_link = DM.click_link
236
242
  driver.click_if_visible = DM.click_if_visible
@@ -291,6 +297,7 @@ def extend_driver(
291
297
  driver.switch_to_default_window = DM.switch_to_default_window
292
298
  driver.switch_to_newest_window = DM.switch_to_newest_window
293
299
  driver.open_new_window = DM.open_new_window
300
+ driver.switch_to_newest_tab = DM.switch_to_newest_tab
294
301
  driver.open_new_tab = DM.open_new_tab
295
302
  driver.switch_to_window = DM.switch_to_window
296
303
  driver.switch_to_tab = DM.switch_to_tab
@@ -759,6 +766,7 @@ def uc_open_with_cdp_mode(driver, url=None, **kwargs):
759
766
  CDPM = sb_cdp.CDPMethods(loop, page, driver)
760
767
  cdp.get = CDPM.get
761
768
  cdp.open = CDPM.open
769
+ cdp.goto = CDPM.goto
762
770
  cdp.reload = CDPM.reload
763
771
  cdp.refresh = CDPM.refresh
764
772
  cdp.add_handler = CDPM.add_handler
@@ -972,6 +980,7 @@ def uc_open_with_cdp_mode(driver, url=None, **kwargs):
972
980
  driver.solve_captcha = CDPM.solve_captcha
973
981
  driver.click_captcha = CDPM.click_captcha
974
982
  driver.find_element_by_text = CDPM.find_element_by_text
983
+ driver.flash = CDPM.flash
975
984
  driver._is_using_cdp = True
976
985
  if (
977
986
  getattr(sb_config, "_cdp_proxy", None)
@@ -155,6 +155,9 @@ class CDPMethods():
155
155
  def open(self, url, **kwargs):
156
156
  self.get(url, **kwargs)
157
157
 
158
+ def goto(self, url, **kwargs):
159
+ self.get(url, **kwargs)
160
+
158
161
  def reload(self, ignore_cache=True, script_to_evaluate_on_load=None):
159
162
  self.loop.run_until_complete(
160
163
  self.page.reload(
@@ -2033,6 +2036,13 @@ class CDPMethods():
2033
2036
  self.__slow_mode_pause_if_set()
2034
2037
  self.loop.run_until_complete(self.page.wait(0.2))
2035
2038
 
2039
+ def quit(self):
2040
+ """Quit the browser in the Pure CDP Mode Sync format."""
2041
+ driver = self.driver
2042
+ if hasattr(driver, "cdp_base"):
2043
+ driver = driver.cdp_base
2044
+ driver.quit()
2045
+
2036
2046
  def _on_a_cf_turnstile_page(self, source=None):
2037
2047
  if not source or len(source) < 400:
2038
2048
  time.sleep(0.2)
@@ -2325,28 +2335,22 @@ class CDPMethods():
2325
2335
  'form div:not([class]):has(input[name*="cf-turn"])'
2326
2336
  ):
2327
2337
  selector = 'form div:not([class]):has(input[name*="cf-turn"])'
2328
- elif self.is_element_present("form div:not(:has(*))"):
2329
- selector = "form div:not(:has(*))"
2330
2338
  elif self.is_element_present("body > div#check > div:not([class])"):
2331
2339
  selector = "body > div#check > div:not([class])"
2332
2340
  elif self.is_element_present(".cf-turnstile-wrapper"):
2333
2341
  selector = ".cf-turnstile-wrapper"
2334
- elif self.is_element_present(
2335
- '[id*="turnstile"] div:not([class])'
2336
- ):
2342
+ elif self.is_element_present('[id*="turnstile"] div:not([class])'):
2337
2343
  selector = '[id*="turnstile"] div:not([class])'
2338
- elif self.is_element_present(
2339
- '[class*="turnstile"] div:not([class])'
2340
- ):
2344
+ elif self.is_element_present('[class*="turnstile"] div:not([class])'):
2341
2345
  selector = '[class*="turnstile"] div:not([class])'
2342
- elif self.is_element_present(
2343
- "iframe[data-hcaptcha-widget-id]"
2344
- ):
2346
+ elif self.is_element_present("iframe[data-hcaptcha-widget-id]"):
2345
2347
  selector = "iframe[data-hcaptcha-widget-id]"
2346
- elif self.is_element_present(
2347
- '[data-callback="onCaptchaSuccess"]'
2348
- ):
2348
+ elif self.is_element_present('[data-callback="onCaptchaSuccess"]'):
2349
2349
  selector = '[data-callback="onCaptchaSuccess"]'
2350
+ elif self.is_element_present('[class*="captcha"] div:not([class])'):
2351
+ selector = '[class*="captcha"] div:not([class])'
2352
+ elif self.is_element_present("form div:not(:has(*))"):
2353
+ selector = "form div:not(:has(*))"
2350
2354
  elif self.is_element_present(
2351
2355
  "div:not([class]):not([id]):not([aria-label]) > "
2352
2356
  "div:not([class]):not([id]):not([aria-label])"
@@ -41,6 +41,18 @@ class DriverMethods(WebDriver):
41
41
  value, by = page_utils.swap_selector_and_by_if_reversed(value, by)
42
42
  return self.driver.default_find_elements(by=by, value=value)
43
43
 
44
+ def select(self, *args, **kwargs):
45
+ if self.__is_cdp_swap_needed():
46
+ return self.driver.cdp.select(*args, **kwargs)
47
+ else:
48
+ return self.find_element(*args, **kwargs)
49
+
50
+ def select_all(self, *args, **kwargs):
51
+ if self.__is_cdp_swap_needed():
52
+ return self.driver.cdp.select_all(*args, **kwargs)
53
+ else:
54
+ return self.find_elements(*args, **kwargs)
55
+
44
56
  def add_cookie(self, *args, **kwargs):
45
57
  page_actions._reconnect_if_disconnected(self.driver)
46
58
  self.driver.default_add_cookie(*args, **kwargs)
@@ -372,6 +384,12 @@ class DriverMethods(WebDriver):
372
384
  def switch_to_window(self, *args, **kwargs):
373
385
  page_actions.switch_to_window(self.driver, *args, **kwargs)
374
386
 
387
+ def switch_to_newest_tab(self):
388
+ if self.__is_cdp_swap_needed():
389
+ self.driver.cdp.switch_to_newest_tab()
390
+ return
391
+ self.switch_to_newest_window()
392
+
375
393
  def switch_to_tab(self, *args, **kwargs):
376
394
  self.switch_to_window(*args, **kwargs)
377
395
 
@@ -5096,8 +5096,32 @@ class BaseCase(unittest.TestCase):
5096
5096
  self.solve_captcha = self.cdp.solve_captcha
5097
5097
  if hasattr(self.cdp, "click_captcha"):
5098
5098
  self.click_captcha = self.cdp.click_captcha
5099
+ if hasattr(self.cdp, "add_handler"):
5100
+ self.add_handler = self.cdp.add_handler
5101
+ if hasattr(self.cdp, "close_active_tab"):
5102
+ self.close_active_tab = self.cdp.close_active_tab
5099
5103
  if hasattr(self.cdp, "find_element_by_text"):
5100
5104
  self.find_element_by_text = self.cdp.find_element_by_text
5105
+ if hasattr(self.cdp, "flash"):
5106
+ self.flash = self.cdp.flash
5107
+ if hasattr(self.cdp, "get_active_tab"):
5108
+ self.get_active_tab = self.cdp.get_active_tab
5109
+ if hasattr(self.cdp, "get_endpoint_url"):
5110
+ self.get_endpoint_url = self.cdp.get_endpoint_url
5111
+ if hasattr(self.cdp, "get_event_loop"):
5112
+ self.get_event_loop = self.cdp.get_event_loop
5113
+ if hasattr(self.cdp, "get_tabs"):
5114
+ self.get_tabs = self.cdp.get_tabs
5115
+ if hasattr(self.cdp, "gui_click_and_hold"):
5116
+ self.gui_click_and_hold = self.cdp.gui_click_and_hold
5117
+ if hasattr(self.cdp, "gui_click_element"):
5118
+ self.gui_click_element = self.cdp.gui_click_element
5119
+ if hasattr(self.cdp, "gui_drag_and_drop"):
5120
+ self.gui_drag_and_drop = self.cdp.gui_drag_and_drop
5121
+ if hasattr(self.cdp, "gui_drag_drop_points"):
5122
+ self.gui_drag_drop_points = self.cdp.gui_drag_drop_points
5123
+ if hasattr(self.cdp, "highlight_overlay"):
5124
+ self.highlight_overlay = self.cdp.highlight_overlay
5101
5125
  if getattr(self.driver, "_is_using_auth", None):
5102
5126
  with suppress(Exception):
5103
5127
  self.cdp.loop.run_until_complete(self.cdp.page.wait(0.25))
@@ -8861,9 +8885,22 @@ class BaseCase(unittest.TestCase):
8861
8885
  element = page_actions.wait_for_element_present(
8862
8886
  self.driver, selector, by, timeout
8863
8887
  )
8864
- if element.tag_name.lower() in ["input", "textarea"]:
8865
- self.js_update_text(selector, text, by=by, timeout=timeout)
8866
- return
8888
+ try:
8889
+ if element.tag_name.lower() in ["input", "textarea"]:
8890
+ self.js_update_text(selector, text, by=by, timeout=timeout)
8891
+ return
8892
+ except (Stale_Exception, ENI_Exception):
8893
+ time.sleep(0.16)
8894
+ if self.__is_cdp_swap_needed():
8895
+ element = self.cdp.select(selector, timeout=timeout)
8896
+ else:
8897
+ self.wait_for_ready_state_complete()
8898
+ element = page_actions.wait_for_element_present(
8899
+ self.driver, selector, by, timeout
8900
+ )
8901
+ if element.tag_name.lower() in ["input", "textarea"]:
8902
+ self.js_update_text(selector, text, by=by, timeout=timeout)
8903
+ return
8867
8904
  original_selector = selector
8868
8905
  css_selector = self.convert_to_css_selector(selector, by=by)
8869
8906
  if scroll:
@@ -9340,6 +9377,9 @@ class BaseCase(unittest.TestCase):
9340
9377
 
9341
9378
  def switch_to_newest_tab(self):
9342
9379
  """Same as self.switch_to_newest_window()"""
9380
+ if self.__is_cdp_swap_needed():
9381
+ self.cdp.switch_to_newest_tab()
9382
+ return
9343
9383
  self.switch_to_newest_window()
9344
9384
 
9345
9385
  def save_as_html(self, name, folder=None):
@@ -9976,6 +10016,8 @@ class BaseCase(unittest.TestCase):
9976
10016
  self, selector, by="css selector", timeout=None
9977
10017
  ):
9978
10018
  """Waits for an element to appear in the HTML of a page.
10019
+ Returns the element once it exists in the HTML.
10020
+ Raises an exception if the element doesn't come in time.
9979
10021
  The element does not need be visible (it may be hidden)."""
9980
10022
  self.__check_scope()
9981
10023
  if not timeout:
@@ -10022,6 +10064,19 @@ class BaseCase(unittest.TestCase):
10022
10064
  self.driver, selector, by, timeout
10023
10065
  )
10024
10066
 
10067
+ def select(self, selector, by="css selector", timeout=None):
10068
+ """Returns the element once it appears in the HTML.
10069
+ Raises an exception if the element doesn't come in time.
10070
+ The element does not need be visible (it may be hidden).
10071
+ If CDP Mode has been activated: Calls self.cdp.select().
10072
+ Otherwise: Same as self.wait_for_element_present()."""
10073
+ if self.__is_cdp_swap_needed():
10074
+ return self.cdp.select(selector, timeout=timeout)
10075
+ else:
10076
+ return self.wait_for_element_present(
10077
+ selector, by=by, timeout=timeout
10078
+ )
10079
+
10025
10080
  def get_element(self, selector, by="css selector", timeout=None):
10026
10081
  """Same as wait_for_element_present() - returns the element.
10027
10082
  The element does not need be visible (it may be hidden)."""