seleniumbase 4.49.13__tar.gz → 4.50.0__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.

Potentially problematic release.


This version of seleniumbase might be problematic. Click here for more details.

Files changed (164) hide show
  1. {seleniumbase-4.49.13/seleniumbase.egg-info → seleniumbase-4.50.0}/PKG-INFO +5 -3
  2. {seleniumbase-4.49.13 → seleniumbase-4.50.0}/README.md +2 -0
  3. {seleniumbase-4.49.13 → seleniumbase-4.50.0}/requirements.txt +2 -2
  4. seleniumbase-4.50.0/seleniumbase/__version__.py +2 -0
  5. {seleniumbase-4.49.13 → seleniumbase-4.50.0}/seleniumbase/console_scripts/run.py +2 -0
  6. {seleniumbase-4.49.13 → seleniumbase-4.50.0}/seleniumbase/console_scripts/sb_install.py +20 -0
  7. {seleniumbase-4.49.13 → seleniumbase-4.50.0}/seleniumbase/console_scripts/sb_mkrec.py +10 -0
  8. {seleniumbase-4.49.13 → seleniumbase-4.50.0}/seleniumbase/console_scripts/sb_recorder.py +233 -70
  9. {seleniumbase-4.49.13 → seleniumbase-4.50.0}/seleniumbase/core/browser_launcher.py +12 -7
  10. {seleniumbase-4.49.13 → seleniumbase-4.50.0}/seleniumbase/core/sb_cdp.py +47 -10
  11. {seleniumbase-4.49.13 → seleniumbase-4.50.0}/seleniumbase/fixtures/base_case.py +335 -119
  12. {seleniumbase-4.49.13 → seleniumbase-4.50.0}/seleniumbase/plugins/pytest_plugin.py +32 -9
  13. {seleniumbase-4.49.13 → seleniumbase-4.50.0}/seleniumbase/plugins/sb_manager.py +28 -9
  14. {seleniumbase-4.49.13 → seleniumbase-4.50.0}/seleniumbase/plugins/selenium_plugin.py +32 -9
  15. {seleniumbase-4.49.13 → seleniumbase-4.50.0}/seleniumbase/undetected/cdp_driver/browser.py +19 -0
  16. {seleniumbase-4.49.13 → seleniumbase-4.50.0}/seleniumbase/undetected/cdp_driver/config.py +4 -3
  17. {seleniumbase-4.49.13 → seleniumbase-4.50.0}/seleniumbase/undetected/cdp_driver/tab.py +5 -1
  18. {seleniumbase-4.49.13 → seleniumbase-4.50.0/seleniumbase.egg-info}/PKG-INFO +5 -3
  19. {seleniumbase-4.49.13 → seleniumbase-4.50.0}/seleniumbase.egg-info/requires.txt +2 -2
  20. {seleniumbase-4.49.13 → seleniumbase-4.50.0}/setup.py +2 -2
  21. seleniumbase-4.49.13/seleniumbase/__version__.py +0 -2
  22. {seleniumbase-4.49.13 → seleniumbase-4.50.0}/.gitignore +0 -0
  23. {seleniumbase-4.49.13 → seleniumbase-4.50.0}/LICENSE +0 -0
  24. {seleniumbase-4.49.13 → seleniumbase-4.50.0}/MANIFEST.in +0 -0
  25. {seleniumbase-4.49.13 → seleniumbase-4.50.0}/install.sh +0 -0
  26. {seleniumbase-4.49.13 → seleniumbase-4.50.0}/pyproject.toml +0 -0
  27. {seleniumbase-4.49.13 → seleniumbase-4.50.0}/pytest.ini +0 -0
  28. {seleniumbase-4.49.13 → seleniumbase-4.50.0}/sbase/__init__.py +0 -0
  29. {seleniumbase-4.49.13 → seleniumbase-4.50.0}/sbase/__main__.py +0 -0
  30. {seleniumbase-4.49.13 → seleniumbase-4.50.0}/sbase/steps.py +0 -0
  31. {seleniumbase-4.49.13 → seleniumbase-4.50.0}/seleniumbase/__init__.py +0 -0
  32. {seleniumbase-4.49.13 → seleniumbase-4.50.0}/seleniumbase/__main__.py +0 -0
  33. {seleniumbase-4.49.13 → seleniumbase-4.50.0}/seleniumbase/behave/__init__.py +0 -0
  34. {seleniumbase-4.49.13 → seleniumbase-4.50.0}/seleniumbase/behave/behave_helper.py +0 -0
  35. {seleniumbase-4.49.13 → seleniumbase-4.50.0}/seleniumbase/behave/behave_sb.py +0 -0
  36. {seleniumbase-4.49.13 → seleniumbase-4.50.0}/seleniumbase/behave/steps.py +0 -0
  37. {seleniumbase-4.49.13 → seleniumbase-4.50.0}/seleniumbase/common/__init__.py +0 -0
  38. {seleniumbase-4.49.13 → seleniumbase-4.50.0}/seleniumbase/common/decorators.py +0 -0
  39. {seleniumbase-4.49.13 → seleniumbase-4.50.0}/seleniumbase/common/encryption.py +0 -0
  40. {seleniumbase-4.49.13 → seleniumbase-4.50.0}/seleniumbase/common/exceptions.py +0 -0
  41. {seleniumbase-4.49.13 → seleniumbase-4.50.0}/seleniumbase/common/obfuscate.py +0 -0
  42. {seleniumbase-4.49.13 → seleniumbase-4.50.0}/seleniumbase/common/unobfuscate.py +0 -0
  43. {seleniumbase-4.49.13 → seleniumbase-4.50.0}/seleniumbase/config/__init__.py +0 -0
  44. {seleniumbase-4.49.13 → seleniumbase-4.50.0}/seleniumbase/config/ad_block_list.py +0 -0
  45. {seleniumbase-4.49.13 → seleniumbase-4.50.0}/seleniumbase/config/proxy_list.py +0 -0
  46. {seleniumbase-4.49.13 → seleniumbase-4.50.0}/seleniumbase/config/settings.py +0 -0
  47. {seleniumbase-4.49.13 → seleniumbase-4.50.0}/seleniumbase/console_scripts/__init__.py +0 -0
  48. {seleniumbase-4.49.13 → seleniumbase-4.50.0}/seleniumbase/console_scripts/logo_helper.py +0 -0
  49. {seleniumbase-4.49.13 → seleniumbase-4.50.0}/seleniumbase/console_scripts/rich_helper.py +0 -0
  50. {seleniumbase-4.49.13 → seleniumbase-4.50.0}/seleniumbase/console_scripts/sb_behave_gui.py +0 -0
  51. {seleniumbase-4.49.13 → seleniumbase-4.50.0}/seleniumbase/console_scripts/sb_caseplans.py +0 -0
  52. {seleniumbase-4.49.13 → seleniumbase-4.50.0}/seleniumbase/console_scripts/sb_commander.py +0 -0
  53. {seleniumbase-4.49.13 → seleniumbase-4.50.0}/seleniumbase/console_scripts/sb_mkchart.py +0 -0
  54. {seleniumbase-4.49.13 → seleniumbase-4.50.0}/seleniumbase/console_scripts/sb_mkdir.py +0 -0
  55. {seleniumbase-4.49.13 → seleniumbase-4.50.0}/seleniumbase/console_scripts/sb_mkfile.py +0 -0
  56. {seleniumbase-4.49.13 → seleniumbase-4.50.0}/seleniumbase/console_scripts/sb_mkpres.py +0 -0
  57. {seleniumbase-4.49.13 → seleniumbase-4.50.0}/seleniumbase/console_scripts/sb_objectify.py +0 -0
  58. {seleniumbase-4.49.13 → seleniumbase-4.50.0}/seleniumbase/console_scripts/sb_print.py +0 -0
  59. {seleniumbase-4.49.13 → seleniumbase-4.50.0}/seleniumbase/core/__init__.py +0 -0
  60. {seleniumbase-4.49.13 → seleniumbase-4.50.0}/seleniumbase/core/application_manager.py +0 -0
  61. {seleniumbase-4.49.13 → seleniumbase-4.50.0}/seleniumbase/core/capabilities_parser.py +0 -0
  62. {seleniumbase-4.49.13 → seleniumbase-4.50.0}/seleniumbase/core/colored_traceback.py +0 -0
  63. {seleniumbase-4.49.13 → seleniumbase-4.50.0}/seleniumbase/core/create_db_tables.sql +0 -0
  64. {seleniumbase-4.49.13 → seleniumbase-4.50.0}/seleniumbase/core/detect_b_ver.py +0 -0
  65. {seleniumbase-4.49.13 → seleniumbase-4.50.0}/seleniumbase/core/download_helper.py +0 -0
  66. {seleniumbase-4.49.13 → seleniumbase-4.50.0}/seleniumbase/core/encoded_images.py +0 -0
  67. {seleniumbase-4.49.13 → seleniumbase-4.50.0}/seleniumbase/core/jqc_helper.py +0 -0
  68. {seleniumbase-4.49.13 → seleniumbase-4.50.0}/seleniumbase/core/log_helper.py +0 -0
  69. {seleniumbase-4.49.13 → seleniumbase-4.50.0}/seleniumbase/core/mysql.py +0 -0
  70. {seleniumbase-4.49.13 → seleniumbase-4.50.0}/seleniumbase/core/nest_asyncio.py +0 -0
  71. {seleniumbase-4.49.13 → seleniumbase-4.50.0}/seleniumbase/core/proxy_helper.py +0 -0
  72. {seleniumbase-4.49.13 → seleniumbase-4.50.0}/seleniumbase/core/recorder_helper.py +0 -0
  73. {seleniumbase-4.49.13 → seleniumbase-4.50.0}/seleniumbase/core/report_helper.py +0 -0
  74. {seleniumbase-4.49.13 → seleniumbase-4.50.0}/seleniumbase/core/s3_manager.py +0 -0
  75. {seleniumbase-4.49.13 → seleniumbase-4.50.0}/seleniumbase/core/sb_driver.py +0 -0
  76. {seleniumbase-4.49.13 → seleniumbase-4.50.0}/seleniumbase/core/session_helper.py +0 -0
  77. {seleniumbase-4.49.13 → seleniumbase-4.50.0}/seleniumbase/core/settings_parser.py +0 -0
  78. {seleniumbase-4.49.13 → seleniumbase-4.50.0}/seleniumbase/core/style_sheet.py +0 -0
  79. {seleniumbase-4.49.13 → seleniumbase-4.50.0}/seleniumbase/core/testcase_manager.py +0 -0
  80. {seleniumbase-4.49.13 → seleniumbase-4.50.0}/seleniumbase/core/tour_helper.py +0 -0
  81. {seleniumbase-4.49.13 → seleniumbase-4.50.0}/seleniumbase/core/visual_helper.py +0 -0
  82. {seleniumbase-4.49.13 → seleniumbase-4.50.0}/seleniumbase/drivers/__init__.py +0 -0
  83. {seleniumbase-4.49.13 → seleniumbase-4.50.0}/seleniumbase/drivers/atlas_drivers/__init__.py +0 -0
  84. {seleniumbase-4.49.13 → seleniumbase-4.50.0}/seleniumbase/drivers/brave_drivers/__init__.py +0 -0
  85. {seleniumbase-4.49.13 → seleniumbase-4.50.0}/seleniumbase/drivers/cft_drivers/__init__.py +0 -0
  86. {seleniumbase-4.49.13 → seleniumbase-4.50.0}/seleniumbase/drivers/chromium_drivers/__init__.py +0 -0
  87. {seleniumbase-4.49.13 → seleniumbase-4.50.0}/seleniumbase/drivers/chs_drivers/__init__.py +0 -0
  88. {seleniumbase-4.49.13 → seleniumbase-4.50.0}/seleniumbase/drivers/comet_drivers/__init__.py +0 -0
  89. {seleniumbase-4.49.13 → seleniumbase-4.50.0}/seleniumbase/drivers/opera_drivers/__init__.py +0 -0
  90. {seleniumbase-4.49.13 → seleniumbase-4.50.0}/seleniumbase/extensions/__init__.py +0 -0
  91. {seleniumbase-4.49.13 → seleniumbase-4.50.0}/seleniumbase/extensions/ad_block.zip +0 -0
  92. {seleniumbase-4.49.13 → seleniumbase-4.50.0}/seleniumbase/extensions/disable_csp.zip +0 -0
  93. {seleniumbase-4.49.13 → seleniumbase-4.50.0}/seleniumbase/extensions/recorder.zip +0 -0
  94. {seleniumbase-4.49.13 → seleniumbase-4.50.0}/seleniumbase/extensions/sbase_ext.zip +0 -0
  95. {seleniumbase-4.49.13 → seleniumbase-4.50.0}/seleniumbase/fixtures/__init__.py +0 -0
  96. {seleniumbase-4.49.13 → seleniumbase-4.50.0}/seleniumbase/fixtures/constants.py +0 -0
  97. {seleniumbase-4.49.13 → seleniumbase-4.50.0}/seleniumbase/fixtures/css_to_xpath.py +0 -0
  98. {seleniumbase-4.49.13 → seleniumbase-4.50.0}/seleniumbase/fixtures/errors.py +0 -0
  99. {seleniumbase-4.49.13 → seleniumbase-4.50.0}/seleniumbase/fixtures/js_utils.py +0 -0
  100. {seleniumbase-4.49.13 → seleniumbase-4.50.0}/seleniumbase/fixtures/page_actions.py +0 -0
  101. {seleniumbase-4.49.13 → seleniumbase-4.50.0}/seleniumbase/fixtures/page_utils.py +0 -0
  102. {seleniumbase-4.49.13 → seleniumbase-4.50.0}/seleniumbase/fixtures/shared_utils.py +0 -0
  103. {seleniumbase-4.49.13 → seleniumbase-4.50.0}/seleniumbase/fixtures/unittest_helper.py +0 -0
  104. {seleniumbase-4.49.13 → seleniumbase-4.50.0}/seleniumbase/fixtures/words.py +0 -0
  105. {seleniumbase-4.49.13 → seleniumbase-4.50.0}/seleniumbase/fixtures/xpath_to_css.py +0 -0
  106. {seleniumbase-4.49.13 → seleniumbase-4.50.0}/seleniumbase/js_code/__init__.py +0 -0
  107. {seleniumbase-4.49.13 → seleniumbase-4.50.0}/seleniumbase/js_code/active_css_js.py +0 -0
  108. {seleniumbase-4.49.13 → seleniumbase-4.50.0}/seleniumbase/js_code/live_js.py +0 -0
  109. {seleniumbase-4.49.13 → seleniumbase-4.50.0}/seleniumbase/js_code/recorder_js.py +0 -0
  110. {seleniumbase-4.49.13 → seleniumbase-4.50.0}/seleniumbase/masterqa/__init__.py +0 -0
  111. {seleniumbase-4.49.13 → seleniumbase-4.50.0}/seleniumbase/masterqa/master_qa.py +0 -0
  112. {seleniumbase-4.49.13 → seleniumbase-4.50.0}/seleniumbase/plugins/__init__.py +0 -0
  113. {seleniumbase-4.49.13 → seleniumbase-4.50.0}/seleniumbase/plugins/base_plugin.py +0 -0
  114. {seleniumbase-4.49.13 → seleniumbase-4.50.0}/seleniumbase/plugins/basic_test_info.py +0 -0
  115. {seleniumbase-4.49.13 → seleniumbase-4.50.0}/seleniumbase/plugins/db_reporting_plugin.py +0 -0
  116. {seleniumbase-4.49.13 → seleniumbase-4.50.0}/seleniumbase/plugins/driver_manager.py +0 -0
  117. {seleniumbase-4.49.13 → seleniumbase-4.50.0}/seleniumbase/plugins/page_source.py +0 -0
  118. {seleniumbase-4.49.13 → seleniumbase-4.50.0}/seleniumbase/plugins/s3_logging_plugin.py +0 -0
  119. {seleniumbase-4.49.13 → seleniumbase-4.50.0}/seleniumbase/plugins/screen_shots.py +0 -0
  120. {seleniumbase-4.49.13 → seleniumbase-4.50.0}/seleniumbase/resources/__init__.py +0 -0
  121. {seleniumbase-4.49.13 → seleniumbase-4.50.0}/seleniumbase/translate/__init__.py +0 -0
  122. {seleniumbase-4.49.13 → seleniumbase-4.50.0}/seleniumbase/translate/chinese.py +0 -0
  123. {seleniumbase-4.49.13 → seleniumbase-4.50.0}/seleniumbase/translate/dutch.py +0 -0
  124. {seleniumbase-4.49.13 → seleniumbase-4.50.0}/seleniumbase/translate/french.py +0 -0
  125. {seleniumbase-4.49.13 → seleniumbase-4.50.0}/seleniumbase/translate/italian.py +0 -0
  126. {seleniumbase-4.49.13 → seleniumbase-4.50.0}/seleniumbase/translate/japanese.py +0 -0
  127. {seleniumbase-4.49.13 → seleniumbase-4.50.0}/seleniumbase/translate/korean.py +0 -0
  128. {seleniumbase-4.49.13 → seleniumbase-4.50.0}/seleniumbase/translate/master_dict.py +0 -0
  129. {seleniumbase-4.49.13 → seleniumbase-4.50.0}/seleniumbase/translate/portuguese.py +0 -0
  130. {seleniumbase-4.49.13 → seleniumbase-4.50.0}/seleniumbase/translate/russian.py +0 -0
  131. {seleniumbase-4.49.13 → seleniumbase-4.50.0}/seleniumbase/translate/spanish.py +0 -0
  132. {seleniumbase-4.49.13 → seleniumbase-4.50.0}/seleniumbase/translate/translator.py +0 -0
  133. {seleniumbase-4.49.13 → seleniumbase-4.50.0}/seleniumbase/undetected/__init__.py +0 -0
  134. {seleniumbase-4.49.13 → seleniumbase-4.50.0}/seleniumbase/undetected/cdp.py +0 -0
  135. {seleniumbase-4.49.13 → seleniumbase-4.50.0}/seleniumbase/undetected/cdp_driver/__init__.py +0 -0
  136. {seleniumbase-4.49.13 → seleniumbase-4.50.0}/seleniumbase/undetected/cdp_driver/_contradict.py +0 -0
  137. {seleniumbase-4.49.13 → seleniumbase-4.50.0}/seleniumbase/undetected/cdp_driver/cdp_util.py +0 -0
  138. {seleniumbase-4.49.13 → seleniumbase-4.50.0}/seleniumbase/undetected/cdp_driver/connection.py +0 -0
  139. {seleniumbase-4.49.13 → seleniumbase-4.50.0}/seleniumbase/undetected/cdp_driver/element.py +0 -0
  140. {seleniumbase-4.49.13 → seleniumbase-4.50.0}/seleniumbase/undetected/dprocess.py +0 -0
  141. {seleniumbase-4.49.13 → seleniumbase-4.50.0}/seleniumbase/undetected/options.py +0 -0
  142. {seleniumbase-4.49.13 → seleniumbase-4.50.0}/seleniumbase/undetected/patcher.py +0 -0
  143. {seleniumbase-4.49.13 → seleniumbase-4.50.0}/seleniumbase/undetected/reactor.py +0 -0
  144. {seleniumbase-4.49.13 → seleniumbase-4.50.0}/seleniumbase/undetected/webelement.py +0 -0
  145. {seleniumbase-4.49.13 → seleniumbase-4.50.0}/seleniumbase/utilities/__init__.py +0 -0
  146. {seleniumbase-4.49.13 → seleniumbase-4.50.0}/seleniumbase/utilities/selenium_grid/__init__.py +0 -0
  147. {seleniumbase-4.49.13 → seleniumbase-4.50.0}/seleniumbase/utilities/selenium_grid/download_selenium_server.py +0 -0
  148. {seleniumbase-4.49.13 → seleniumbase-4.50.0}/seleniumbase/utilities/selenium_grid/font_color +0 -0
  149. {seleniumbase-4.49.13 → seleniumbase-4.50.0}/seleniumbase/utilities/selenium_grid/grid-hub +0 -0
  150. {seleniumbase-4.49.13 → seleniumbase-4.50.0}/seleniumbase/utilities/selenium_grid/grid-node +0 -0
  151. {seleniumbase-4.49.13 → seleniumbase-4.50.0}/seleniumbase/utilities/selenium_grid/grid_hub.py +0 -0
  152. {seleniumbase-4.49.13 → seleniumbase-4.50.0}/seleniumbase/utilities/selenium_grid/grid_node.py +0 -0
  153. {seleniumbase-4.49.13 → seleniumbase-4.50.0}/seleniumbase/utilities/selenium_grid/register-grid-node.bat +0 -0
  154. {seleniumbase-4.49.13 → seleniumbase-4.50.0}/seleniumbase/utilities/selenium_grid/register-grid-node.sh +0 -0
  155. {seleniumbase-4.49.13 → seleniumbase-4.50.0}/seleniumbase/utilities/selenium_grid/start-grid-hub.bat +0 -0
  156. {seleniumbase-4.49.13 → seleniumbase-4.50.0}/seleniumbase/utilities/selenium_grid/start-grid-hub.sh +0 -0
  157. {seleniumbase-4.49.13 → seleniumbase-4.50.0}/seleniumbase/utilities/selenium_ide/__init__.py +0 -0
  158. {seleniumbase-4.49.13 → seleniumbase-4.50.0}/seleniumbase/utilities/selenium_ide/convert_ide.py +0 -0
  159. {seleniumbase-4.49.13 → seleniumbase-4.50.0}/seleniumbase.egg-info/SOURCES.txt +0 -0
  160. {seleniumbase-4.49.13 → seleniumbase-4.50.0}/seleniumbase.egg-info/dependency_links.txt +0 -0
  161. {seleniumbase-4.49.13 → seleniumbase-4.50.0}/seleniumbase.egg-info/entry_points.txt +0 -0
  162. {seleniumbase-4.49.13 → seleniumbase-4.50.0}/seleniumbase.egg-info/top_level.txt +0 -0
  163. {seleniumbase-4.49.13 → seleniumbase-4.50.0}/setup.cfg +0 -0
  164. {seleniumbase-4.49.13 → seleniumbase-4.50.0}/virtualenv_install.sh +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: seleniumbase
3
- Version: 4.49.13
3
+ Version: 4.50.0
4
4
  Summary: SeleniumBase is a framework for web crawling, scraping, and testing. Supports pytest. CDP Mode adds stealth. Includes many tools.
5
5
  Home-page: https://github.com/seleniumbase/SeleniumBase
6
6
  Author: Michael Mintz
@@ -66,7 +66,7 @@ Requires-Dist: setuptools~=70.2; python_version < "3.10"
66
66
  Requires-Dist: setuptools>=82.0.1; python_version >= "3.10"
67
67
  Requires-Dist: wheel>=0.47.0
68
68
  Requires-Dist: attrs>=26.1.0
69
- Requires-Dist: certifi>=2026.5.20
69
+ Requires-Dist: certifi>=2026.6.17
70
70
  Requires-Dist: exceptiongroup>=1.3.1
71
71
  Requires-Dist: websockets~=15.0.1; python_version < "3.10"
72
72
  Requires-Dist: websockets>=16.0; python_version >= "3.10"
@@ -107,7 +107,7 @@ Requires-Dist: wsproto==1.2.0; python_version < "3.10"
107
107
  Requires-Dist: wsproto~=1.3.2; python_version >= "3.10"
108
108
  Requires-Dist: websocket-client~=1.9.0
109
109
  Requires-Dist: selenium==4.32.0; python_version < "3.10"
110
- Requires-Dist: selenium==4.44.0; python_version >= "3.10"
110
+ Requires-Dist: selenium==4.45.0; python_version >= "3.10"
111
111
  Requires-Dist: cssselect==1.3.0; python_version < "3.10"
112
112
  Requires-Dist: cssselect<2,>=1.4.0; python_version >= "3.10"
113
113
  Requires-Dist: sortedcontainers==2.4.0
@@ -1009,6 +1009,8 @@ pytest test_coffee_cart.py --trace
1009
1009
  --verify-delay=SECONDS # (The delay before MasterQA verification checks.)
1010
1010
  --ee | --esc-end # (Lets the user end the current test via the ESC key.)
1011
1011
  --recorder # (Enables the Recorder for turning browser actions into code.)
1012
+ --rec-sb-mgr # (A Recorder Mode that generates SB() context manager code.)
1013
+ --rec-sb-cdp # (A Recorder Mode that generates Pure CDP Mode sb_cdp code.)
1012
1014
  --rec-behave # (Same as Recorder Mode, but also generates behave-gherkin.)
1013
1015
  --rec-sleep # (If the Recorder is enabled, also records self.sleep calls.)
1014
1016
  --rec-print # (If the Recorder is enabled, prints output after tests end.)
@@ -823,6 +823,8 @@ pytest test_coffee_cart.py --trace
823
823
  --verify-delay=SECONDS # (The delay before MasterQA verification checks.)
824
824
  --ee | --esc-end # (Lets the user end the current test via the ESC key.)
825
825
  --recorder # (Enables the Recorder for turning browser actions into code.)
826
+ --rec-sb-mgr # (A Recorder Mode that generates SB() context manager code.)
827
+ --rec-sb-cdp # (A Recorder Mode that generates Pure CDP Mode sb_cdp code.)
826
828
  --rec-behave # (Same as Recorder Mode, but also generates behave-gherkin.)
827
829
  --rec-sleep # (If the Recorder is enabled, also records self.sleep calls.)
828
830
  --rec-print # (If the Recorder is enabled, prints output after tests end.)
@@ -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.5.20
8
+ certifi>=2026.6.17
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"
@@ -46,7 +46,7 @@ wsproto==1.2.0;python_version<"3.10"
46
46
  wsproto~=1.3.2;python_version>="3.10"
47
47
  websocket-client~=1.9.0
48
48
  selenium==4.32.0;python_version<"3.10"
49
- selenium==4.44.0;python_version>="3.10"
49
+ selenium==4.45.0;python_version>="3.10"
50
50
  cssselect==1.3.0;python_version<"3.10"
51
51
  cssselect>=1.4.0,<2;python_version>="3.10"
52
52
  sortedcontainers==2.4.0
@@ -0,0 +1,2 @@
1
+ # seleniumbase package
2
+ __version__ = "4.50.0"
@@ -834,6 +834,8 @@ def show_options():
834
834
  op += "--help / -h (Display list of all available pytest options.)\n"
835
835
  op += "--ftrace / --final-trace (Enter Debug Mode after tests end.)\n"
836
836
  op += "--recorder / --rec (Save browser actions as Python scripts.)\n"
837
+ op += "--rec-sb-mgr (Save Recorder actions as SB() context manager.)\n"
838
+ op += "--rec-sb-cdp (Save Recorder actions as Pure CDP Mode sb_cdp.)\n"
837
839
  op += "--rec-behave / --rec-gherkin (Save actions as Gherkin code.)\n"
838
840
  op += "--rec-print (Display recorded scripts when they are created.)\n"
839
841
  op += "--save-screenshot (Save a screenshot at the end of each test.)\n"
@@ -734,6 +734,26 @@ def main(override=None, intel_for_uc=None, force_uc=None):
734
734
  platform_code = "Win"
735
735
  file_name = "chrome-win.zip"
736
736
  revision = get_chromium_latest_revision(platform_code)
737
+ arg_join = " ".join(sys.argv)
738
+ if "--revision" in arg_join:
739
+ rev_str = None
740
+ if "--revision=" in arg_join:
741
+ rev_str = arg_join.split("--revision=")[1].split(" ")[0]
742
+ elif "--revision " in arg_join:
743
+ rev_str = arg_join.split("--revision ")[1].split(" ")[0]
744
+ if rev_str:
745
+ if rev_str.startswith('"') and rev_str.endswith('"'):
746
+ rev_str = rev_str[1:-1]
747
+ elif rev_str.startswith("'") and rev_str.endswith("'"):
748
+ rev_str = rev_str[1:-1]
749
+ with suppress(Exception):
750
+ if int(rev_str) > 1000000:
751
+ revision = rev_str
752
+ else:
753
+ print(
754
+ "Invalid revision number! Defaulting to %s!"
755
+ % revision
756
+ )
737
757
  msg = c2 + "Chromium revision to download" + cr
738
758
  p_version = c3 + revision + cr
739
759
  log_d("\n*** %s = %s" % (msg, p_version))
@@ -96,6 +96,8 @@ def main():
96
96
  use_colors = True
97
97
  force_gui = False
98
98
  rec_behave = False
99
+ rec_sb_mgr = False
100
+ rec_sb_cdp = False
99
101
 
100
102
  sys_executable = sys.executable
101
103
  if " " in sys_executable:
@@ -164,6 +166,10 @@ def main():
164
166
  use_uc = True
165
167
  elif option.lower() in ("--rec-behave", "--behave", "--gherkin"):
166
168
  rec_behave = True
169
+ elif option.lower() in ("--rec-sb-mgr"):
170
+ rec_sb_mgr = True
171
+ elif option.lower() in ("--rec-sb-cdp"):
172
+ rec_sb_cdp = True
167
173
  elif option.lower().startswith("--url="):
168
174
  start_page = option[len("--url="):]
169
175
  elif option.lower() == "--url":
@@ -306,6 +312,10 @@ def main():
306
312
  run_cmd += " --uc"
307
313
  if rec_behave:
308
314
  run_cmd += " --rec-behave"
315
+ if rec_sb_mgr:
316
+ run_cmd += " --rec-sb-mgr"
317
+ if rec_sb_cdp:
318
+ run_cmd += " --rec-sb-cdp"
309
319
  print(run_cmd)
310
320
  os.system(run_cmd)
311
321
  if os.path.exists(file_path):
@@ -20,7 +20,10 @@ import os
20
20
  import subprocess
21
21
  import sys
22
22
  import tkinter as tk
23
+ from tkinter import ttk
24
+ from contextlib import suppress
23
25
  from seleniumbase import config as sb_config
26
+ from seleniumbase.core import detect_b_ver
24
27
  from seleniumbase.fixtures import page_utils
25
28
  from seleniumbase.fixtures import shared_utils
26
29
  from tkinter import messagebox
@@ -76,7 +79,15 @@ def file_name_error(file_name):
76
79
  return error_msg
77
80
 
78
81
 
79
- def do_recording(file_name, url, overwrite_enabled, use_chrome, window):
82
+ def do_recording(
83
+ file_name,
84
+ url,
85
+ overwrite_enabled,
86
+ brx,
87
+ ucb,
88
+ output_format,
89
+ window,
90
+ ):
80
91
  poll = None
81
92
  if sb_config.rec_subprocess_used:
82
93
  poll = sb_config.rec_subprocess_p.poll()
@@ -101,7 +112,13 @@ def do_recording(file_name, url, overwrite_enabled, use_chrome, window):
101
112
  if not page_utils.is_valid_url(url):
102
113
  if page_utils.is_valid_url("https://" + url):
103
114
  url = "https://" + url
104
- if not page_utils.is_valid_url(url):
115
+ if "edge" in brx.lower() and ucb:
116
+ messagebox.showwarning(
117
+ "Invalid selection",
118
+ "MS Edge cannot be combined with UC Mode "
119
+ "because it uses msedgedriver, not chromedriver!",
120
+ )
121
+ elif not page_utils.is_valid_url(url):
105
122
  messagebox.showwarning(
106
123
  "Invalid URL", "Enter a valid URL! (Eg. seleniumbase.io)"
107
124
  )
@@ -121,13 +138,12 @@ def do_recording(file_name, url, overwrite_enabled, use_chrome, window):
121
138
  else:
122
139
  os.remove(file_name)
123
140
  add_on = ""
124
- command_args = sys.argv[2:]
125
- if (
126
- "--rec-behave" in command_args
127
- or "--behave" in command_args
128
- or "--gherkin" in command_args
129
- ):
141
+ if "Behave" in output_format:
130
142
  add_on = " --rec-behave"
143
+ elif "SB()" in output_format:
144
+ add_on = " --rec-sb-mgr"
145
+ elif "sb_cdp" in output_format:
146
+ add_on = " --rec-sb-cdp"
131
147
  command = (
132
148
  "%s -m seleniumbase mkrec %s --url=%s --gui"
133
149
  % (sys_executable, file_name, url)
@@ -142,25 +158,21 @@ def do_recording(file_name, url, overwrite_enabled, use_chrome, window):
142
158
  "%s -m seleniumbase mkrec %s --url='%s' --gui"
143
159
  % (sys_executable, file_name, url)
144
160
  )
145
- if not use_chrome:
161
+ if "edge" in brx.lower():
146
162
  command += " --edge"
147
- elif "--opera" in command_args:
163
+ elif "opera" in brx.lower():
148
164
  command += " --opera"
149
- elif "--brave" in command_args:
165
+ elif "brave" in brx.lower():
150
166
  command += " --brave"
151
- elif "--comet" in command_args:
167
+ elif "comet" in brx.lower():
152
168
  command += " --comet"
153
- elif "--atlas" in command_args:
169
+ elif "atlas" in brx.lower():
154
170
  command += " --atlas"
155
- elif "--use-chromium" in command_args:
171
+ elif "chromium" in brx.lower():
156
172
  command += " --use-chromium"
157
- if (
158
- "--uc" in command_args
159
- or "--cdp" in command_args
160
- or "--undetected" in command_args
161
- or "--undetectable" in command_args
162
- ):
173
+ if ucb:
163
174
  command += " --uc"
175
+ command_args = sys.argv[2:]
164
176
  if "--ee" in command_args:
165
177
  command += " --ee"
166
178
  command += add_on
@@ -175,7 +187,7 @@ def do_recording(file_name, url, overwrite_enabled, use_chrome, window):
175
187
  send_window_to_front(window)
176
188
 
177
189
 
178
- def do_playback(file_name, use_chrome, window, demo_mode=False):
190
+ def do_playback(file_name, brx, window, demo_mode=False):
179
191
  file_name = file_name.strip()
180
192
  error_msg = file_name_error(file_name)
181
193
  if error_msg:
@@ -189,11 +201,22 @@ def do_playback(file_name, use_chrome, window, demo_mode=False):
189
201
  'File "%s" does not exist in the current directory!' % file_name,
190
202
  )
191
203
  return
192
- command = "%s -m pytest %s -q -s" % (sys_executable, file_name)
204
+ # command = "%s -m pytest %s -q -s" % (sys_executable, file_name)
205
+ command = "%s %s -q -s" % (sys_executable, file_name)
193
206
  if shared_utils.is_linux():
194
207
  command += " --gui"
195
- if not use_chrome:
208
+ if "edge" in brx.lower():
196
209
  command += " --edge"
210
+ elif "opera" in brx.lower():
211
+ command += " --opera"
212
+ elif "brave" in brx.lower():
213
+ command += " --brave"
214
+ elif "comet" in brx.lower():
215
+ command += " --comet"
216
+ elif "atlas" in brx.lower():
217
+ command += " --atlas"
218
+ elif "chromium" in brx.lower():
219
+ command += " --use-chromium"
197
220
  if demo_mode:
198
221
  command += " --demo"
199
222
  command_args = sys.argv[2:]
@@ -223,100 +246,233 @@ def create_tkinter_gui():
223
246
  default_file_name = "new_recording.py"
224
247
  window = tk.Tk()
225
248
  window.title("SeleniumBase Recorder App")
226
- window.geometry("344x388")
249
+ window.geometry("344x564")
250
+ my_font = ("TkDefaultFont", 11)
227
251
  frame = tk.Frame(window)
228
252
  frame.pack()
229
253
 
230
- tk.Label(window, text="").pack()
231
254
  fname = tk.StringVar(value=default_file_name)
232
- tk.Label(window, text="Enter filename to save recording as:").pack()
255
+ label = tk.Label(window, text="Enter filename to save recording as:")
256
+ label.pack(pady=(20, 0.2))
233
257
  entry = tk.Entry(window, textvariable=fname)
234
- entry.pack()
258
+ entry.config(width=21)
259
+ entry.pack(pady=(0.6, 0.2))
235
260
  cbx = tk.IntVar()
236
261
  chk = tk.Checkbutton(window, text="Overwrite existing files", variable=cbx)
237
262
  chk.pack()
238
263
  chk.select()
239
264
  use_stealth = False
265
+ use_behave = False
266
+ use_sb_mgr = False
267
+ use_sb_cdp = False
268
+ use_atlas = False
240
269
  command_args = sys.argv[2:]
241
270
  if (
242
271
  "--uc" in command_args
243
272
  or "--cdp" in command_args
273
+ or "--stealth" in command_args
244
274
  or "--undetected" in command_args
245
275
  or "--undetectable" in command_args
246
276
  ):
247
277
  use_stealth = True
248
- browser_display = "Use Chrome over Edge"
249
- if "--opera" in command_args:
250
- browser_display = "Use Opera over Edge"
251
- elif "--brave" in command_args:
252
- browser_display = "Use Brave over Edge"
253
- elif "--comet" in command_args:
254
- browser_display = "Use Comet over Edge"
255
- elif "--atlas" in command_args:
256
- browser_display = "Use Atlas over Edge"
257
- cbb = tk.IntVar()
258
- if not use_stealth:
259
- chkb = tk.Checkbutton(window, text=browser_display, variable=cbb)
260
- chkb.pack()
261
- if "--edge" not in command_args:
262
- chkb.select()
278
+ if (
279
+ "--rec-behave" in command_args
280
+ or "--behave" in command_args
281
+ or "--gherkin" in command_args
282
+ ):
283
+ use_behave = True
284
+ if "--rec-sb-mgr" in command_args:
285
+ use_sb_mgr = True
286
+ if "--rec-sb-cdp" in command_args:
287
+ use_sb_cdp = True
288
+ if "--atlas" in command_args:
289
+ use_atlas = True
290
+
291
+ tk.Label(window, text="\nSelect a web browser to use:").pack()
292
+ br_count = 2
293
+ br_order = {"chrome": 0, "chromium": 1}
294
+ options_list = ["Google Chrome"]
295
+ options_list.append("Chromium Browser")
296
+ if shared_utils.is_windows():
297
+ options_list.append("MS Edge (No Stealth)")
298
+ br_order["edge"] = br_count
299
+ br_count += 1
263
300
  else:
264
- chkb = tk.Checkbutton(
265
- window, text="Stealthy Chrome Mode", variable=cbb
266
- )
267
- chkb.pack()
301
+ with suppress(Exception):
302
+ if os.path.exists(detect_b_ver.get_binary_location("edge")):
303
+ options_list.append("MS Edge (No Stealth)")
304
+ br_order["edge"] = br_count
305
+ br_count += 1
306
+ with suppress(Exception):
307
+ if os.path.exists(detect_b_ver.get_binary_location("opera")):
308
+ options_list.append("Opera Browser")
309
+ br_order["opera"] = br_count
310
+ br_count += 1
311
+ with suppress(Exception):
312
+ if os.path.exists(detect_b_ver.get_binary_location("brave")):
313
+ options_list.append("Brave Browser")
314
+ br_order["brave"] = br_count
315
+ br_count += 1
316
+ with suppress(Exception):
317
+ if os.path.exists(detect_b_ver.get_binary_location("comet")):
318
+ options_list.append("Comet Browser")
319
+ br_order["comet"] = br_count
320
+ br_count += 1
321
+ if use_atlas:
322
+ with suppress(Exception):
323
+ if os.path.exists(detect_b_ver.get_binary_location("atlas")):
324
+ options_list.append("Atlas Browser")
325
+ br_order["atlas"] = br_count
326
+ br_count += 1
327
+ brx = tk.StringVar(window)
328
+ if "--use-chromium" in command_args or "--chromium" in command_args:
329
+ brx.set(options_list[1])
330
+ elif (
331
+ "--edge" in command_args
332
+ and "edge" in br_order
333
+ ):
334
+ brx.set(options_list[2])
335
+ use_stealth = False
336
+ elif "--opera" in command_args and "opera" in br_order:
337
+ brx.set(options_list[br_order["opera"]])
338
+ elif "--brave" in command_args and "brave" in br_order:
339
+ brx.set(options_list[br_order["brave"]])
340
+ elif "--comet" in command_args and "comet" in br_order:
341
+ brx.set(options_list[br_order["comet"]])
342
+ elif "--atlas" in command_args and "atlas" in br_order:
343
+ brx.set(options_list[br_order["atlas"]])
344
+ else:
345
+ brx.set(options_list[0])
346
+ question_menu = tk.OptionMenu(window, brx, *options_list)
347
+ question_menu.config(width=16)
348
+ question_menu.pack(pady=(0.6, 0.2))
349
+
350
+ ucb = tk.IntVar()
351
+ chkb = tk.Checkbutton(
352
+ window, text="Stealth Mode / UC + CDP Mode", variable=ucb
353
+ )
354
+ chkb.pack(pady=(0.4, 0.4))
355
+ if use_stealth:
268
356
  chkb.select()
269
- chkb.config(state=tk.DISABLED)
270
- tk.Label(window, text="").pack()
357
+ # chkb.config(state=tk.DISABLED)
358
+
359
+ tk.Label(window, text="\nSelect an output format to use:").pack()
360
+ options_list = ["pytest format / BaseCase"]
361
+ options_list.append("Context Manager / SB()")
362
+ options_list.append("Pure CDP Mode / sb_cdp")
363
+ if use_behave:
364
+ options_list.append("BehaveBDD Gherkin File")
365
+ frx = tk.StringVar(window)
366
+ if use_behave and not use_sb_mgr and not use_sb_cdp:
367
+ frx.set(options_list[3])
368
+ elif use_sb_mgr:
369
+ frx.set(options_list[1])
370
+ elif use_sb_cdp:
371
+ frx.set(options_list[2])
372
+ else:
373
+ frx.set(options_list[0])
374
+ question_menu = tk.OptionMenu(window, frx, *options_list)
375
+ question_menu.config(width=18)
376
+ question_menu.pack(pady=(0.6, 0.2))
377
+
271
378
  url = tk.StringVar()
272
- tk.Label(window, text="Enter the URL to start recording on:").pack()
379
+ label = tk.Label(window, text="Enter a URL to start recording on:")
380
+ label.pack(pady=(20, 0.2))
273
381
  entry = tk.Entry(window, textvariable=url)
382
+ entry.config(width=23)
274
383
  entry.pack()
275
384
  entry.focus()
276
385
  entry.bind(
277
386
  "<Return>",
278
387
  (
279
388
  lambda _: do_recording(
280
- fname.get(), url.get(), cbx.get(), cbb.get(), window
389
+ fname.get(),
390
+ url.get(),
391
+ cbx.get(),
392
+ brx.get(),
393
+ ucb.get(),
394
+ frx.get(),
395
+ window,
281
396
  )
282
397
  ),
283
398
  )
284
- tk.Button(
399
+ # Automatically set focus on URL field when clicking back into the app
400
+ window.bind(
401
+ "<FocusIn>", lambda event: entry.focus_set()
402
+ if event.widget == window
403
+ else None
404
+ )
405
+ style = ttk.Style()
406
+ style.configure(
407
+ "Record.TButton",
408
+ foreground="red",
409
+ font=("TkDefaultFont", 12, "bold"),
410
+ width="8",
411
+ padding=(4, 3, 4, 1)
412
+ )
413
+ ttk.Button(
285
414
  window,
286
415
  text="Record",
287
- fg="red",
416
+ style="Record.TButton",
288
417
  command=lambda: do_recording(
289
- fname.get(), url.get(), cbx.get(), cbb.get(), window
418
+ fname.get(),
419
+ url.get(),
420
+ cbx.get(),
421
+ brx.get(),
422
+ ucb.get(),
423
+ frx.get(),
424
+ window,
290
425
  ),
291
- ).pack()
292
- tk.Label(window, text="").pack()
293
- tk.Label(window, text="Playback recording (Normal Mode):").pack()
294
- tk.Button(
426
+ ).pack(pady=0.2)
427
+ label = tk.Label(window, text="Playback recording (Normal Mode):")
428
+ label.pack(pady=(18, 0))
429
+
430
+ style.configure(
431
+ "Playback.TButton",
432
+ foreground="green",
433
+ font=("TkDefaultFont", 11, "bold"),
434
+ width="8",
435
+ padding=(4, 3, 4, 1)
436
+ )
437
+ ttk.Button(
295
438
  window,
296
439
  text="Playback",
297
- fg="green",
298
- command=lambda: do_playback(fname.get(), cbb.get(), window),
299
- ).pack()
300
- tk.Label(window, text="").pack()
301
- tk.Label(window, text="Playback recording (Demo Mode):").pack()
440
+ style="Playback.TButton",
441
+ command=lambda: do_playback(fname.get(), brx.get(), window),
442
+ ).pack(pady=0.2)
443
+ label = tk.Label(window, text="Playback recording (Demo Mode):")
444
+ label.pack(pady=(14, 0))
302
445
  try:
303
- tk.Button(
446
+ style.configure(
447
+ "PlaybackDemo.TButton",
448
+ foreground="teal",
449
+ font=("TkDefaultFont", 11, "bold"),
450
+ width="16",
451
+ padding=(4, 3, 4, 1)
452
+ )
453
+ ttk.Button(
304
454
  window,
305
455
  text="Playback (Demo Mode)",
306
- fg="teal",
456
+ style="PlaybackDemo.TButton",
307
457
  command=lambda: do_playback(
308
- fname.get(), cbb.get(), window, demo_mode=True
458
+ fname.get(), brx.get(), window, demo_mode=True
309
459
  ),
310
- ).pack()
460
+ ).pack(pady=0.2)
311
461
  except Exception:
312
- tk.Button(
462
+ style.configure(
463
+ "PlaybackDemo.TButton",
464
+ foreground="blue",
465
+ font=("TkDefaultFont", 11, "bold"),
466
+ padding=(4, 3, 4, 1)
467
+ )
468
+ ttk.Button(
313
469
  window,
314
470
  text="Playback (Demo Mode)",
315
- fg="blue",
471
+ style="PlaybackDemo.TButton",
316
472
  command=lambda: do_playback(
317
- fname.get(), cbb.get(), window, demo_mode=True
473
+ fname.get(), brx.get(), window, demo_mode=True
318
474
  ),
319
- ).pack()
475
+ ).pack(pady=0.2)
320
476
 
321
477
  # Bring form window to front
322
478
  send_window_to_front(window)
@@ -328,6 +484,13 @@ def create_tkinter_gui():
328
484
  decoy.deiconify()
329
485
  decoy.destroy()
330
486
  # Start tkinter
487
+ for widget in window.winfo_children():
488
+ if isinstance(
489
+ widget, (tk.Label, tk.Entry, tk.Checkbutton, tk.OptionMenu)
490
+ ):
491
+ widget.configure(font=my_font)
492
+ window.deiconify() # Force the OS to redraw it actively on top
493
+ window.focus_force() # Force keyboard focus into the entry fields
331
494
  window.mainloop()
332
495
  end_program()
333
496
 
@@ -761,6 +761,7 @@ def uc_open_with_cdp_mode(driver, url=None, **kwargs):
761
761
  cdp.goto = CDPM.goto
762
762
  cdp.reload = CDPM.reload
763
763
  cdp.refresh = CDPM.refresh
764
+ cdp.goto_if_not_url = CDPM.goto_if_not_url
764
765
  cdp.add_handler = CDPM.add_handler
765
766
  cdp.get_event_loop = CDPM.get_event_loop
766
767
  cdp.get_rd_host = CDPM.get_rd_host
@@ -851,8 +852,9 @@ def uc_open_with_cdp_mode(driver, url=None, **kwargs):
851
852
  cdp.gui_drag_drop_points = CDPM.gui_drag_drop_points
852
853
  cdp.gui_drag_and_drop = CDPM.gui_drag_and_drop
853
854
  cdp.gui_click_and_hold = CDPM.gui_click_and_hold
854
- cdp.gui_hover_x_y = CDPM.gui_hover_x_y
855
+ cdp.gui_move_to_element = CDPM.gui_move_to_element
855
856
  cdp.gui_hover_element = CDPM.gui_hover_element
857
+ cdp.gui_hover_x_y = CDPM.gui_hover_x_y
856
858
  cdp.gui_hover_and_click = CDPM.gui_hover_and_click
857
859
  cdp.hover_element = CDPM.hover_element
858
860
  cdp.hover_and_click = CDPM.hover_and_click
@@ -2763,6 +2765,7 @@ def _set_chrome_options(
2763
2765
  chrome_options.add_argument("--disable-3d-apis")
2764
2766
  if headless or headless2 or is_using_uc(undetectable, browser_name):
2765
2767
  chrome_options.add_argument("--disable-renderer-backgrounding")
2768
+ chrome_options.add_argument("--disable-background-networking")
2766
2769
  chrome_options.add_argument("--disable-backgrounding-occluded-windows")
2767
2770
  chrome_options.add_argument("--disable-client-side-phishing-detection")
2768
2771
  chrome_options.add_argument("--disable-device-discovery-notifications")
@@ -2779,7 +2782,6 @@ def _set_chrome_options(
2779
2782
  chrome_options.add_argument("--disable-domain-reliability")
2780
2783
  chrome_options.add_argument("--disable-breakpad")
2781
2784
  included_disabled_features = []
2782
- included_disabled_features.append("OptimizationHints")
2783
2785
  included_disabled_features.append("OptimizationHintsFetching")
2784
2786
  included_disabled_features.append("Translate")
2785
2787
  included_disabled_features.append("ComponentUpdater")
@@ -2800,14 +2802,19 @@ def _set_chrome_options(
2800
2802
  included_disabled_features.append("UnifiedWebBluetooth")
2801
2803
  included_disabled_features.append("WebAuthentication")
2802
2804
  included_disabled_features.append("PasskeyAuth")
2805
+ included_disabled_features.append("MediaRouter")
2806
+ included_disabled_features.append("DialMediaRouteProvider")
2807
+ included_disabled_features.append("WebRtcHideLocalIpsWithMdns")
2808
+ if is_using_uc(undetectable, browser_name):
2809
+ included_disabled_features.append("IsolateOrigins")
2810
+ included_disabled_features.append("site-per-process")
2803
2811
  for item in extra_disabled_features:
2804
2812
  if item not in included_disabled_features:
2805
2813
  included_disabled_features.append(item)
2806
2814
  d_f_string = ",".join(included_disabled_features)
2807
2815
  chrome_options.add_argument("--disable-features=%s" % d_f_string)
2808
2816
  chrome_options.add_argument("--enable-unsafe-extension-debugging")
2809
- if proxy_string:
2810
- chrome_options.add_argument("--test-type")
2817
+ chrome_options.add_argument("--test-type")
2811
2818
  if proxy_auth or sb_config._ext_dirs:
2812
2819
  if not is_using_uc(undetectable, browser_name):
2813
2820
  chrome_options.add_argument("--remote-debugging-pipe")
@@ -2825,13 +2832,12 @@ def _set_chrome_options(
2825
2832
  chrome_options.add_argument("--animation-duration-scale=0")
2826
2833
  chrome_options.add_argument("--wm-window-animations-disabled")
2827
2834
  chrome_options.add_argument("--enable-privacy-sandbox-ads-apis")
2835
+ chrome_options.add_argument("--disable-auto-reload")
2828
2836
  chrome_options.add_argument("--disable-background-timer-throttling")
2829
2837
  # Prevent new tabs opened by Selenium from being blocked:
2830
2838
  chrome_options.add_argument("--disable-popup-blocking")
2831
2839
  # Skip remaining options that trigger anti-bot services
2832
2840
  return chrome_options
2833
- if not proxy_string:
2834
- chrome_options.add_argument("--test-type")
2835
2841
  chrome_options.add_argument("--log-level=3")
2836
2842
  chrome_options.add_argument("--no-first-run")
2837
2843
  chrome_options.add_argument("--allow-insecure-localhost")
@@ -4803,7 +4809,6 @@ def get_local_driver(
4803
4809
  edge_options.add_argument("--disable-domain-reliability")
4804
4810
  edge_options.add_argument("--disable-breakpad")
4805
4811
  included_disabled_features = []
4806
- included_disabled_features.append("OptimizationHints")
4807
4812
  included_disabled_features.append("OptimizationHintsFetching")
4808
4813
  included_disabled_features.append("Translate")
4809
4814
  included_disabled_features.append("ComponentUpdater")