seleniumbase 4.42.0__tar.gz → 4.42.2__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {seleniumbase-4.42.0/seleniumbase.egg-info → seleniumbase-4.42.2}/PKG-INFO +6 -7
- {seleniumbase-4.42.0 → seleniumbase-4.42.2}/README.md +2 -4
- {seleniumbase-4.42.0 → seleniumbase-4.42.2}/requirements.txt +3 -2
- {seleniumbase-4.42.0 → seleniumbase-4.42.2}/seleniumbase/__version__.py +1 -1
- {seleniumbase-4.42.0 → seleniumbase-4.42.2}/seleniumbase/core/browser_launcher.py +8 -1
- {seleniumbase-4.42.0 → seleniumbase-4.42.2}/seleniumbase/core/sb_cdp.py +31 -0
- {seleniumbase-4.42.0 → seleniumbase-4.42.2}/seleniumbase/fixtures/base_case.py +7 -27
- {seleniumbase-4.42.0 → seleniumbase-4.42.2}/seleniumbase/fixtures/page_actions.py +4 -0
- {seleniumbase-4.42.0 → seleniumbase-4.42.2}/seleniumbase/fixtures/shared_utils.py +29 -0
- {seleniumbase-4.42.0 → seleniumbase-4.42.2}/seleniumbase/undetected/cdp_driver/browser.py +6 -8
- {seleniumbase-4.42.0 → seleniumbase-4.42.2}/seleniumbase/undetected/cdp_driver/config.py +9 -6
- {seleniumbase-4.42.0 → seleniumbase-4.42.2/seleniumbase.egg-info}/PKG-INFO +6 -7
- {seleniumbase-4.42.0 → seleniumbase-4.42.2}/seleniumbase.egg-info/requires.txt +3 -2
- {seleniumbase-4.42.0 → seleniumbase-4.42.2}/setup.py +3 -2
- {seleniumbase-4.42.0 → seleniumbase-4.42.2}/.gitignore +0 -0
- {seleniumbase-4.42.0 → seleniumbase-4.42.2}/LICENSE +0 -0
- {seleniumbase-4.42.0 → seleniumbase-4.42.2}/MANIFEST.in +0 -0
- {seleniumbase-4.42.0 → seleniumbase-4.42.2}/install.sh +0 -0
- {seleniumbase-4.42.0 → seleniumbase-4.42.2}/pyproject.toml +0 -0
- {seleniumbase-4.42.0 → seleniumbase-4.42.2}/pytest.ini +0 -0
- {seleniumbase-4.42.0 → seleniumbase-4.42.2}/sbase/__init__.py +0 -0
- {seleniumbase-4.42.0 → seleniumbase-4.42.2}/sbase/__main__.py +0 -0
- {seleniumbase-4.42.0 → seleniumbase-4.42.2}/sbase/steps.py +0 -0
- {seleniumbase-4.42.0 → seleniumbase-4.42.2}/seleniumbase/__init__.py +0 -0
- {seleniumbase-4.42.0 → seleniumbase-4.42.2}/seleniumbase/__main__.py +0 -0
- {seleniumbase-4.42.0 → seleniumbase-4.42.2}/seleniumbase/behave/__init__.py +0 -0
- {seleniumbase-4.42.0 → seleniumbase-4.42.2}/seleniumbase/behave/behave_helper.py +0 -0
- {seleniumbase-4.42.0 → seleniumbase-4.42.2}/seleniumbase/behave/behave_sb.py +0 -0
- {seleniumbase-4.42.0 → seleniumbase-4.42.2}/seleniumbase/behave/steps.py +0 -0
- {seleniumbase-4.42.0 → seleniumbase-4.42.2}/seleniumbase/common/__init__.py +0 -0
- {seleniumbase-4.42.0 → seleniumbase-4.42.2}/seleniumbase/common/decorators.py +0 -0
- {seleniumbase-4.42.0 → seleniumbase-4.42.2}/seleniumbase/common/encryption.py +0 -0
- {seleniumbase-4.42.0 → seleniumbase-4.42.2}/seleniumbase/common/exceptions.py +0 -0
- {seleniumbase-4.42.0 → seleniumbase-4.42.2}/seleniumbase/common/obfuscate.py +0 -0
- {seleniumbase-4.42.0 → seleniumbase-4.42.2}/seleniumbase/common/unobfuscate.py +0 -0
- {seleniumbase-4.42.0 → seleniumbase-4.42.2}/seleniumbase/config/__init__.py +0 -0
- {seleniumbase-4.42.0 → seleniumbase-4.42.2}/seleniumbase/config/ad_block_list.py +0 -0
- {seleniumbase-4.42.0 → seleniumbase-4.42.2}/seleniumbase/config/proxy_list.py +0 -0
- {seleniumbase-4.42.0 → seleniumbase-4.42.2}/seleniumbase/config/settings.py +0 -0
- {seleniumbase-4.42.0 → seleniumbase-4.42.2}/seleniumbase/console_scripts/__init__.py +0 -0
- {seleniumbase-4.42.0 → seleniumbase-4.42.2}/seleniumbase/console_scripts/logo_helper.py +0 -0
- {seleniumbase-4.42.0 → seleniumbase-4.42.2}/seleniumbase/console_scripts/rich_helper.py +0 -0
- {seleniumbase-4.42.0 → seleniumbase-4.42.2}/seleniumbase/console_scripts/run.py +0 -0
- {seleniumbase-4.42.0 → seleniumbase-4.42.2}/seleniumbase/console_scripts/sb_behave_gui.py +0 -0
- {seleniumbase-4.42.0 → seleniumbase-4.42.2}/seleniumbase/console_scripts/sb_caseplans.py +0 -0
- {seleniumbase-4.42.0 → seleniumbase-4.42.2}/seleniumbase/console_scripts/sb_commander.py +0 -0
- {seleniumbase-4.42.0 → seleniumbase-4.42.2}/seleniumbase/console_scripts/sb_install.py +0 -0
- {seleniumbase-4.42.0 → seleniumbase-4.42.2}/seleniumbase/console_scripts/sb_mkchart.py +0 -0
- {seleniumbase-4.42.0 → seleniumbase-4.42.2}/seleniumbase/console_scripts/sb_mkdir.py +0 -0
- {seleniumbase-4.42.0 → seleniumbase-4.42.2}/seleniumbase/console_scripts/sb_mkfile.py +0 -0
- {seleniumbase-4.42.0 → seleniumbase-4.42.2}/seleniumbase/console_scripts/sb_mkpres.py +0 -0
- {seleniumbase-4.42.0 → seleniumbase-4.42.2}/seleniumbase/console_scripts/sb_mkrec.py +0 -0
- {seleniumbase-4.42.0 → seleniumbase-4.42.2}/seleniumbase/console_scripts/sb_objectify.py +0 -0
- {seleniumbase-4.42.0 → seleniumbase-4.42.2}/seleniumbase/console_scripts/sb_print.py +0 -0
- {seleniumbase-4.42.0 → seleniumbase-4.42.2}/seleniumbase/console_scripts/sb_recorder.py +0 -0
- {seleniumbase-4.42.0 → seleniumbase-4.42.2}/seleniumbase/core/__init__.py +0 -0
- {seleniumbase-4.42.0 → seleniumbase-4.42.2}/seleniumbase/core/application_manager.py +0 -0
- {seleniumbase-4.42.0 → seleniumbase-4.42.2}/seleniumbase/core/capabilities_parser.py +0 -0
- {seleniumbase-4.42.0 → seleniumbase-4.42.2}/seleniumbase/core/colored_traceback.py +0 -0
- {seleniumbase-4.42.0 → seleniumbase-4.42.2}/seleniumbase/core/create_db_tables.sql +0 -0
- {seleniumbase-4.42.0 → seleniumbase-4.42.2}/seleniumbase/core/detect_b_ver.py +0 -0
- {seleniumbase-4.42.0 → seleniumbase-4.42.2}/seleniumbase/core/download_helper.py +0 -0
- {seleniumbase-4.42.0 → seleniumbase-4.42.2}/seleniumbase/core/encoded_images.py +0 -0
- {seleniumbase-4.42.0 → seleniumbase-4.42.2}/seleniumbase/core/jqc_helper.py +0 -0
- {seleniumbase-4.42.0 → seleniumbase-4.42.2}/seleniumbase/core/log_helper.py +0 -0
- {seleniumbase-4.42.0 → seleniumbase-4.42.2}/seleniumbase/core/mysql.py +0 -0
- {seleniumbase-4.42.0 → seleniumbase-4.42.2}/seleniumbase/core/proxy_helper.py +0 -0
- {seleniumbase-4.42.0 → seleniumbase-4.42.2}/seleniumbase/core/recorder_helper.py +0 -0
- {seleniumbase-4.42.0 → seleniumbase-4.42.2}/seleniumbase/core/report_helper.py +0 -0
- {seleniumbase-4.42.0 → seleniumbase-4.42.2}/seleniumbase/core/s3_manager.py +0 -0
- {seleniumbase-4.42.0 → seleniumbase-4.42.2}/seleniumbase/core/sb_driver.py +0 -0
- {seleniumbase-4.42.0 → seleniumbase-4.42.2}/seleniumbase/core/session_helper.py +0 -0
- {seleniumbase-4.42.0 → seleniumbase-4.42.2}/seleniumbase/core/settings_parser.py +0 -0
- {seleniumbase-4.42.0 → seleniumbase-4.42.2}/seleniumbase/core/style_sheet.py +0 -0
- {seleniumbase-4.42.0 → seleniumbase-4.42.2}/seleniumbase/core/testcase_manager.py +0 -0
- {seleniumbase-4.42.0 → seleniumbase-4.42.2}/seleniumbase/core/tour_helper.py +0 -0
- {seleniumbase-4.42.0 → seleniumbase-4.42.2}/seleniumbase/core/visual_helper.py +0 -0
- {seleniumbase-4.42.0 → seleniumbase-4.42.2}/seleniumbase/drivers/__init__.py +0 -0
- {seleniumbase-4.42.0 → seleniumbase-4.42.2}/seleniumbase/drivers/cft_drivers/__init__.py +0 -0
- {seleniumbase-4.42.0 → seleniumbase-4.42.2}/seleniumbase/drivers/chs_drivers/__init__.py +0 -0
- {seleniumbase-4.42.0 → seleniumbase-4.42.2}/seleniumbase/extensions/__init__.py +0 -0
- {seleniumbase-4.42.0 → seleniumbase-4.42.2}/seleniumbase/extensions/ad_block.zip +0 -0
- {seleniumbase-4.42.0 → seleniumbase-4.42.2}/seleniumbase/extensions/disable_csp.zip +0 -0
- {seleniumbase-4.42.0 → seleniumbase-4.42.2}/seleniumbase/extensions/recorder.zip +0 -0
- {seleniumbase-4.42.0 → seleniumbase-4.42.2}/seleniumbase/extensions/sbase_ext.zip +0 -0
- {seleniumbase-4.42.0 → seleniumbase-4.42.2}/seleniumbase/fixtures/__init__.py +0 -0
- {seleniumbase-4.42.0 → seleniumbase-4.42.2}/seleniumbase/fixtures/constants.py +0 -0
- {seleniumbase-4.42.0 → seleniumbase-4.42.2}/seleniumbase/fixtures/css_to_xpath.py +0 -0
- {seleniumbase-4.42.0 → seleniumbase-4.42.2}/seleniumbase/fixtures/errors.py +0 -0
- {seleniumbase-4.42.0 → seleniumbase-4.42.2}/seleniumbase/fixtures/js_utils.py +0 -0
- {seleniumbase-4.42.0 → seleniumbase-4.42.2}/seleniumbase/fixtures/page_utils.py +0 -0
- {seleniumbase-4.42.0 → seleniumbase-4.42.2}/seleniumbase/fixtures/unittest_helper.py +0 -0
- {seleniumbase-4.42.0 → seleniumbase-4.42.2}/seleniumbase/fixtures/words.py +0 -0
- {seleniumbase-4.42.0 → seleniumbase-4.42.2}/seleniumbase/fixtures/xpath_to_css.py +0 -0
- {seleniumbase-4.42.0 → seleniumbase-4.42.2}/seleniumbase/js_code/__init__.py +0 -0
- {seleniumbase-4.42.0 → seleniumbase-4.42.2}/seleniumbase/js_code/active_css_js.py +0 -0
- {seleniumbase-4.42.0 → seleniumbase-4.42.2}/seleniumbase/js_code/live_js.py +0 -0
- {seleniumbase-4.42.0 → seleniumbase-4.42.2}/seleniumbase/js_code/recorder_js.py +0 -0
- {seleniumbase-4.42.0 → seleniumbase-4.42.2}/seleniumbase/masterqa/__init__.py +0 -0
- {seleniumbase-4.42.0 → seleniumbase-4.42.2}/seleniumbase/masterqa/master_qa.py +0 -0
- {seleniumbase-4.42.0 → seleniumbase-4.42.2}/seleniumbase/plugins/__init__.py +0 -0
- {seleniumbase-4.42.0 → seleniumbase-4.42.2}/seleniumbase/plugins/base_plugin.py +0 -0
- {seleniumbase-4.42.0 → seleniumbase-4.42.2}/seleniumbase/plugins/basic_test_info.py +0 -0
- {seleniumbase-4.42.0 → seleniumbase-4.42.2}/seleniumbase/plugins/db_reporting_plugin.py +0 -0
- {seleniumbase-4.42.0 → seleniumbase-4.42.2}/seleniumbase/plugins/driver_manager.py +0 -0
- {seleniumbase-4.42.0 → seleniumbase-4.42.2}/seleniumbase/plugins/page_source.py +0 -0
- {seleniumbase-4.42.0 → seleniumbase-4.42.2}/seleniumbase/plugins/pytest_plugin.py +0 -0
- {seleniumbase-4.42.0 → seleniumbase-4.42.2}/seleniumbase/plugins/s3_logging_plugin.py +0 -0
- {seleniumbase-4.42.0 → seleniumbase-4.42.2}/seleniumbase/plugins/sb_manager.py +0 -0
- {seleniumbase-4.42.0 → seleniumbase-4.42.2}/seleniumbase/plugins/screen_shots.py +0 -0
- {seleniumbase-4.42.0 → seleniumbase-4.42.2}/seleniumbase/plugins/selenium_plugin.py +0 -0
- {seleniumbase-4.42.0 → seleniumbase-4.42.2}/seleniumbase/resources/__init__.py +0 -0
- {seleniumbase-4.42.0 → seleniumbase-4.42.2}/seleniumbase/translate/__init__.py +0 -0
- {seleniumbase-4.42.0 → seleniumbase-4.42.2}/seleniumbase/translate/chinese.py +0 -0
- {seleniumbase-4.42.0 → seleniumbase-4.42.2}/seleniumbase/translate/dutch.py +0 -0
- {seleniumbase-4.42.0 → seleniumbase-4.42.2}/seleniumbase/translate/french.py +0 -0
- {seleniumbase-4.42.0 → seleniumbase-4.42.2}/seleniumbase/translate/italian.py +0 -0
- {seleniumbase-4.42.0 → seleniumbase-4.42.2}/seleniumbase/translate/japanese.py +0 -0
- {seleniumbase-4.42.0 → seleniumbase-4.42.2}/seleniumbase/translate/korean.py +0 -0
- {seleniumbase-4.42.0 → seleniumbase-4.42.2}/seleniumbase/translate/master_dict.py +0 -0
- {seleniumbase-4.42.0 → seleniumbase-4.42.2}/seleniumbase/translate/portuguese.py +0 -0
- {seleniumbase-4.42.0 → seleniumbase-4.42.2}/seleniumbase/translate/russian.py +0 -0
- {seleniumbase-4.42.0 → seleniumbase-4.42.2}/seleniumbase/translate/spanish.py +0 -0
- {seleniumbase-4.42.0 → seleniumbase-4.42.2}/seleniumbase/translate/translator.py +0 -0
- {seleniumbase-4.42.0 → seleniumbase-4.42.2}/seleniumbase/undetected/__init__.py +0 -0
- {seleniumbase-4.42.0 → seleniumbase-4.42.2}/seleniumbase/undetected/cdp.py +0 -0
- {seleniumbase-4.42.0 → seleniumbase-4.42.2}/seleniumbase/undetected/cdp_driver/__init__.py +0 -0
- {seleniumbase-4.42.0 → seleniumbase-4.42.2}/seleniumbase/undetected/cdp_driver/_contradict.py +0 -0
- {seleniumbase-4.42.0 → seleniumbase-4.42.2}/seleniumbase/undetected/cdp_driver/cdp_util.py +0 -0
- {seleniumbase-4.42.0 → seleniumbase-4.42.2}/seleniumbase/undetected/cdp_driver/connection.py +0 -0
- {seleniumbase-4.42.0 → seleniumbase-4.42.2}/seleniumbase/undetected/cdp_driver/element.py +0 -0
- {seleniumbase-4.42.0 → seleniumbase-4.42.2}/seleniumbase/undetected/cdp_driver/tab.py +0 -0
- {seleniumbase-4.42.0 → seleniumbase-4.42.2}/seleniumbase/undetected/dprocess.py +0 -0
- {seleniumbase-4.42.0 → seleniumbase-4.42.2}/seleniumbase/undetected/options.py +0 -0
- {seleniumbase-4.42.0 → seleniumbase-4.42.2}/seleniumbase/undetected/patcher.py +0 -0
- {seleniumbase-4.42.0 → seleniumbase-4.42.2}/seleniumbase/undetected/reactor.py +0 -0
- {seleniumbase-4.42.0 → seleniumbase-4.42.2}/seleniumbase/undetected/webelement.py +0 -0
- {seleniumbase-4.42.0 → seleniumbase-4.42.2}/seleniumbase/utilities/__init__.py +0 -0
- {seleniumbase-4.42.0 → seleniumbase-4.42.2}/seleniumbase/utilities/selenium_grid/__init__.py +0 -0
- {seleniumbase-4.42.0 → seleniumbase-4.42.2}/seleniumbase/utilities/selenium_grid/download_selenium_server.py +0 -0
- {seleniumbase-4.42.0 → seleniumbase-4.42.2}/seleniumbase/utilities/selenium_grid/font_color +0 -0
- {seleniumbase-4.42.0 → seleniumbase-4.42.2}/seleniumbase/utilities/selenium_grid/grid-hub +0 -0
- {seleniumbase-4.42.0 → seleniumbase-4.42.2}/seleniumbase/utilities/selenium_grid/grid-node +0 -0
- {seleniumbase-4.42.0 → seleniumbase-4.42.2}/seleniumbase/utilities/selenium_grid/grid_hub.py +0 -0
- {seleniumbase-4.42.0 → seleniumbase-4.42.2}/seleniumbase/utilities/selenium_grid/grid_node.py +0 -0
- {seleniumbase-4.42.0 → seleniumbase-4.42.2}/seleniumbase/utilities/selenium_grid/register-grid-node.bat +0 -0
- {seleniumbase-4.42.0 → seleniumbase-4.42.2}/seleniumbase/utilities/selenium_grid/register-grid-node.sh +0 -0
- {seleniumbase-4.42.0 → seleniumbase-4.42.2}/seleniumbase/utilities/selenium_grid/start-grid-hub.bat +0 -0
- {seleniumbase-4.42.0 → seleniumbase-4.42.2}/seleniumbase/utilities/selenium_grid/start-grid-hub.sh +0 -0
- {seleniumbase-4.42.0 → seleniumbase-4.42.2}/seleniumbase/utilities/selenium_ide/__init__.py +0 -0
- {seleniumbase-4.42.0 → seleniumbase-4.42.2}/seleniumbase/utilities/selenium_ide/convert_ide.py +0 -0
- {seleniumbase-4.42.0 → seleniumbase-4.42.2}/seleniumbase.egg-info/SOURCES.txt +0 -0
- {seleniumbase-4.42.0 → seleniumbase-4.42.2}/seleniumbase.egg-info/dependency_links.txt +0 -0
- {seleniumbase-4.42.0 → seleniumbase-4.42.2}/seleniumbase.egg-info/entry_points.txt +0 -0
- {seleniumbase-4.42.0 → seleniumbase-4.42.2}/seleniumbase.egg-info/top_level.txt +0 -0
- {seleniumbase-4.42.0 → seleniumbase-4.42.2}/setup.cfg +0 -0
- {seleniumbase-4.42.0 → seleniumbase-4.42.2}/virtualenv_install.sh +0 -0
@@ -1,6 +1,6 @@
|
|
1
1
|
Metadata-Version: 2.4
|
2
2
|
Name: seleniumbase
|
3
|
-
Version: 4.42.
|
3
|
+
Version: 4.42.2
|
4
4
|
Summary: A complete web automation framework for end-to-end testing.
|
5
5
|
Home-page: https://github.com/seleniumbase/SeleniumBase
|
6
6
|
Author: Michael Mintz
|
@@ -66,8 +66,9 @@ Requires-Dist: packaging>=25.0
|
|
66
66
|
Requires-Dist: setuptools~=70.2; python_version < "3.10"
|
67
67
|
Requires-Dist: setuptools>=80.9.0; python_version >= "3.10"
|
68
68
|
Requires-Dist: wheel>=0.45.1
|
69
|
-
Requires-Dist: attrs
|
70
|
-
Requires-Dist:
|
69
|
+
Requires-Dist: attrs~=25.3.0; python_version < "3.9"
|
70
|
+
Requires-Dist: attrs>=25.4.0; python_version >= "3.9"
|
71
|
+
Requires-Dist: certifi>=2025.10.5
|
71
72
|
Requires-Dist: exceptiongroup>=1.3.0
|
72
73
|
Requires-Dist: websockets~=13.1; python_version < "3.9"
|
73
74
|
Requires-Dist: websockets>=15.0.1; python_version >= "3.9"
|
@@ -314,7 +315,7 @@ with SB(uc=True, test=True, locale="en") as sb:
|
|
314
315
|
sb.assert_text("Username", '[for="user_login"]', timeout=3)
|
315
316
|
sb.assert_element('label[for="user_login"]')
|
316
317
|
sb.highlight('button:contains("Sign in")')
|
317
|
-
sb.highlight('h1:contains("GitLab
|
318
|
+
sb.highlight('h1:contains("GitLab")')
|
318
319
|
sb.post_message("SeleniumBase wasn't detected", duration=4)
|
319
320
|
```
|
320
321
|
|
@@ -329,13 +330,11 @@ url = "https://gitlab.com/users/sign_in"
|
|
329
330
|
sb = sb_cdp.Chrome(url)
|
330
331
|
sb.sleep(2.5)
|
331
332
|
sb.gui_click_captcha()
|
332
|
-
sb.highlight('h1:contains("GitLab
|
333
|
+
sb.highlight('h1:contains("GitLab")')
|
333
334
|
sb.highlight('button:contains("Sign in")')
|
334
335
|
sb.driver.stop()
|
335
336
|
```
|
336
337
|
|
337
|
-
> (Due to changes in Chrome 137 where the `--load-extension` switch was removed, you can't load extensions directly from this format.)
|
338
|
-
|
339
338
|
--------
|
340
339
|
|
341
340
|
<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>
|
@@ -103,7 +103,7 @@ with SB(uc=True, test=True, locale="en") as sb:
|
|
103
103
|
sb.assert_text("Username", '[for="user_login"]', timeout=3)
|
104
104
|
sb.assert_element('label[for="user_login"]')
|
105
105
|
sb.highlight('button:contains("Sign in")')
|
106
|
-
sb.highlight('h1:contains("GitLab
|
106
|
+
sb.highlight('h1:contains("GitLab")')
|
107
107
|
sb.post_message("SeleniumBase wasn't detected", duration=4)
|
108
108
|
```
|
109
109
|
|
@@ -118,13 +118,11 @@ url = "https://gitlab.com/users/sign_in"
|
|
118
118
|
sb = sb_cdp.Chrome(url)
|
119
119
|
sb.sleep(2.5)
|
120
120
|
sb.gui_click_captcha()
|
121
|
-
sb.highlight('h1:contains("GitLab
|
121
|
+
sb.highlight('h1:contains("GitLab")')
|
122
122
|
sb.highlight('button:contains("Sign in")')
|
123
123
|
sb.driver.stop()
|
124
124
|
```
|
125
125
|
|
126
|
-
> (Due to changes in Chrome 137 where the `--load-extension` switch was removed, you can't load extensions directly from this format.)
|
127
|
-
|
128
126
|
--------
|
129
127
|
|
130
128
|
<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>
|
@@ -4,8 +4,9 @@ packaging>=25.0
|
|
4
4
|
setuptools~=70.2;python_version<"3.10"
|
5
5
|
setuptools>=80.9.0;python_version>="3.10"
|
6
6
|
wheel>=0.45.1
|
7
|
-
attrs
|
8
|
-
|
7
|
+
attrs~=25.3.0;python_version<"3.9"
|
8
|
+
attrs>=25.4.0;python_version>="3.9"
|
9
|
+
certifi>=2025.10.5
|
9
10
|
exceptiongroup>=1.3.0
|
10
11
|
websockets~=13.1;python_version<"3.9"
|
11
12
|
websockets>=15.0.1;python_version>="3.9"
|
@@ -1,2 +1,2 @@
|
|
1
1
|
# seleniumbase package
|
2
|
-
__version__ = "4.42.
|
2
|
+
__version__ = "4.42.2"
|
@@ -766,6 +766,8 @@ def uc_open_with_cdp_mode(driver, url=None, **kwargs):
|
|
766
766
|
cdp.set_local_storage_item = CDPM.set_local_storage_item
|
767
767
|
cdp.set_session_storage_item = CDPM.set_session_storage_item
|
768
768
|
cdp.set_attributes = CDPM.set_attributes
|
769
|
+
cdp.is_attribute_present = CDPM.is_attribute_present
|
770
|
+
cdp.is_online = CDPM.is_online
|
769
771
|
cdp.gui_press_key = CDPM.gui_press_key
|
770
772
|
cdp.gui_press_keys = CDPM.gui_press_keys
|
771
773
|
cdp.gui_write = CDPM.gui_write
|
@@ -815,10 +817,12 @@ def uc_open_with_cdp_mode(driver, url=None, **kwargs):
|
|
815
817
|
cdp.get_screen_rect = CDPM.get_screen_rect
|
816
818
|
cdp.get_window_rect = CDPM.get_window_rect
|
817
819
|
cdp.get_window_size = CDPM.get_window_size
|
820
|
+
cdp.get_mfa_code = CDPM.get_mfa_code
|
818
821
|
cdp.nested_click = CDPM.nested_click
|
819
822
|
cdp.select_option_by_text = CDPM.select_option_by_text
|
820
823
|
cdp.select_option_by_index = CDPM.select_option_by_index
|
821
824
|
cdp.select_option_by_value = CDPM.select_option_by_value
|
825
|
+
cdp.enter_mfa_code = CDPM.enter_mfa_code
|
822
826
|
cdp.flash = CDPM.flash
|
823
827
|
cdp.highlight = CDPM.highlight
|
824
828
|
cdp.focus = CDPM.focus
|
@@ -2664,6 +2668,8 @@ def _set_chrome_options(
|
|
2664
2668
|
included_disabled_features.append(item)
|
2665
2669
|
d_f_string = ",".join(included_disabled_features)
|
2666
2670
|
chrome_options.add_argument("--disable-features=%s" % d_f_string)
|
2671
|
+
if proxy_auth:
|
2672
|
+
chrome_options.add_argument("--test-type")
|
2667
2673
|
if (
|
2668
2674
|
is_using_uc(undetectable, browser_name)
|
2669
2675
|
and (
|
@@ -2681,7 +2687,8 @@ def _set_chrome_options(
|
|
2681
2687
|
chrome_options.add_argument("--disable-popup-blocking")
|
2682
2688
|
# Skip remaining options that trigger anti-bot services
|
2683
2689
|
return chrome_options
|
2684
|
-
|
2690
|
+
if not proxy_auth:
|
2691
|
+
chrome_options.add_argument("--test-type")
|
2685
2692
|
chrome_options.add_argument("--log-level=3")
|
2686
2693
|
chrome_options.add_argument("--no-first-run")
|
2687
2694
|
chrome_options.add_argument("--allow-insecure-localhost")
|
@@ -1393,6 +1393,17 @@ class CDPMethods():
|
|
1393
1393
|
)
|
1394
1394
|
)
|
1395
1395
|
|
1396
|
+
def get_mfa_code(self, totp_key=None):
|
1397
|
+
"""Returns a time-based one-time password based on the Google
|
1398
|
+
Authenticator algorithm for multi-factor authentication."""
|
1399
|
+
return shared_utils.get_mfa_code(totp_key)
|
1400
|
+
|
1401
|
+
def enter_mfa_code(self, selector, totp_key=None, timeout=None):
|
1402
|
+
if not timeout:
|
1403
|
+
timeout = settings.SMALL_TIMEOUT
|
1404
|
+
mfa_code = self.get_mfa_code(totp_key)
|
1405
|
+
self.type(selector, mfa_code + "\n", timeout=timeout)
|
1406
|
+
|
1396
1407
|
def set_locale(self, locale):
|
1397
1408
|
"""(Settings will take effect on the next page load)"""
|
1398
1409
|
self.loop.run_until_complete(self.page.set_locale(locale))
|
@@ -1430,6 +1441,26 @@ class CDPMethods():
|
|
1430
1441
|
with suppress(Exception):
|
1431
1442
|
self.loop.run_until_complete(self.page.evaluate(js_code))
|
1432
1443
|
|
1444
|
+
def is_attribute_present(self, selector, attribute, value=None):
|
1445
|
+
try:
|
1446
|
+
element = self.find_element(selector, timeout=0.1)
|
1447
|
+
found_value = element.get_attribute(attribute)
|
1448
|
+
if found_value is None:
|
1449
|
+
return False
|
1450
|
+
if value is not None:
|
1451
|
+
if found_value == value:
|
1452
|
+
return True
|
1453
|
+
else:
|
1454
|
+
return False
|
1455
|
+
else:
|
1456
|
+
return True
|
1457
|
+
except Exception:
|
1458
|
+
return False
|
1459
|
+
|
1460
|
+
def is_online(self):
|
1461
|
+
js_code = "navigator.onLine;"
|
1462
|
+
return self.loop.run_until_complete(self.page.evaluate(js_code))
|
1463
|
+
|
1433
1464
|
def __make_sure_pyautogui_lock_is_writable(self):
|
1434
1465
|
with suppress(Exception):
|
1435
1466
|
shared_utils.make_writable(constants.MultiBrowser.PYAUTOGUILOCK)
|
@@ -1503,6 +1503,10 @@ class BaseCase(unittest.TestCase):
|
|
1503
1503
|
):
|
1504
1504
|
"""Returns True if the element attribute/value is found.
|
1505
1505
|
If the value is not specified, the attribute only needs to exist."""
|
1506
|
+
if self.__is_cdp_swap_needed():
|
1507
|
+
return self.cdp.is_attribute_present(
|
1508
|
+
selector, attribute, value=value
|
1509
|
+
)
|
1506
1510
|
self.wait_for_ready_state_complete()
|
1507
1511
|
time.sleep(0.01)
|
1508
1512
|
selector, by = self.__recalculate_selector(selector, by)
|
@@ -8510,33 +8514,9 @@ class BaseCase(unittest.TestCase):
|
|
8510
8514
|
|
8511
8515
|
def get_mfa_code(self, totp_key=None):
|
8512
8516
|
"""Same as get_totp_code() and get_google_auth_password().
|
8513
|
-
Returns a time-based one-time password based on the
|
8514
|
-
|
8515
|
-
|
8516
|
-
to using the one provided in [seleniumbase/config/settings.py].
|
8517
|
-
Google Authenticator codes expire & change at 30-sec intervals.
|
8518
|
-
If the fetched password expires in the next 1.2 seconds, waits
|
8519
|
-
for a new one before returning it (may take up to 1.2 seconds).
|
8520
|
-
See https://pyotp.readthedocs.io/en/latest/ for details."""
|
8521
|
-
import pyotp
|
8522
|
-
|
8523
|
-
if not totp_key:
|
8524
|
-
totp_key = settings.TOTP_KEY
|
8525
|
-
|
8526
|
-
epoch_interval = time.time() / 30.0
|
8527
|
-
cycle_lifespan = float(epoch_interval) - int(epoch_interval)
|
8528
|
-
if float(cycle_lifespan) > 0.96:
|
8529
|
-
# Password expires in the next 1.2 seconds. Wait for a new one.
|
8530
|
-
for i in range(30):
|
8531
|
-
time.sleep(0.04)
|
8532
|
-
epoch_interval = time.time() / 30.0
|
8533
|
-
cycle_lifespan = float(epoch_interval) - int(epoch_interval)
|
8534
|
-
if not float(cycle_lifespan) > 0.96:
|
8535
|
-
# The new password cycle has begun
|
8536
|
-
break
|
8537
|
-
|
8538
|
-
totp = pyotp.TOTP(totp_key)
|
8539
|
-
return str(totp.now())
|
8517
|
+
Returns a time-based one-time password based on the Google
|
8518
|
+
Authenticator algorithm for multi-factor authentication."""
|
8519
|
+
return shared_utils.get_mfa_code(totp_key)
|
8540
8520
|
|
8541
8521
|
def enter_mfa_code(
|
8542
8522
|
self, selector, totp_key=None, by="css selector", timeout=None
|
@@ -193,6 +193,10 @@ def is_attribute_present(
|
|
193
193
|
@Returns
|
194
194
|
Boolean (is attribute present)
|
195
195
|
"""
|
196
|
+
if __is_cdp_swap_needed(driver):
|
197
|
+
return driver.cdp.is_attribute_present(
|
198
|
+
selector, attribute, value=value
|
199
|
+
)
|
196
200
|
_reconnect_if_disconnected(driver)
|
197
201
|
try:
|
198
202
|
element = driver.find_element(by=by, value=selector)
|
@@ -7,6 +7,7 @@ import sys
|
|
7
7
|
import time
|
8
8
|
from contextlib import suppress
|
9
9
|
from seleniumbase import config as sb_config
|
10
|
+
from seleniumbase.config import settings
|
10
11
|
from seleniumbase.fixtures import constants
|
11
12
|
|
12
13
|
|
@@ -29,6 +30,34 @@ def pip_install(package, version=None):
|
|
29
30
|
)
|
30
31
|
|
31
32
|
|
33
|
+
def get_mfa_code(totp_key=None):
|
34
|
+
"""Returns a time-based one-time password based on the
|
35
|
+
Google Authenticator algorithm for multi-factor authentication.
|
36
|
+
If the "totp_key" is not specified, this method defaults
|
37
|
+
to using the one provided in [seleniumbase/config/settings.py].
|
38
|
+
Google Authenticator codes expire & change at 30-sec intervals.
|
39
|
+
If the fetched password expires in the next 1.2 seconds, waits
|
40
|
+
for a new one before returning it (may take up to 1.2 seconds).
|
41
|
+
See https://pyotp.readthedocs.io/en/latest/ for details."""
|
42
|
+
import pyotp
|
43
|
+
|
44
|
+
if not totp_key:
|
45
|
+
totp_key = settings.TOTP_KEY
|
46
|
+
epoch_interval = time.time() / 30.0
|
47
|
+
cycle_lifespan = float(epoch_interval) - int(epoch_interval)
|
48
|
+
if float(cycle_lifespan) > 0.96:
|
49
|
+
# Password expires in the next 1.2 seconds. Wait for a new one.
|
50
|
+
for i in range(30):
|
51
|
+
time.sleep(0.04)
|
52
|
+
epoch_interval = time.time() / 30.0
|
53
|
+
cycle_lifespan = float(epoch_interval) - int(epoch_interval)
|
54
|
+
if not float(cycle_lifespan) > 0.96:
|
55
|
+
# The new password cycle has begun
|
56
|
+
break
|
57
|
+
totp = pyotp.TOTP(totp_key)
|
58
|
+
return str(totp.now())
|
59
|
+
|
60
|
+
|
32
61
|
def is_arm_linux():
|
33
62
|
"""Returns True if machine is ARM Linux.
|
34
63
|
This will be useful once Google adds
|
@@ -350,7 +350,8 @@ class Browser:
|
|
350
350
|
if _cdp_geolocation:
|
351
351
|
await connection.send(cdp.page.navigate("about:blank"))
|
352
352
|
await connection.set_geolocation(_cdp_geolocation)
|
353
|
-
#
|
353
|
+
# This part isn't needed now, but may be needed later
|
354
|
+
"""
|
354
355
|
if (
|
355
356
|
hasattr(sb_config, "_cdp_proxy")
|
356
357
|
and "@" in sb_config._cdp_proxy
|
@@ -360,17 +361,14 @@ class Browser:
|
|
360
361
|
username_and_password = sb_config._cdp_proxy.split("@")[0]
|
361
362
|
proxy_user = username_and_password.split(":")[0]
|
362
363
|
proxy_pass = username_and_password.split(":")[1]
|
363
|
-
await connection.set_auth(
|
364
|
-
proxy_user, proxy_pass, self.tabs[0]
|
365
|
-
)
|
364
|
+
await connection.set_auth(proxy_user, proxy_pass, self.tabs[0])
|
366
365
|
time.sleep(0.25)
|
367
|
-
|
366
|
+
"""
|
367
|
+
if "auth" in kwargs and kwargs["auth"] and ":" in kwargs["auth"]:
|
368
368
|
username_and_password = kwargs["auth"]
|
369
369
|
proxy_user = username_and_password.split(":")[0]
|
370
370
|
proxy_pass = username_and_password.split(":")[1]
|
371
|
-
await connection.set_auth(
|
372
|
-
proxy_user, proxy_pass, self.tabs[0]
|
373
|
-
)
|
371
|
+
await connection.set_auth(proxy_user, proxy_pass, self.tabs[0])
|
374
372
|
time.sleep(0.25)
|
375
373
|
frame_id, loader_id, *_ = await connection.send(
|
376
374
|
cdp.page.navigate(url)
|
@@ -150,11 +150,6 @@ class Config:
|
|
150
150
|
"--disable-renderer-backgrounding",
|
151
151
|
"--disable-background-networking",
|
152
152
|
"--disable-dev-shm-usage",
|
153
|
-
"--disable-features=IsolateOrigins,site-per-process,Translate,"
|
154
|
-
"InsecureDownloadWarnings,DownloadBubble,DownloadBubbleV2,"
|
155
|
-
"OptimizationTargetPrediction,OptimizationGuideModelDownloading,"
|
156
|
-
"SidePanelPinning,UserAgentClientHint,PrivacySandboxSettings4,"
|
157
|
-
"DisableLoadExtensionCommandLineSwitch",
|
158
153
|
]
|
159
154
|
|
160
155
|
@property
|
@@ -202,7 +197,15 @@ class Config:
|
|
202
197
|
# By the time it starts, the port is probably already taken.
|
203
198
|
args = self._default_browser_args.copy()
|
204
199
|
args += ["--user-data-dir=%s" % self.user_data_dir]
|
205
|
-
args += [
|
200
|
+
args += [
|
201
|
+
"--disable-features=IsolateOrigins,site-per-process,Translate,"
|
202
|
+
"InsecureDownloadWarnings,DownloadBubble,DownloadBubbleV2,"
|
203
|
+
"OptimizationTargetPrediction,OptimizationGuideModelDownloading,"
|
204
|
+
"SidePanelPinning,UserAgentClientHint,PrivacySandboxSettings4,"
|
205
|
+
"DisableLoadExtensionCommandLineSwitch"
|
206
|
+
]
|
207
|
+
if self.proxy:
|
208
|
+
args += ["--test-type"]
|
206
209
|
args += ["--disable-session-crashed-bubble"]
|
207
210
|
if self.expert:
|
208
211
|
args += [
|
@@ -1,6 +1,6 @@
|
|
1
1
|
Metadata-Version: 2.4
|
2
2
|
Name: seleniumbase
|
3
|
-
Version: 4.42.
|
3
|
+
Version: 4.42.2
|
4
4
|
Summary: A complete web automation framework for end-to-end testing.
|
5
5
|
Home-page: https://github.com/seleniumbase/SeleniumBase
|
6
6
|
Author: Michael Mintz
|
@@ -66,8 +66,9 @@ Requires-Dist: packaging>=25.0
|
|
66
66
|
Requires-Dist: setuptools~=70.2; python_version < "3.10"
|
67
67
|
Requires-Dist: setuptools>=80.9.0; python_version >= "3.10"
|
68
68
|
Requires-Dist: wheel>=0.45.1
|
69
|
-
Requires-Dist: attrs
|
70
|
-
Requires-Dist:
|
69
|
+
Requires-Dist: attrs~=25.3.0; python_version < "3.9"
|
70
|
+
Requires-Dist: attrs>=25.4.0; python_version >= "3.9"
|
71
|
+
Requires-Dist: certifi>=2025.10.5
|
71
72
|
Requires-Dist: exceptiongroup>=1.3.0
|
72
73
|
Requires-Dist: websockets~=13.1; python_version < "3.9"
|
73
74
|
Requires-Dist: websockets>=15.0.1; python_version >= "3.9"
|
@@ -314,7 +315,7 @@ with SB(uc=True, test=True, locale="en") as sb:
|
|
314
315
|
sb.assert_text("Username", '[for="user_login"]', timeout=3)
|
315
316
|
sb.assert_element('label[for="user_login"]')
|
316
317
|
sb.highlight('button:contains("Sign in")')
|
317
|
-
sb.highlight('h1:contains("GitLab
|
318
|
+
sb.highlight('h1:contains("GitLab")')
|
318
319
|
sb.post_message("SeleniumBase wasn't detected", duration=4)
|
319
320
|
```
|
320
321
|
|
@@ -329,13 +330,11 @@ url = "https://gitlab.com/users/sign_in"
|
|
329
330
|
sb = sb_cdp.Chrome(url)
|
330
331
|
sb.sleep(2.5)
|
331
332
|
sb.gui_click_captcha()
|
332
|
-
sb.highlight('h1:contains("GitLab
|
333
|
+
sb.highlight('h1:contains("GitLab")')
|
333
334
|
sb.highlight('button:contains("Sign in")')
|
334
335
|
sb.driver.stop()
|
335
336
|
```
|
336
337
|
|
337
|
-
> (Due to changes in Chrome 137 where the `--load-extension` switch was removed, you can't load extensions directly from this format.)
|
338
|
-
|
339
338
|
--------
|
340
339
|
|
341
340
|
<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>
|
@@ -1,7 +1,6 @@
|
|
1
1
|
packaging>=25.0
|
2
2
|
wheel>=0.45.1
|
3
|
-
|
4
|
-
certifi>=2025.8.3
|
3
|
+
certifi>=2025.10.5
|
5
4
|
exceptiongroup>=1.3.0
|
6
5
|
fasteners>=0.20
|
7
6
|
mycdp>=1.2.0
|
@@ -51,6 +50,7 @@ markdown-it-py==3.0.0
|
|
51
50
|
|
52
51
|
[:python_version < "3.9"]
|
53
52
|
pip>=25.0.1
|
53
|
+
attrs~=25.3.0
|
54
54
|
websockets~=13.1
|
55
55
|
filelock~=3.16.1
|
56
56
|
platformdirs>=4.3.6
|
@@ -74,6 +74,7 @@ markdown-it-py==4.0.0
|
|
74
74
|
|
75
75
|
[:python_version >= "3.9"]
|
76
76
|
pip>=25.2
|
77
|
+
attrs>=25.4.0
|
77
78
|
websockets>=15.0.1
|
78
79
|
filelock>=3.19.1
|
79
80
|
platformdirs>=4.4.0
|
@@ -152,8 +152,9 @@ setup(
|
|
152
152
|
'setuptools~=70.2;python_version<"3.10"', # Newer ones had issues
|
153
153
|
'setuptools>=80.9.0;python_version>="3.10"',
|
154
154
|
'wheel>=0.45.1',
|
155
|
-
'attrs
|
156
|
-
|
155
|
+
'attrs~=25.3.0;python_version<"3.9"',
|
156
|
+
'attrs>=25.4.0;python_version>="3.9"',
|
157
|
+
"certifi>=2025.10.5",
|
157
158
|
"exceptiongroup>=1.3.0",
|
158
159
|
'websockets~=13.1;python_version<"3.9"',
|
159
160
|
'websockets>=15.0.1;python_version>="3.9"',
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
{seleniumbase-4.42.0 → seleniumbase-4.42.2}/seleniumbase/undetected/cdp_driver/_contradict.py
RENAMED
File without changes
|
File without changes
|
{seleniumbase-4.42.0 → seleniumbase-4.42.2}/seleniumbase/undetected/cdp_driver/connection.py
RENAMED
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
{seleniumbase-4.42.0 → seleniumbase-4.42.2}/seleniumbase/utilities/selenium_grid/__init__.py
RENAMED
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
{seleniumbase-4.42.0 → seleniumbase-4.42.2}/seleniumbase/utilities/selenium_grid/grid_hub.py
RENAMED
File without changes
|
{seleniumbase-4.42.0 → seleniumbase-4.42.2}/seleniumbase/utilities/selenium_grid/grid_node.py
RENAMED
File without changes
|
File without changes
|
File without changes
|
{seleniumbase-4.42.0 → seleniumbase-4.42.2}/seleniumbase/utilities/selenium_grid/start-grid-hub.bat
RENAMED
File without changes
|
{seleniumbase-4.42.0 → seleniumbase-4.42.2}/seleniumbase/utilities/selenium_grid/start-grid-hub.sh
RENAMED
File without changes
|
File without changes
|
{seleniumbase-4.42.0 → seleniumbase-4.42.2}/seleniumbase/utilities/selenium_ide/convert_ide.py
RENAMED
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|