seleniumbase 4.47.3__tar.gz → 4.47.5__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 (162) hide show
  1. {seleniumbase-4.47.3/seleniumbase.egg-info → seleniumbase-4.47.5}/PKG-INFO +46 -36
  2. {seleniumbase-4.47.3 → seleniumbase-4.47.5}/README.md +40 -30
  3. {seleniumbase-4.47.3 → seleniumbase-4.47.5}/requirements.txt +5 -5
  4. {seleniumbase-4.47.3 → seleniumbase-4.47.5}/seleniumbase/__version__.py +1 -1
  5. {seleniumbase-4.47.3 → seleniumbase-4.47.5}/seleniumbase/core/browser_launcher.py +1 -0
  6. {seleniumbase-4.47.3 → seleniumbase-4.47.5}/seleniumbase/core/sb_cdp.py +4 -4
  7. {seleniumbase-4.47.3 → seleniumbase-4.47.5}/seleniumbase/fixtures/page_actions.py +1 -1
  8. {seleniumbase-4.47.3 → seleniumbase-4.47.5}/seleniumbase/undetected/cdp_driver/browser.py +22 -10
  9. {seleniumbase-4.47.3 → seleniumbase-4.47.5}/seleniumbase/undetected/cdp_driver/cdp_util.py +21 -13
  10. {seleniumbase-4.47.3 → seleniumbase-4.47.5}/seleniumbase/undetected/cdp_driver/tab.py +7 -7
  11. {seleniumbase-4.47.3 → seleniumbase-4.47.5/seleniumbase.egg-info}/PKG-INFO +46 -36
  12. {seleniumbase-4.47.3 → seleniumbase-4.47.5}/seleniumbase.egg-info/requires.txt +5 -5
  13. {seleniumbase-4.47.3 → seleniumbase-4.47.5}/setup.py +5 -5
  14. {seleniumbase-4.47.3 → seleniumbase-4.47.5}/.gitignore +0 -0
  15. {seleniumbase-4.47.3 → seleniumbase-4.47.5}/LICENSE +0 -0
  16. {seleniumbase-4.47.3 → seleniumbase-4.47.5}/MANIFEST.in +0 -0
  17. {seleniumbase-4.47.3 → seleniumbase-4.47.5}/install.sh +0 -0
  18. {seleniumbase-4.47.3 → seleniumbase-4.47.5}/pyproject.toml +0 -0
  19. {seleniumbase-4.47.3 → seleniumbase-4.47.5}/pytest.ini +0 -0
  20. {seleniumbase-4.47.3 → seleniumbase-4.47.5}/sbase/__init__.py +0 -0
  21. {seleniumbase-4.47.3 → seleniumbase-4.47.5}/sbase/__main__.py +0 -0
  22. {seleniumbase-4.47.3 → seleniumbase-4.47.5}/sbase/steps.py +0 -0
  23. {seleniumbase-4.47.3 → seleniumbase-4.47.5}/seleniumbase/__init__.py +0 -0
  24. {seleniumbase-4.47.3 → seleniumbase-4.47.5}/seleniumbase/__main__.py +0 -0
  25. {seleniumbase-4.47.3 → seleniumbase-4.47.5}/seleniumbase/behave/__init__.py +0 -0
  26. {seleniumbase-4.47.3 → seleniumbase-4.47.5}/seleniumbase/behave/behave_helper.py +0 -0
  27. {seleniumbase-4.47.3 → seleniumbase-4.47.5}/seleniumbase/behave/behave_sb.py +0 -0
  28. {seleniumbase-4.47.3 → seleniumbase-4.47.5}/seleniumbase/behave/steps.py +0 -0
  29. {seleniumbase-4.47.3 → seleniumbase-4.47.5}/seleniumbase/common/__init__.py +0 -0
  30. {seleniumbase-4.47.3 → seleniumbase-4.47.5}/seleniumbase/common/decorators.py +0 -0
  31. {seleniumbase-4.47.3 → seleniumbase-4.47.5}/seleniumbase/common/encryption.py +0 -0
  32. {seleniumbase-4.47.3 → seleniumbase-4.47.5}/seleniumbase/common/exceptions.py +0 -0
  33. {seleniumbase-4.47.3 → seleniumbase-4.47.5}/seleniumbase/common/obfuscate.py +0 -0
  34. {seleniumbase-4.47.3 → seleniumbase-4.47.5}/seleniumbase/common/unobfuscate.py +0 -0
  35. {seleniumbase-4.47.3 → seleniumbase-4.47.5}/seleniumbase/config/__init__.py +0 -0
  36. {seleniumbase-4.47.3 → seleniumbase-4.47.5}/seleniumbase/config/ad_block_list.py +0 -0
  37. {seleniumbase-4.47.3 → seleniumbase-4.47.5}/seleniumbase/config/proxy_list.py +0 -0
  38. {seleniumbase-4.47.3 → seleniumbase-4.47.5}/seleniumbase/config/settings.py +0 -0
  39. {seleniumbase-4.47.3 → seleniumbase-4.47.5}/seleniumbase/console_scripts/__init__.py +0 -0
  40. {seleniumbase-4.47.3 → seleniumbase-4.47.5}/seleniumbase/console_scripts/logo_helper.py +0 -0
  41. {seleniumbase-4.47.3 → seleniumbase-4.47.5}/seleniumbase/console_scripts/rich_helper.py +0 -0
  42. {seleniumbase-4.47.3 → seleniumbase-4.47.5}/seleniumbase/console_scripts/run.py +0 -0
  43. {seleniumbase-4.47.3 → seleniumbase-4.47.5}/seleniumbase/console_scripts/sb_behave_gui.py +0 -0
  44. {seleniumbase-4.47.3 → seleniumbase-4.47.5}/seleniumbase/console_scripts/sb_caseplans.py +0 -0
  45. {seleniumbase-4.47.3 → seleniumbase-4.47.5}/seleniumbase/console_scripts/sb_commander.py +0 -0
  46. {seleniumbase-4.47.3 → seleniumbase-4.47.5}/seleniumbase/console_scripts/sb_install.py +0 -0
  47. {seleniumbase-4.47.3 → seleniumbase-4.47.5}/seleniumbase/console_scripts/sb_mkchart.py +0 -0
  48. {seleniumbase-4.47.3 → seleniumbase-4.47.5}/seleniumbase/console_scripts/sb_mkdir.py +0 -0
  49. {seleniumbase-4.47.3 → seleniumbase-4.47.5}/seleniumbase/console_scripts/sb_mkfile.py +0 -0
  50. {seleniumbase-4.47.3 → seleniumbase-4.47.5}/seleniumbase/console_scripts/sb_mkpres.py +0 -0
  51. {seleniumbase-4.47.3 → seleniumbase-4.47.5}/seleniumbase/console_scripts/sb_mkrec.py +0 -0
  52. {seleniumbase-4.47.3 → seleniumbase-4.47.5}/seleniumbase/console_scripts/sb_objectify.py +0 -0
  53. {seleniumbase-4.47.3 → seleniumbase-4.47.5}/seleniumbase/console_scripts/sb_print.py +0 -0
  54. {seleniumbase-4.47.3 → seleniumbase-4.47.5}/seleniumbase/console_scripts/sb_recorder.py +0 -0
  55. {seleniumbase-4.47.3 → seleniumbase-4.47.5}/seleniumbase/core/__init__.py +0 -0
  56. {seleniumbase-4.47.3 → seleniumbase-4.47.5}/seleniumbase/core/application_manager.py +0 -0
  57. {seleniumbase-4.47.3 → seleniumbase-4.47.5}/seleniumbase/core/capabilities_parser.py +0 -0
  58. {seleniumbase-4.47.3 → seleniumbase-4.47.5}/seleniumbase/core/colored_traceback.py +0 -0
  59. {seleniumbase-4.47.3 → seleniumbase-4.47.5}/seleniumbase/core/create_db_tables.sql +0 -0
  60. {seleniumbase-4.47.3 → seleniumbase-4.47.5}/seleniumbase/core/detect_b_ver.py +0 -0
  61. {seleniumbase-4.47.3 → seleniumbase-4.47.5}/seleniumbase/core/download_helper.py +0 -0
  62. {seleniumbase-4.47.3 → seleniumbase-4.47.5}/seleniumbase/core/encoded_images.py +0 -0
  63. {seleniumbase-4.47.3 → seleniumbase-4.47.5}/seleniumbase/core/jqc_helper.py +0 -0
  64. {seleniumbase-4.47.3 → seleniumbase-4.47.5}/seleniumbase/core/log_helper.py +0 -0
  65. {seleniumbase-4.47.3 → seleniumbase-4.47.5}/seleniumbase/core/mysql.py +0 -0
  66. {seleniumbase-4.47.3 → seleniumbase-4.47.5}/seleniumbase/core/proxy_helper.py +0 -0
  67. {seleniumbase-4.47.3 → seleniumbase-4.47.5}/seleniumbase/core/recorder_helper.py +0 -0
  68. {seleniumbase-4.47.3 → seleniumbase-4.47.5}/seleniumbase/core/report_helper.py +0 -0
  69. {seleniumbase-4.47.3 → seleniumbase-4.47.5}/seleniumbase/core/s3_manager.py +0 -0
  70. {seleniumbase-4.47.3 → seleniumbase-4.47.5}/seleniumbase/core/sb_driver.py +0 -0
  71. {seleniumbase-4.47.3 → seleniumbase-4.47.5}/seleniumbase/core/session_helper.py +0 -0
  72. {seleniumbase-4.47.3 → seleniumbase-4.47.5}/seleniumbase/core/settings_parser.py +0 -0
  73. {seleniumbase-4.47.3 → seleniumbase-4.47.5}/seleniumbase/core/style_sheet.py +0 -0
  74. {seleniumbase-4.47.3 → seleniumbase-4.47.5}/seleniumbase/core/testcase_manager.py +0 -0
  75. {seleniumbase-4.47.3 → seleniumbase-4.47.5}/seleniumbase/core/tour_helper.py +0 -0
  76. {seleniumbase-4.47.3 → seleniumbase-4.47.5}/seleniumbase/core/visual_helper.py +0 -0
  77. {seleniumbase-4.47.3 → seleniumbase-4.47.5}/seleniumbase/drivers/__init__.py +0 -0
  78. {seleniumbase-4.47.3 → seleniumbase-4.47.5}/seleniumbase/drivers/atlas_drivers/__init__.py +0 -0
  79. {seleniumbase-4.47.3 → seleniumbase-4.47.5}/seleniumbase/drivers/brave_drivers/__init__.py +0 -0
  80. {seleniumbase-4.47.3 → seleniumbase-4.47.5}/seleniumbase/drivers/cft_drivers/__init__.py +0 -0
  81. {seleniumbase-4.47.3 → seleniumbase-4.47.5}/seleniumbase/drivers/chromium_drivers/__init__.py +0 -0
  82. {seleniumbase-4.47.3 → seleniumbase-4.47.5}/seleniumbase/drivers/chs_drivers/__init__.py +0 -0
  83. {seleniumbase-4.47.3 → seleniumbase-4.47.5}/seleniumbase/drivers/comet_drivers/__init__.py +0 -0
  84. {seleniumbase-4.47.3 → seleniumbase-4.47.5}/seleniumbase/drivers/opera_drivers/__init__.py +0 -0
  85. {seleniumbase-4.47.3 → seleniumbase-4.47.5}/seleniumbase/extensions/__init__.py +0 -0
  86. {seleniumbase-4.47.3 → seleniumbase-4.47.5}/seleniumbase/extensions/ad_block.zip +0 -0
  87. {seleniumbase-4.47.3 → seleniumbase-4.47.5}/seleniumbase/extensions/disable_csp.zip +0 -0
  88. {seleniumbase-4.47.3 → seleniumbase-4.47.5}/seleniumbase/extensions/recorder.zip +0 -0
  89. {seleniumbase-4.47.3 → seleniumbase-4.47.5}/seleniumbase/extensions/sbase_ext.zip +0 -0
  90. {seleniumbase-4.47.3 → seleniumbase-4.47.5}/seleniumbase/fixtures/__init__.py +0 -0
  91. {seleniumbase-4.47.3 → seleniumbase-4.47.5}/seleniumbase/fixtures/base_case.py +0 -0
  92. {seleniumbase-4.47.3 → seleniumbase-4.47.5}/seleniumbase/fixtures/constants.py +0 -0
  93. {seleniumbase-4.47.3 → seleniumbase-4.47.5}/seleniumbase/fixtures/css_to_xpath.py +0 -0
  94. {seleniumbase-4.47.3 → seleniumbase-4.47.5}/seleniumbase/fixtures/errors.py +0 -0
  95. {seleniumbase-4.47.3 → seleniumbase-4.47.5}/seleniumbase/fixtures/js_utils.py +0 -0
  96. {seleniumbase-4.47.3 → seleniumbase-4.47.5}/seleniumbase/fixtures/page_utils.py +0 -0
  97. {seleniumbase-4.47.3 → seleniumbase-4.47.5}/seleniumbase/fixtures/shared_utils.py +0 -0
  98. {seleniumbase-4.47.3 → seleniumbase-4.47.5}/seleniumbase/fixtures/unittest_helper.py +0 -0
  99. {seleniumbase-4.47.3 → seleniumbase-4.47.5}/seleniumbase/fixtures/words.py +0 -0
  100. {seleniumbase-4.47.3 → seleniumbase-4.47.5}/seleniumbase/fixtures/xpath_to_css.py +0 -0
  101. {seleniumbase-4.47.3 → seleniumbase-4.47.5}/seleniumbase/js_code/__init__.py +0 -0
  102. {seleniumbase-4.47.3 → seleniumbase-4.47.5}/seleniumbase/js_code/active_css_js.py +0 -0
  103. {seleniumbase-4.47.3 → seleniumbase-4.47.5}/seleniumbase/js_code/live_js.py +0 -0
  104. {seleniumbase-4.47.3 → seleniumbase-4.47.5}/seleniumbase/js_code/recorder_js.py +0 -0
  105. {seleniumbase-4.47.3 → seleniumbase-4.47.5}/seleniumbase/masterqa/__init__.py +0 -0
  106. {seleniumbase-4.47.3 → seleniumbase-4.47.5}/seleniumbase/masterqa/master_qa.py +0 -0
  107. {seleniumbase-4.47.3 → seleniumbase-4.47.5}/seleniumbase/plugins/__init__.py +0 -0
  108. {seleniumbase-4.47.3 → seleniumbase-4.47.5}/seleniumbase/plugins/base_plugin.py +0 -0
  109. {seleniumbase-4.47.3 → seleniumbase-4.47.5}/seleniumbase/plugins/basic_test_info.py +0 -0
  110. {seleniumbase-4.47.3 → seleniumbase-4.47.5}/seleniumbase/plugins/db_reporting_plugin.py +0 -0
  111. {seleniumbase-4.47.3 → seleniumbase-4.47.5}/seleniumbase/plugins/driver_manager.py +0 -0
  112. {seleniumbase-4.47.3 → seleniumbase-4.47.5}/seleniumbase/plugins/page_source.py +0 -0
  113. {seleniumbase-4.47.3 → seleniumbase-4.47.5}/seleniumbase/plugins/pytest_plugin.py +0 -0
  114. {seleniumbase-4.47.3 → seleniumbase-4.47.5}/seleniumbase/plugins/s3_logging_plugin.py +0 -0
  115. {seleniumbase-4.47.3 → seleniumbase-4.47.5}/seleniumbase/plugins/sb_manager.py +0 -0
  116. {seleniumbase-4.47.3 → seleniumbase-4.47.5}/seleniumbase/plugins/screen_shots.py +0 -0
  117. {seleniumbase-4.47.3 → seleniumbase-4.47.5}/seleniumbase/plugins/selenium_plugin.py +0 -0
  118. {seleniumbase-4.47.3 → seleniumbase-4.47.5}/seleniumbase/resources/__init__.py +0 -0
  119. {seleniumbase-4.47.3 → seleniumbase-4.47.5}/seleniumbase/translate/__init__.py +0 -0
  120. {seleniumbase-4.47.3 → seleniumbase-4.47.5}/seleniumbase/translate/chinese.py +0 -0
  121. {seleniumbase-4.47.3 → seleniumbase-4.47.5}/seleniumbase/translate/dutch.py +0 -0
  122. {seleniumbase-4.47.3 → seleniumbase-4.47.5}/seleniumbase/translate/french.py +0 -0
  123. {seleniumbase-4.47.3 → seleniumbase-4.47.5}/seleniumbase/translate/italian.py +0 -0
  124. {seleniumbase-4.47.3 → seleniumbase-4.47.5}/seleniumbase/translate/japanese.py +0 -0
  125. {seleniumbase-4.47.3 → seleniumbase-4.47.5}/seleniumbase/translate/korean.py +0 -0
  126. {seleniumbase-4.47.3 → seleniumbase-4.47.5}/seleniumbase/translate/master_dict.py +0 -0
  127. {seleniumbase-4.47.3 → seleniumbase-4.47.5}/seleniumbase/translate/portuguese.py +0 -0
  128. {seleniumbase-4.47.3 → seleniumbase-4.47.5}/seleniumbase/translate/russian.py +0 -0
  129. {seleniumbase-4.47.3 → seleniumbase-4.47.5}/seleniumbase/translate/spanish.py +0 -0
  130. {seleniumbase-4.47.3 → seleniumbase-4.47.5}/seleniumbase/translate/translator.py +0 -0
  131. {seleniumbase-4.47.3 → seleniumbase-4.47.5}/seleniumbase/undetected/__init__.py +0 -0
  132. {seleniumbase-4.47.3 → seleniumbase-4.47.5}/seleniumbase/undetected/cdp.py +0 -0
  133. {seleniumbase-4.47.3 → seleniumbase-4.47.5}/seleniumbase/undetected/cdp_driver/__init__.py +0 -0
  134. {seleniumbase-4.47.3 → seleniumbase-4.47.5}/seleniumbase/undetected/cdp_driver/_contradict.py +0 -0
  135. {seleniumbase-4.47.3 → seleniumbase-4.47.5}/seleniumbase/undetected/cdp_driver/config.py +0 -0
  136. {seleniumbase-4.47.3 → seleniumbase-4.47.5}/seleniumbase/undetected/cdp_driver/connection.py +0 -0
  137. {seleniumbase-4.47.3 → seleniumbase-4.47.5}/seleniumbase/undetected/cdp_driver/element.py +0 -0
  138. {seleniumbase-4.47.3 → seleniumbase-4.47.5}/seleniumbase/undetected/dprocess.py +0 -0
  139. {seleniumbase-4.47.3 → seleniumbase-4.47.5}/seleniumbase/undetected/options.py +0 -0
  140. {seleniumbase-4.47.3 → seleniumbase-4.47.5}/seleniumbase/undetected/patcher.py +0 -0
  141. {seleniumbase-4.47.3 → seleniumbase-4.47.5}/seleniumbase/undetected/reactor.py +0 -0
  142. {seleniumbase-4.47.3 → seleniumbase-4.47.5}/seleniumbase/undetected/webelement.py +0 -0
  143. {seleniumbase-4.47.3 → seleniumbase-4.47.5}/seleniumbase/utilities/__init__.py +0 -0
  144. {seleniumbase-4.47.3 → seleniumbase-4.47.5}/seleniumbase/utilities/selenium_grid/__init__.py +0 -0
  145. {seleniumbase-4.47.3 → seleniumbase-4.47.5}/seleniumbase/utilities/selenium_grid/download_selenium_server.py +0 -0
  146. {seleniumbase-4.47.3 → seleniumbase-4.47.5}/seleniumbase/utilities/selenium_grid/font_color +0 -0
  147. {seleniumbase-4.47.3 → seleniumbase-4.47.5}/seleniumbase/utilities/selenium_grid/grid-hub +0 -0
  148. {seleniumbase-4.47.3 → seleniumbase-4.47.5}/seleniumbase/utilities/selenium_grid/grid-node +0 -0
  149. {seleniumbase-4.47.3 → seleniumbase-4.47.5}/seleniumbase/utilities/selenium_grid/grid_hub.py +0 -0
  150. {seleniumbase-4.47.3 → seleniumbase-4.47.5}/seleniumbase/utilities/selenium_grid/grid_node.py +0 -0
  151. {seleniumbase-4.47.3 → seleniumbase-4.47.5}/seleniumbase/utilities/selenium_grid/register-grid-node.bat +0 -0
  152. {seleniumbase-4.47.3 → seleniumbase-4.47.5}/seleniumbase/utilities/selenium_grid/register-grid-node.sh +0 -0
  153. {seleniumbase-4.47.3 → seleniumbase-4.47.5}/seleniumbase/utilities/selenium_grid/start-grid-hub.bat +0 -0
  154. {seleniumbase-4.47.3 → seleniumbase-4.47.5}/seleniumbase/utilities/selenium_grid/start-grid-hub.sh +0 -0
  155. {seleniumbase-4.47.3 → seleniumbase-4.47.5}/seleniumbase/utilities/selenium_ide/__init__.py +0 -0
  156. {seleniumbase-4.47.3 → seleniumbase-4.47.5}/seleniumbase/utilities/selenium_ide/convert_ide.py +0 -0
  157. {seleniumbase-4.47.3 → seleniumbase-4.47.5}/seleniumbase.egg-info/SOURCES.txt +0 -0
  158. {seleniumbase-4.47.3 → seleniumbase-4.47.5}/seleniumbase.egg-info/dependency_links.txt +0 -0
  159. {seleniumbase-4.47.3 → seleniumbase-4.47.5}/seleniumbase.egg-info/entry_points.txt +0 -0
  160. {seleniumbase-4.47.3 → seleniumbase-4.47.5}/seleniumbase.egg-info/top_level.txt +0 -0
  161. {seleniumbase-4.47.3 → seleniumbase-4.47.5}/setup.cfg +0 -0
  162. {seleniumbase-4.47.3 → seleniumbase-4.47.5}/virtualenv_install.sh +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: seleniumbase
3
- Version: 4.47.3
3
+ Version: 4.47.5
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
@@ -63,7 +63,7 @@ Requires-Dist: packaging>=26.0
63
63
  Requires-Dist: setuptools~=70.2; python_version < "3.10"
64
64
  Requires-Dist: setuptools>=82.0.1; python_version >= "3.10"
65
65
  Requires-Dist: wheel>=0.46.3
66
- Requires-Dist: attrs>=25.4.0
66
+ Requires-Dist: attrs>=26.1.0
67
67
  Requires-Dist: certifi>=2026.2.25
68
68
  Requires-Dist: exceptiongroup>=1.3.1
69
69
  Requires-Dist: websockets~=15.0.1; python_version < "3.10"
@@ -71,7 +71,7 @@ Requires-Dist: websockets>=16.0; python_version >= "3.10"
71
71
  Requires-Dist: filelock~=3.19.1; python_version < "3.10"
72
72
  Requires-Dist: filelock>=3.25.2; python_version >= "3.10"
73
73
  Requires-Dist: fasteners>=0.20
74
- Requires-Dist: mycdp>=1.3.4
74
+ Requires-Dist: mycdp>=1.3.7
75
75
  Requires-Dist: pynose>=1.5.5
76
76
  Requires-Dist: platformdirs~=4.4.0; python_version < "3.10"
77
77
  Requires-Dist: platformdirs>=4.9.4; python_version >= "3.10"
@@ -89,7 +89,7 @@ Requires-Dist: pyreadline3>=3.5.4; platform_system == "Windows"
89
89
  Requires-Dist: tabcompleter>=1.4.0
90
90
  Requires-Dist: pdbp>=1.8.2
91
91
  Requires-Dist: idna>=3.11
92
- Requires-Dist: charset-normalizer<4,>=3.4.5
92
+ Requires-Dist: charset-normalizer<4,>=3.4.6
93
93
  Requires-Dist: urllib3<2,>=1.26.20; python_version < "3.10"
94
94
  Requires-Dist: urllib3<3,>=1.26.20; python_version >= "3.10"
95
95
  Requires-Dist: requests~=2.32.5
@@ -138,8 +138,8 @@ Requires-Dist: allure-python-commons>=2.13.5; extra == "allure"
138
138
  Requires-Dist: allure-behave>=2.13.5; extra == "allure"
139
139
  Provides-Extra: coverage
140
140
  Requires-Dist: coverage>=7.10.7; python_version < "3.10" and extra == "coverage"
141
- Requires-Dist: coverage>=7.13.4; python_version >= "3.10" and extra == "coverage"
142
- Requires-Dist: pytest-cov>=7.0.0; extra == "coverage"
141
+ Requires-Dist: coverage>=7.13.5; python_version >= "3.10" and extra == "coverage"
142
+ Requires-Dist: pytest-cov>=7.1.0; extra == "coverage"
143
143
  Provides-Extra: flake8
144
144
  Requires-Dist: flake8==7.3.0; extra == "flake8"
145
145
  Requires-Dist: mccabe==0.7.0; extra == "flake8"
@@ -209,7 +209,7 @@ Dynamic: summary
209
209
 
210
210
  <h1>SeleniumBase</h1>
211
211
 
212
- <p align="center"><a href="https://github.com/seleniumbase/SeleniumBase/"><img src="https://seleniumbase.github.io/cdn/img/super_logo_sb3.png" alt="SeleniumBase" title="SeleniumBase" width="350" /></a></p>
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>
213
213
 
214
214
  <p align="center" class="hero__title"><b>All-in-one Browser Automation Framework:<br />Web Crawling / Testing / Scraping / Stealth</b></p>
215
215
 
@@ -252,17 +252,39 @@ Dynamic: summary
252
252
  <br />
253
253
  </p>
254
254
 
255
- 📊 <a href="https://github.com/seleniumbase/SeleniumBase/"><b translate="no">SeleniumBase</b></a> is a complete framework for web automation, testing, scraping, and stealth. Includes a <a href="https://docs.pytest.org/en/latest/how-to/usage.html">pytest</a> integration for customizing automation from the command-line.
255
+ 📊 <a href="https://github.com/seleniumbase/SeleniumBase/"><b translate="no">SeleniumBase</b></a> is a complete framework for browser automation and testing with Python and <a href="https://docs.pytest.org/en/latest/how-to/usage.html">pytest</a>. Includes stealth options and other advanced features.
256
256
 
257
- 👤 Stealth modes: <a translate="no" href="https://github.com/seleniumbase/SeleniumBase/blob/master/help_docs/uc_mode.md">UC Mode</a> and <a translate="no" href="https://github.com/seleniumbase/SeleniumBase/blob/master/examples/cdp_mode/ReadMe.md"><b>CDP Mode</b></a> can bypass bot-detection, solve CAPTCHAs, and call methods from 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 makes Playwright stealthy via CDP Mode.
257
+ 🐙 Stealth modes: <a translate="no" href="https://github.com/seleniumbase/SeleniumBase/blob/master/help_docs/uc_mode.md">UC Mode</a> and <a translate="no" href="https://github.com/seleniumbase/SeleniumBase/blob/master/examples/cdp_mode/ReadMe.md"><b>CDP Mode</b></a> can bypass bot-detection, handle CAPTCHAs, and call methods from the <a href="https://chromedevtools.github.io/devtools-protocol/" translate="no">Chrome Devtools Protocol</a>. CDP Mode 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 makes Playwright stealthy.
258
258
 
259
- 📚 Example scripts and tests are located in [**SeleniumBase/examples/**](https://github.com/seleniumbase/SeleniumBase/tree/master/examples).
259
+ 📚 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).
260
260
 
261
- 👤 Stealthy example scripts are located in [**SeleniumBase/examples/cdp_mode/**](https://github.com/seleniumbase/SeleniumBase/tree/master/examples/cdp_mode).
261
+ 🥷 Stealthy examples are located in [SeleniumBase/examples/cdp_mode/](https://github.com/seleniumbase/SeleniumBase/tree/master/examples/cdp_mode).
262
262
 
263
263
  --------
264
264
 
265
- <p align="left">📗 This script performs a Google Search using SeleniumBase UC Mode + CDP Mode:<br /><a href="https://github.com/seleniumbase/SeleniumBase/blob/master/examples/raw_google.py">SeleniumBase/examples/raw_google.py</a> (Results are saved as PDF, HTML, and PNG)</p>
265
+ <p align="left">📓 Here's the stealthy architecture overview:</p>
266
+
267
+ <img src="https://seleniumbase.github.io/other/sb_stealth.png" width="596" alt="Stealthy architecture overview" />
268
+
269
+ (For maximum stealth, use <a translate="no" href="https://github.com/seleniumbase/SeleniumBase/blob/master/examples/cdp_mode/ReadMe.md">CDP Mode</a>, which includes <a translate="no" href="https://github.com/seleniumbase/SeleniumBase/blob/master/examples/cdp_mode/playwright/ReadMe.md">Stealthy Playwright Mode</a>)
270
+
271
+ --------
272
+
273
+ <p align="left">📗 <a href="https://github.com/seleniumbase/SeleniumBase/blob/master/examples/cdp_mode/raw_cdp_yc_news.py" target="_blank">This example</a> scrapes Hacker News listings with <a href="https://github.com/seleniumbase/SeleniumBase/blob/master/examples/cdp_mode/ReadMe.md#-pure-cdp-mode-sb_cdp">Pure CDP Mode</a>:
274
+
275
+ ```python
276
+ from seleniumbase import sb_cdp
277
+
278
+ url = "https://news.ycombinator.com/submitted?id=seleniumbase"
279
+ sb = sb_cdp.Chrome(url)
280
+ elements = sb.find_elements("span.titleline > a")
281
+ for element in elements:
282
+ print("* " + element.text)
283
+ ```
284
+
285
+ --------
286
+
287
+ <p align="left">📗 <a href="https://github.com/seleniumbase/SeleniumBase/blob/master/examples/raw_google.py" target="_blank">This example</a> saves Google Search results with UC + CDP Mode:<br />(Results are saved as PDF, HTML, and PNG files)</p>
266
288
 
267
289
  ```python
268
290
  from seleniumbase import SB
@@ -280,13 +302,9 @@ with SB(uc=True, test=True) as sb:
280
302
  print("Logs have been saved to: ./latest_logs/")
281
303
  ```
282
304
 
283
- > `python raw_google.py`
284
-
285
- <a href="https://github.com/seleniumbase/SeleniumBase/blob/master/examples/raw_google.py"><img src="https://seleniumbase.github.io/cdn/img/google_sb_result.jpg" alt="SeleniumBase on Google" title="SeleniumBase on Google" width="580" /></a>
286
-
287
305
  --------
288
306
 
289
- <p align="left">📗 Here's a script that bypasses Cloudflare's challenge page with UC Mode + CDP Mode: <a href="https://github.com/seleniumbase/SeleniumBase/blob/master/examples/cdp_mode/raw_gitlab.py">SeleniumBase/examples/cdp_mode/raw_gitlab.py</a></p>
307
+ <p align="left">📗 <a href="https://github.com/seleniumbase/SeleniumBase/blob/master/examples/cdp_mode/raw_gitlab.py" target="_blank">This example</a> bypasses Cloudflare's challenge page with UC + CDP Mode:
290
308
 
291
309
  ```python
292
310
  from seleniumbase import SB
@@ -304,9 +322,11 @@ with SB(uc=True, test=True, locale="en") as sb:
304
322
  sb.post_message("SeleniumBase wasn't detected", duration=4)
305
323
  ```
306
324
 
307
- <img src="https://seleniumbase.github.io/other/cf_sec.jpg" title="SeleniumBase" width="344"> <img src="https://seleniumbase.github.io/other/gitlab_bypass.png" title="SeleniumBase" width="298">
325
+ <img src="https://seleniumbase.github.io/other/cf_sec.jpg" alt="SeleniumBase" width="344"> <img src="https://seleniumbase.github.io/other/gitlab_bypass.png" alt="SeleniumBase" width="298">
326
+
327
+ ----
308
328
 
309
- <p align="left">📙 There's also SeleniumBase's "Pure CDP Mode", which doesn't use WebDriver or Selenium at all: <a href="https://github.com/seleniumbase/SeleniumBase/blob/master/examples/cdp_mode/raw_cdp_gitlab.py">SeleniumBase/examples/cdp_mode/raw_cdp_gitlab.py</a></p>
329
+ <p align="left">📗 <a href="https://github.com/seleniumbase/SeleniumBase/blob/master/examples/cdp_mode/raw_cdp_gitlab.py" target="_blank">This example</a> handles a CAPTCHA page with Pure CDP Mode:
310
330
 
311
331
  ```python
312
332
  from seleniumbase import sb_cdp
@@ -322,7 +342,7 @@ sb.driver.stop()
322
342
 
323
343
  --------
324
344
 
325
- <p align="left">📗 Here's <a href="https://github.com/seleniumbase/SeleniumBase/blob/master/examples/test_get_swag.py">SeleniumBase/examples/test_get_swag.py</a>, which tests an e-commerce site:</p>
345
+ <p align="left">📗 <a href="https://github.com/seleniumbase/SeleniumBase/blob/master/examples/test_get_swag.py" target="_blank">This example</a> tests an e-commerce site with <code>pytest</code>:
326
346
 
327
347
  ```python
328
348
  from seleniumbase import BaseCase
@@ -348,19 +368,17 @@ class MyTestClass(BaseCase):
348
368
 
349
369
  > `pytest test_get_swag.py`
350
370
 
351
- <a href="https://github.com/seleniumbase/SeleniumBase/blob/master/examples/test_get_swag.py"><img src="https://seleniumbase.github.io/cdn/gif/fast_swag_2.gif" alt="SeleniumBase Test" title="SeleniumBase Test" width="480" /></a>
352
-
353
- > (The default browser is `--chrome` if not set.)
371
+ <a href="https://github.com/seleniumbase/SeleniumBase/blob/master/examples/test_get_swag.py"><img src="https://seleniumbase.github.io/cdn/gif/fast_swag_2.gif" alt="SeleniumBase Test" width="480" /></a>
354
372
 
355
373
  --------
356
374
 
357
- <p align="left">📗 Here's <a href="https://github.com/seleniumbase/SeleniumBase/blob/master/examples/test_coffee_cart.py" target="_blank">SeleniumBase/examples/test_coffee_cart.py</a>, which verifies an e-commerce site:</p>
375
+ <p align="left">📗 <a href="https://github.com/seleniumbase/SeleniumBase/blob/master/examples/test_coffee_cart.py" target="_blank">This example</a> tests another e-commerce site with <code>pytest</code>:
358
376
 
359
377
  ```zsh
360
378
  pytest test_coffee_cart.py --demo
361
379
  ```
362
380
 
363
- <p align="left"><a href="https://seleniumbase.io/coffee/" target="_blank"><img src="https://seleniumbase.github.io/cdn/gif/coffee_cart.gif" width="480" alt="SeleniumBase Coffee Cart Test" title="SeleniumBase Coffee Cart Test" /></a></p>
381
+ <p align="left"><a href="https://seleniumbase.io/coffee/" target="_blank"><img src="https://seleniumbase.github.io/cdn/gif/coffee_cart.gif" width="480" alt="SeleniumBase Coffee Cart Test" /></a></p>
364
382
 
365
383
  > <p>(<code translate="no">--demo</code> mode slows down tests and highlights actions)</p>
366
384
 
@@ -368,13 +386,13 @@ pytest test_coffee_cart.py --demo
368
386
 
369
387
  <a id="multiple_examples"></a>
370
388
 
371
- <p align="left">📗 Here's <a href="https://github.com/seleniumbase/SeleniumBase/blob/master/examples/test_demo_site.py" target="_blank">SeleniumBase/examples/test_demo_site.py</a>, which covers several actions:</p>
389
+ <p align="left">📗 <a href="https://github.com/seleniumbase/SeleniumBase/blob/master/examples/test_demo_site.py" target="_blank">This example</a> covers multiple actions with <code>pytest</code>:
372
390
 
373
391
  ```zsh
374
392
  pytest test_demo_site.py
375
393
  ```
376
394
 
377
- <p align="left"><a href="https://seleniumbase.io/demo_page" target="_blank"><img src="https://seleniumbase.github.io/cdn/gif/demo_page_5.gif" width="480" alt="SeleniumBase Example" title="SeleniumBase Example" /></a></p>
395
+ <p align="left"><a href="https://seleniumbase.io/demo_page" target="_blank"><img src="https://seleniumbase.github.io/cdn/gif/demo_page_5.gif" width="480" alt="SeleniumBase Example" /></a></p>
378
396
 
379
397
  > Easy to type, click, select, toggle, drag & drop, and more.
380
398
 
@@ -382,14 +400,6 @@ pytest test_demo_site.py
382
400
 
383
401
  --------
384
402
 
385
- <p align="left">📓 Here's a high-level stealthy architecture overview of SeleniumBase:</p>
386
-
387
- <img src="https://seleniumbase.github.io/other/sb_stealth.png" width="585" alt="High-Level Stealthy Architecture Overview" title="High-Level Stealthy Architecture Overview" />
388
-
389
- (For maximum stealth, use <a translate="no" href="https://github.com/seleniumbase/SeleniumBase/blob/master/examples/cdp_mode/ReadMe.md">CDP Mode</a>, which is used by <a translate="no" href="https://github.com/seleniumbase/SeleniumBase/blob/master/examples/cdp_mode/playwright/ReadMe.md">Stealthy Playwright Mode</a>)
390
-
391
- --------
392
-
393
403
  <p align="left"><a href="https://github.com/seleniumbase/SeleniumBase/"><img src="https://seleniumbase.github.io/cdn/img/super_logo_sb3.png" alt="SeleniumBase" title="SeleniumBase" width="232" /></a></p>
394
404
 
395
405
  <blockquote>
@@ -637,7 +647,7 @@ cd examples/
637
647
  pytest my_first_test.py
638
648
  ```
639
649
 
640
- <a href="https://github.com/seleniumbase/SeleniumBase/blob/master/examples/my_first_test.py"><img src="https://seleniumbase.github.io/cdn/gif/fast_swag_2.gif" alt="SeleniumBase Test" title="SeleniumBase Test" width="480" /></a>
650
+ <a href="https://github.com/seleniumbase/SeleniumBase/blob/master/examples/my_first_test.py"><img src="https://seleniumbase.github.io/cdn/gif/fast_swag_2.gif" alt="SeleniumBase Test" width="480" /></a>
641
651
 
642
652
  <p align="left"><b>Here's the full code for <a href="https://github.com/seleniumbase/SeleniumBase/blob/master/examples/my_first_test.py">my_first_test.py</a>:</b></p>
643
653
 
@@ -9,7 +9,7 @@
9
9
 
10
10
  <h1>SeleniumBase</h1>
11
11
 
12
- <p align="center"><a href="https://github.com/seleniumbase/SeleniumBase/"><img src="https://seleniumbase.github.io/cdn/img/super_logo_sb3.png" alt="SeleniumBase" title="SeleniumBase" width="350" /></a></p>
12
+ <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
13
 
14
14
  <p align="center" class="hero__title"><b>All-in-one Browser Automation Framework:<br />Web Crawling / Testing / Scraping / Stealth</b></p>
15
15
 
@@ -52,17 +52,39 @@
52
52
  <br />
53
53
  </p>
54
54
 
55
- 📊 <a href="https://github.com/seleniumbase/SeleniumBase/"><b translate="no">SeleniumBase</b></a> is a complete framework for web automation, testing, scraping, and stealth. Includes a <a href="https://docs.pytest.org/en/latest/how-to/usage.html">pytest</a> integration for customizing automation from the command-line.
55
+ 📊 <a href="https://github.com/seleniumbase/SeleniumBase/"><b translate="no">SeleniumBase</b></a> is a complete framework for browser automation and testing with Python and <a href="https://docs.pytest.org/en/latest/how-to/usage.html">pytest</a>. Includes stealth options and other advanced features.
56
56
 
57
- 👤 Stealth modes: <a translate="no" href="https://github.com/seleniumbase/SeleniumBase/blob/master/help_docs/uc_mode.md">UC Mode</a> and <a translate="no" href="https://github.com/seleniumbase/SeleniumBase/blob/master/examples/cdp_mode/ReadMe.md"><b>CDP Mode</b></a> can bypass bot-detection, solve CAPTCHAs, and call methods from 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 makes Playwright stealthy via CDP Mode.
57
+ 🐙 Stealth modes: <a translate="no" href="https://github.com/seleniumbase/SeleniumBase/blob/master/help_docs/uc_mode.md">UC Mode</a> and <a translate="no" href="https://github.com/seleniumbase/SeleniumBase/blob/master/examples/cdp_mode/ReadMe.md"><b>CDP Mode</b></a> can bypass bot-detection, handle CAPTCHAs, and call methods from the <a href="https://chromedevtools.github.io/devtools-protocol/" translate="no">Chrome Devtools Protocol</a>. CDP Mode 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 makes Playwright stealthy.
58
58
 
59
- 📚 Example scripts and tests are located in [**SeleniumBase/examples/**](https://github.com/seleniumbase/SeleniumBase/tree/master/examples).
59
+ 📚 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).
60
60
 
61
- 👤 Stealthy example scripts are located in [**SeleniumBase/examples/cdp_mode/**](https://github.com/seleniumbase/SeleniumBase/tree/master/examples/cdp_mode).
61
+ 🥷 Stealthy examples are located in [SeleniumBase/examples/cdp_mode/](https://github.com/seleniumbase/SeleniumBase/tree/master/examples/cdp_mode).
62
62
 
63
63
  --------
64
64
 
65
- <p align="left">📗 This script performs a Google Search using SeleniumBase UC Mode + CDP Mode:<br /><a href="https://github.com/seleniumbase/SeleniumBase/blob/master/examples/raw_google.py">SeleniumBase/examples/raw_google.py</a> (Results are saved as PDF, HTML, and PNG)</p>
65
+ <p align="left">📓 Here's the stealthy architecture overview:</p>
66
+
67
+ <img src="https://seleniumbase.github.io/other/sb_stealth.png" width="596" alt="Stealthy architecture overview" />
68
+
69
+ (For maximum stealth, use <a translate="no" href="https://github.com/seleniumbase/SeleniumBase/blob/master/examples/cdp_mode/ReadMe.md">CDP Mode</a>, which includes <a translate="no" href="https://github.com/seleniumbase/SeleniumBase/blob/master/examples/cdp_mode/playwright/ReadMe.md">Stealthy Playwright Mode</a>)
70
+
71
+ --------
72
+
73
+ <p align="left">📗 <a href="https://github.com/seleniumbase/SeleniumBase/blob/master/examples/cdp_mode/raw_cdp_yc_news.py" target="_blank">This example</a> scrapes Hacker News listings with <a href="https://github.com/seleniumbase/SeleniumBase/blob/master/examples/cdp_mode/ReadMe.md#-pure-cdp-mode-sb_cdp">Pure CDP Mode</a>:
74
+
75
+ ```python
76
+ from seleniumbase import sb_cdp
77
+
78
+ url = "https://news.ycombinator.com/submitted?id=seleniumbase"
79
+ sb = sb_cdp.Chrome(url)
80
+ elements = sb.find_elements("span.titleline > a")
81
+ for element in elements:
82
+ print("* " + element.text)
83
+ ```
84
+
85
+ --------
86
+
87
+ <p align="left">📗 <a href="https://github.com/seleniumbase/SeleniumBase/blob/master/examples/raw_google.py" target="_blank">This example</a> saves Google Search results with UC + CDP Mode:<br />(Results are saved as PDF, HTML, and PNG files)</p>
66
88
 
67
89
  ```python
68
90
  from seleniumbase import SB
@@ -80,13 +102,9 @@ with SB(uc=True, test=True) as sb:
80
102
  print("Logs have been saved to: ./latest_logs/")
81
103
  ```
82
104
 
83
- > `python raw_google.py`
84
-
85
- <a href="https://github.com/seleniumbase/SeleniumBase/blob/master/examples/raw_google.py"><img src="https://seleniumbase.github.io/cdn/img/google_sb_result.jpg" alt="SeleniumBase on Google" title="SeleniumBase on Google" width="580" /></a>
86
-
87
105
  --------
88
106
 
89
- <p align="left">📗 Here's a script that bypasses Cloudflare's challenge page with UC Mode + CDP Mode: <a href="https://github.com/seleniumbase/SeleniumBase/blob/master/examples/cdp_mode/raw_gitlab.py">SeleniumBase/examples/cdp_mode/raw_gitlab.py</a></p>
107
+ <p align="left">📗 <a href="https://github.com/seleniumbase/SeleniumBase/blob/master/examples/cdp_mode/raw_gitlab.py" target="_blank">This example</a> bypasses Cloudflare's challenge page with UC + CDP Mode:
90
108
 
91
109
  ```python
92
110
  from seleniumbase import SB
@@ -104,9 +122,11 @@ with SB(uc=True, test=True, locale="en") as sb:
104
122
  sb.post_message("SeleniumBase wasn't detected", duration=4)
105
123
  ```
106
124
 
107
- <img src="https://seleniumbase.github.io/other/cf_sec.jpg" title="SeleniumBase" width="344"> <img src="https://seleniumbase.github.io/other/gitlab_bypass.png" title="SeleniumBase" width="298">
125
+ <img src="https://seleniumbase.github.io/other/cf_sec.jpg" alt="SeleniumBase" width="344"> <img src="https://seleniumbase.github.io/other/gitlab_bypass.png" alt="SeleniumBase" width="298">
126
+
127
+ ----
108
128
 
109
- <p align="left">📙 There's also SeleniumBase's "Pure CDP Mode", which doesn't use WebDriver or Selenium at all: <a href="https://github.com/seleniumbase/SeleniumBase/blob/master/examples/cdp_mode/raw_cdp_gitlab.py">SeleniumBase/examples/cdp_mode/raw_cdp_gitlab.py</a></p>
129
+ <p align="left">📗 <a href="https://github.com/seleniumbase/SeleniumBase/blob/master/examples/cdp_mode/raw_cdp_gitlab.py" target="_blank">This example</a> handles a CAPTCHA page with Pure CDP Mode:
110
130
 
111
131
  ```python
112
132
  from seleniumbase import sb_cdp
@@ -122,7 +142,7 @@ sb.driver.stop()
122
142
 
123
143
  --------
124
144
 
125
- <p align="left">📗 Here's <a href="https://github.com/seleniumbase/SeleniumBase/blob/master/examples/test_get_swag.py">SeleniumBase/examples/test_get_swag.py</a>, which tests an e-commerce site:</p>
145
+ <p align="left">📗 <a href="https://github.com/seleniumbase/SeleniumBase/blob/master/examples/test_get_swag.py" target="_blank">This example</a> tests an e-commerce site with <code>pytest</code>:
126
146
 
127
147
  ```python
128
148
  from seleniumbase import BaseCase
@@ -148,19 +168,17 @@ class MyTestClass(BaseCase):
148
168
 
149
169
  > `pytest test_get_swag.py`
150
170
 
151
- <a href="https://github.com/seleniumbase/SeleniumBase/blob/master/examples/test_get_swag.py"><img src="https://seleniumbase.github.io/cdn/gif/fast_swag_2.gif" alt="SeleniumBase Test" title="SeleniumBase Test" width="480" /></a>
152
-
153
- > (The default browser is `--chrome` if not set.)
171
+ <a href="https://github.com/seleniumbase/SeleniumBase/blob/master/examples/test_get_swag.py"><img src="https://seleniumbase.github.io/cdn/gif/fast_swag_2.gif" alt="SeleniumBase Test" width="480" /></a>
154
172
 
155
173
  --------
156
174
 
157
- <p align="left">📗 Here's <a href="https://github.com/seleniumbase/SeleniumBase/blob/master/examples/test_coffee_cart.py" target="_blank">SeleniumBase/examples/test_coffee_cart.py</a>, which verifies an e-commerce site:</p>
175
+ <p align="left">📗 <a href="https://github.com/seleniumbase/SeleniumBase/blob/master/examples/test_coffee_cart.py" target="_blank">This example</a> tests another e-commerce site with <code>pytest</code>:
158
176
 
159
177
  ```zsh
160
178
  pytest test_coffee_cart.py --demo
161
179
  ```
162
180
 
163
- <p align="left"><a href="https://seleniumbase.io/coffee/" target="_blank"><img src="https://seleniumbase.github.io/cdn/gif/coffee_cart.gif" width="480" alt="SeleniumBase Coffee Cart Test" title="SeleniumBase Coffee Cart Test" /></a></p>
181
+ <p align="left"><a href="https://seleniumbase.io/coffee/" target="_blank"><img src="https://seleniumbase.github.io/cdn/gif/coffee_cart.gif" width="480" alt="SeleniumBase Coffee Cart Test" /></a></p>
164
182
 
165
183
  > <p>(<code translate="no">--demo</code> mode slows down tests and highlights actions)</p>
166
184
 
@@ -168,13 +186,13 @@ pytest test_coffee_cart.py --demo
168
186
 
169
187
  <a id="multiple_examples"></a>
170
188
 
171
- <p align="left">📗 Here's <a href="https://github.com/seleniumbase/SeleniumBase/blob/master/examples/test_demo_site.py" target="_blank">SeleniumBase/examples/test_demo_site.py</a>, which covers several actions:</p>
189
+ <p align="left">📗 <a href="https://github.com/seleniumbase/SeleniumBase/blob/master/examples/test_demo_site.py" target="_blank">This example</a> covers multiple actions with <code>pytest</code>:
172
190
 
173
191
  ```zsh
174
192
  pytest test_demo_site.py
175
193
  ```
176
194
 
177
- <p align="left"><a href="https://seleniumbase.io/demo_page" target="_blank"><img src="https://seleniumbase.github.io/cdn/gif/demo_page_5.gif" width="480" alt="SeleniumBase Example" title="SeleniumBase Example" /></a></p>
195
+ <p align="left"><a href="https://seleniumbase.io/demo_page" target="_blank"><img src="https://seleniumbase.github.io/cdn/gif/demo_page_5.gif" width="480" alt="SeleniumBase Example" /></a></p>
178
196
 
179
197
  > Easy to type, click, select, toggle, drag & drop, and more.
180
198
 
@@ -182,14 +200,6 @@ pytest test_demo_site.py
182
200
 
183
201
  --------
184
202
 
185
- <p align="left">📓 Here's a high-level stealthy architecture overview of SeleniumBase:</p>
186
-
187
- <img src="https://seleniumbase.github.io/other/sb_stealth.png" width="585" alt="High-Level Stealthy Architecture Overview" title="High-Level Stealthy Architecture Overview" />
188
-
189
- (For maximum stealth, use <a translate="no" href="https://github.com/seleniumbase/SeleniumBase/blob/master/examples/cdp_mode/ReadMe.md">CDP Mode</a>, which is used by <a translate="no" href="https://github.com/seleniumbase/SeleniumBase/blob/master/examples/cdp_mode/playwright/ReadMe.md">Stealthy Playwright Mode</a>)
190
-
191
- --------
192
-
193
203
  <p align="left"><a href="https://github.com/seleniumbase/SeleniumBase/"><img src="https://seleniumbase.github.io/cdn/img/super_logo_sb3.png" alt="SeleniumBase" title="SeleniumBase" width="232" /></a></p>
194
204
 
195
205
  <blockquote>
@@ -437,7 +447,7 @@ cd examples/
437
447
  pytest my_first_test.py
438
448
  ```
439
449
 
440
- <a href="https://github.com/seleniumbase/SeleniumBase/blob/master/examples/my_first_test.py"><img src="https://seleniumbase.github.io/cdn/gif/fast_swag_2.gif" alt="SeleniumBase Test" title="SeleniumBase Test" width="480" /></a>
450
+ <a href="https://github.com/seleniumbase/SeleniumBase/blob/master/examples/my_first_test.py"><img src="https://seleniumbase.github.io/cdn/gif/fast_swag_2.gif" alt="SeleniumBase Test" width="480" /></a>
441
451
 
442
452
  <p align="left"><b>Here's the full code for <a href="https://github.com/seleniumbase/SeleniumBase/blob/master/examples/my_first_test.py">my_first_test.py</a>:</b></p>
443
453
 
@@ -3,7 +3,7 @@ packaging>=26.0
3
3
  setuptools~=70.2;python_version<"3.10"
4
4
  setuptools>=82.0.1;python_version>="3.10"
5
5
  wheel>=0.46.3
6
- attrs>=25.4.0
6
+ attrs>=26.1.0
7
7
  certifi>=2026.2.25
8
8
  exceptiongroup>=1.3.1
9
9
  websockets~=15.0.1;python_version<"3.10"
@@ -11,7 +11,7 @@ websockets>=16.0;python_version>="3.10"
11
11
  filelock~=3.19.1;python_version<"3.10"
12
12
  filelock>=3.25.2;python_version>="3.10"
13
13
  fasteners>=0.20
14
- mycdp>=1.3.4
14
+ mycdp>=1.3.7
15
15
  pynose>=1.5.5
16
16
  platformdirs~=4.4.0;python_version<"3.10"
17
17
  platformdirs>=4.9.4;python_version>="3.10"
@@ -29,7 +29,7 @@ pyreadline3>=3.5.4;platform_system=="Windows"
29
29
  tabcompleter>=1.4.0
30
30
  pdbp>=1.8.2
31
31
  idna>=3.11
32
- charset-normalizer>=3.4.5,<4
32
+ charset-normalizer>=3.4.6,<4
33
33
  urllib3>=1.26.20,<2;python_version<"3.10"
34
34
  urllib3>=1.26.20,<3;python_version>="3.10"
35
35
  requests~=2.32.5
@@ -77,8 +77,8 @@ rich>=14.3.3,<15
77
77
  # ("pip install -r requirements.txt" also installs this, but "pip install -e ." won't.)
78
78
 
79
79
  coverage>=7.10.7;python_version<"3.10"
80
- coverage>=7.13.4;python_version>="3.10"
81
- pytest-cov>=7.0.0
80
+ coverage>=7.13.5;python_version>="3.10"
81
+ pytest-cov>=7.1.0
82
82
  flake8==7.3.0
83
83
  mccabe==0.7.0
84
84
  pyflakes==3.4.0
@@ -1,2 +1,2 @@
1
1
  # seleniumbase package
2
- __version__ = "4.47.3"
2
+ __version__ = "4.47.5"
@@ -296,6 +296,7 @@ def extend_driver(
296
296
  driver.switch_to_tab = DM.switch_to_tab
297
297
  driver.switch_to_frame = DM.switch_to_frame
298
298
  driver.reset_window_size = DM.reset_window_size
299
+ driver.stop = driver.quit
299
300
  if recorder_ext:
300
301
  from seleniumbase.js_code.recorder_js import recorder_js
301
302
  recorder_code = (
@@ -391,7 +391,7 @@ class CDPMethods():
391
391
 
392
392
  def select_all(self, selector, timeout=None):
393
393
  if not timeout:
394
- timeout = settings.SMALL_TIMEOUT
394
+ timeout = settings.MINI_TIMEOUT
395
395
  self.__add_light_pause()
396
396
  selector = self.__convert_to_css_if_xpath(selector)
397
397
  if not self.is_element_present(selector):
@@ -414,12 +414,12 @@ class CDPMethods():
414
414
 
415
415
  def find_elements(self, selector, timeout=None):
416
416
  if not timeout:
417
- timeout = settings.SMALL_TIMEOUT
417
+ timeout = settings.MINI_TIMEOUT
418
418
  return self.select_all(selector, timeout=timeout)
419
419
 
420
420
  def find_visible_elements(self, selector, timeout=None):
421
421
  if not timeout:
422
- timeout = settings.SMALL_TIMEOUT
422
+ timeout = settings.MINI_TIMEOUT
423
423
  visible_elements = []
424
424
  elements = self.select_all(selector, timeout=timeout)
425
425
  for element in elements:
@@ -1335,7 +1335,7 @@ class CDPMethods():
1335
1335
  def get_window(self):
1336
1336
  return self.loop.run_until_complete(self.page.get_window())
1337
1337
 
1338
- def get_text(self, selector):
1338
+ def get_text(self, selector="body"):
1339
1339
  return self.find_element(selector).text_all
1340
1340
 
1341
1341
  def get_title(self):
@@ -2138,7 +2138,7 @@ def wait_for_non_empty_text(
2138
2138
 
2139
2139
  def get_text(
2140
2140
  driver,
2141
- selector,
2141
+ selector="body",
2142
2142
  by="css selector",
2143
2143
  timeout=settings.LARGE_TIMEOUT
2144
2144
  ):
@@ -39,14 +39,22 @@ def deconstruct_browser():
39
39
  for _ in __registered__instances__:
40
40
  if not _.stopped:
41
41
  _.stop(deconstruct=True)
42
- for attempt in range(5):
42
+ max_attempts = 5
43
+ for attempt in range(max_attempts):
43
44
  try:
44
45
  if _.config and not _.config.uses_custom_data_dir:
45
- shutil.rmtree(_.config.user_data_dir, ignore_errors=False)
46
+ if os.path.exists(_.config.user_data_dir):
47
+ shutil.rmtree(
48
+ _.config.user_data_dir, ignore_errors=False
49
+ )
50
+ if not os.path.exists(_.config.user_data_dir):
51
+ break
52
+ else:
53
+ time.sleep(0.12)
46
54
  except FileNotFoundError:
47
55
  break
48
56
  except (PermissionError, OSError) as e:
49
- if attempt == 4:
57
+ if attempt == max_attempts - 1:
50
58
  logger.debug(
51
59
  "Problem removing data dir %s\n"
52
60
  "Consider checking whether it's there "
@@ -54,7 +62,7 @@ def deconstruct_browser():
54
62
  % (_.config.user_data_dir, e)
55
63
  )
56
64
  break
57
- time.sleep(0.15)
65
+ time.sleep(0.12)
58
66
  continue
59
67
  logging.debug("Temp profile %s was removed." % _.config.user_data_dir)
60
68
 
@@ -207,7 +215,8 @@ class Browser:
207
215
  target_info = event.target_info
208
216
  current_tab = next(
209
217
  filter(
210
- lambda item: item.target_id == target_info.target_id, self.targets # noqa
218
+ lambda item: item.target_id == target_info.target_id,
219
+ self.targets,
211
220
  )
212
221
  )
213
222
  current_target = current_tab.target
@@ -583,11 +592,11 @@ class Browser:
583
592
  else "c:/path/to/your/browser.exe"
584
593
  )
585
594
  )
586
- if getattr(self.config, "_extensions", None): # noqa
595
+ if getattr(self.config, "_extensions", None):
587
596
  self.config.add_argument(
588
597
  "--load-extension=%s"
589
598
  % ",".join(str(_) for _ in self.config._extensions)
590
- ) # noqa
599
+ )
591
600
  exe = self.config.browser_executable_path
592
601
  params = self.config()
593
602
  logger.debug(
@@ -613,16 +622,17 @@ class Browser:
613
622
  await asyncio.sleep(0.05)
614
623
  get_registered_instances().add(self)
615
624
  await asyncio.sleep(0.15)
616
- for attempt in range(5):
625
+ max_attempts = 20
626
+ for attempt in range(max_attempts):
617
627
  try:
618
628
  self.info = ContraDict(
619
629
  await self._http.get("version"), silent=True
620
630
  )
621
631
  except (Exception,):
622
- if attempt == 4:
632
+ if attempt == max_attempts - 1:
623
633
  logger.debug("Could not start", exc_info=True)
624
634
  else:
625
- await self.sleep(0.5)
635
+ await self.sleep(0.2)
626
636
  else:
627
637
  break
628
638
  if not self.info:
@@ -644,9 +654,11 @@ class Browser:
644
654
  %s
645
655
  """ % (dashes, message, dashes)
646
656
  )
657
+ await asyncio.sleep(0.03)
647
658
  self.connection = Connection(
648
659
  self.info.webSocketDebuggerUrl, browser=self
649
660
  )
661
+ await asyncio.sleep(0.03)
650
662
  if self.config.autodiscover_targets:
651
663
  logger.debug("Enabling autodiscover targets")
652
664
  self.connection.handlers[cdp.target.TargetInfoChanged] = [
@@ -115,13 +115,22 @@ def __activate_virtual_display_as_needed(
115
115
  "Starting VDisplay from cdp_util: (%s, %s)"
116
116
  % (_xvfb_width, _xvfb_height)
117
117
  )
118
- _xvfb_display.start()
118
+ try:
119
+ _xvfb_display.start()
120
+ except Exception:
121
+ time.sleep(0.03)
122
+ _xvfb_display.start()
123
+ time.sleep(0.03)
119
124
  if "DISPLAY" not in os.environ.keys():
120
- print(
121
- "\n X11 display failed! Is Xvfb installed? "
122
- "\n Try this: `sudo apt install -y xvfb`"
123
- )
124
- __activate_standard_virtual_display()
125
+ time.sleep(0.03)
126
+ _xvfb_display.start()
127
+ time.sleep(0.08)
128
+ if "DISPLAY" not in os.environ.keys():
129
+ print(
130
+ "\n X11 display failed! Is Xvfb installed? "
131
+ "\n Try this: `sudo apt install -y xvfb`"
132
+ )
133
+ __activate_standard_virtual_display()
125
134
  else:
126
135
  sb_config._virtual_display = _xvfb_display
127
136
  sb_config.headless_active = True
@@ -781,15 +790,14 @@ async def create_from_driver(driver) -> Browser:
781
790
 
782
791
 
783
792
  def free_port() -> int:
784
- """Determines a free port using sockets."""
793
+ """Find and return a free port number assigned by the OS."""
785
794
  import socket
786
795
 
787
- free_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
788
- free_socket.bind(("127.0.0.1", 0))
789
- free_socket.listen(5)
790
- port: int = free_socket.getsockname()[1]
791
- free_socket.close()
792
- return port
796
+ with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:
797
+ # Binding to port 0 lets the OS pick a free port
798
+ s.bind(("127.0.0.1", 0))
799
+ s.listen(5)
800
+ return s.getsockname()[1]
793
801
 
794
802
 
795
803
  def filter_recurse_all(