seleniumbase 4.49.8__tar.gz → 4.49.10__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.49.8/seleniumbase.egg-info → seleniumbase-4.49.10}/PKG-INFO +10 -9
- {seleniumbase-4.49.8 → seleniumbase-4.49.10}/README.md +8 -7
- {seleniumbase-4.49.8 → seleniumbase-4.49.10}/requirements.txt +1 -1
- seleniumbase-4.49.10/seleniumbase/__version__.py +2 -0
- {seleniumbase-4.49.8 → seleniumbase-4.49.10}/seleniumbase/core/browser_launcher.py +16 -10
- {seleniumbase-4.49.8 → seleniumbase-4.49.10}/seleniumbase/core/sb_cdp.py +116 -4
- {seleniumbase-4.49.8 → seleniumbase-4.49.10}/seleniumbase/fixtures/base_case.py +54 -0
- {seleniumbase-4.49.8 → seleniumbase-4.49.10}/seleniumbase/undetected/cdp_driver/browser.py +6 -0
- {seleniumbase-4.49.8 → seleniumbase-4.49.10}/seleniumbase/undetected/cdp_driver/cdp_util.py +2 -0
- {seleniumbase-4.49.8 → seleniumbase-4.49.10}/seleniumbase/undetected/cdp_driver/connection.py +13 -0
- {seleniumbase-4.49.8 → seleniumbase-4.49.10}/seleniumbase/undetected/cdp_driver/element.py +9 -3
- {seleniumbase-4.49.8 → seleniumbase-4.49.10}/seleniumbase/undetected/cdp_driver/tab.py +25 -36
- {seleniumbase-4.49.8 → seleniumbase-4.49.10/seleniumbase.egg-info}/PKG-INFO +10 -9
- {seleniumbase-4.49.8 → seleniumbase-4.49.10}/seleniumbase.egg-info/requires.txt +1 -1
- {seleniumbase-4.49.8 → seleniumbase-4.49.10}/setup.py +1 -1
- seleniumbase-4.49.8/seleniumbase/__version__.py +0 -2
- {seleniumbase-4.49.8 → seleniumbase-4.49.10}/.gitignore +0 -0
- {seleniumbase-4.49.8 → seleniumbase-4.49.10}/LICENSE +0 -0
- {seleniumbase-4.49.8 → seleniumbase-4.49.10}/MANIFEST.in +0 -0
- {seleniumbase-4.49.8 → seleniumbase-4.49.10}/install.sh +0 -0
- {seleniumbase-4.49.8 → seleniumbase-4.49.10}/pyproject.toml +0 -0
- {seleniumbase-4.49.8 → seleniumbase-4.49.10}/pytest.ini +0 -0
- {seleniumbase-4.49.8 → seleniumbase-4.49.10}/sbase/__init__.py +0 -0
- {seleniumbase-4.49.8 → seleniumbase-4.49.10}/sbase/__main__.py +0 -0
- {seleniumbase-4.49.8 → seleniumbase-4.49.10}/sbase/steps.py +0 -0
- {seleniumbase-4.49.8 → seleniumbase-4.49.10}/seleniumbase/__init__.py +0 -0
- {seleniumbase-4.49.8 → seleniumbase-4.49.10}/seleniumbase/__main__.py +0 -0
- {seleniumbase-4.49.8 → seleniumbase-4.49.10}/seleniumbase/behave/__init__.py +0 -0
- {seleniumbase-4.49.8 → seleniumbase-4.49.10}/seleniumbase/behave/behave_helper.py +0 -0
- {seleniumbase-4.49.8 → seleniumbase-4.49.10}/seleniumbase/behave/behave_sb.py +0 -0
- {seleniumbase-4.49.8 → seleniumbase-4.49.10}/seleniumbase/behave/steps.py +0 -0
- {seleniumbase-4.49.8 → seleniumbase-4.49.10}/seleniumbase/common/__init__.py +0 -0
- {seleniumbase-4.49.8 → seleniumbase-4.49.10}/seleniumbase/common/decorators.py +0 -0
- {seleniumbase-4.49.8 → seleniumbase-4.49.10}/seleniumbase/common/encryption.py +0 -0
- {seleniumbase-4.49.8 → seleniumbase-4.49.10}/seleniumbase/common/exceptions.py +0 -0
- {seleniumbase-4.49.8 → seleniumbase-4.49.10}/seleniumbase/common/obfuscate.py +0 -0
- {seleniumbase-4.49.8 → seleniumbase-4.49.10}/seleniumbase/common/unobfuscate.py +0 -0
- {seleniumbase-4.49.8 → seleniumbase-4.49.10}/seleniumbase/config/__init__.py +0 -0
- {seleniumbase-4.49.8 → seleniumbase-4.49.10}/seleniumbase/config/ad_block_list.py +0 -0
- {seleniumbase-4.49.8 → seleniumbase-4.49.10}/seleniumbase/config/proxy_list.py +0 -0
- {seleniumbase-4.49.8 → seleniumbase-4.49.10}/seleniumbase/config/settings.py +0 -0
- {seleniumbase-4.49.8 → seleniumbase-4.49.10}/seleniumbase/console_scripts/__init__.py +0 -0
- {seleniumbase-4.49.8 → seleniumbase-4.49.10}/seleniumbase/console_scripts/logo_helper.py +0 -0
- {seleniumbase-4.49.8 → seleniumbase-4.49.10}/seleniumbase/console_scripts/rich_helper.py +0 -0
- {seleniumbase-4.49.8 → seleniumbase-4.49.10}/seleniumbase/console_scripts/run.py +0 -0
- {seleniumbase-4.49.8 → seleniumbase-4.49.10}/seleniumbase/console_scripts/sb_behave_gui.py +0 -0
- {seleniumbase-4.49.8 → seleniumbase-4.49.10}/seleniumbase/console_scripts/sb_caseplans.py +0 -0
- {seleniumbase-4.49.8 → seleniumbase-4.49.10}/seleniumbase/console_scripts/sb_commander.py +0 -0
- {seleniumbase-4.49.8 → seleniumbase-4.49.10}/seleniumbase/console_scripts/sb_install.py +0 -0
- {seleniumbase-4.49.8 → seleniumbase-4.49.10}/seleniumbase/console_scripts/sb_mkchart.py +0 -0
- {seleniumbase-4.49.8 → seleniumbase-4.49.10}/seleniumbase/console_scripts/sb_mkdir.py +0 -0
- {seleniumbase-4.49.8 → seleniumbase-4.49.10}/seleniumbase/console_scripts/sb_mkfile.py +0 -0
- {seleniumbase-4.49.8 → seleniumbase-4.49.10}/seleniumbase/console_scripts/sb_mkpres.py +0 -0
- {seleniumbase-4.49.8 → seleniumbase-4.49.10}/seleniumbase/console_scripts/sb_mkrec.py +0 -0
- {seleniumbase-4.49.8 → seleniumbase-4.49.10}/seleniumbase/console_scripts/sb_objectify.py +0 -0
- {seleniumbase-4.49.8 → seleniumbase-4.49.10}/seleniumbase/console_scripts/sb_print.py +0 -0
- {seleniumbase-4.49.8 → seleniumbase-4.49.10}/seleniumbase/console_scripts/sb_recorder.py +0 -0
- {seleniumbase-4.49.8 → seleniumbase-4.49.10}/seleniumbase/core/__init__.py +0 -0
- {seleniumbase-4.49.8 → seleniumbase-4.49.10}/seleniumbase/core/application_manager.py +0 -0
- {seleniumbase-4.49.8 → seleniumbase-4.49.10}/seleniumbase/core/capabilities_parser.py +0 -0
- {seleniumbase-4.49.8 → seleniumbase-4.49.10}/seleniumbase/core/colored_traceback.py +0 -0
- {seleniumbase-4.49.8 → seleniumbase-4.49.10}/seleniumbase/core/create_db_tables.sql +0 -0
- {seleniumbase-4.49.8 → seleniumbase-4.49.10}/seleniumbase/core/detect_b_ver.py +0 -0
- {seleniumbase-4.49.8 → seleniumbase-4.49.10}/seleniumbase/core/download_helper.py +0 -0
- {seleniumbase-4.49.8 → seleniumbase-4.49.10}/seleniumbase/core/encoded_images.py +0 -0
- {seleniumbase-4.49.8 → seleniumbase-4.49.10}/seleniumbase/core/jqc_helper.py +0 -0
- {seleniumbase-4.49.8 → seleniumbase-4.49.10}/seleniumbase/core/log_helper.py +0 -0
- {seleniumbase-4.49.8 → seleniumbase-4.49.10}/seleniumbase/core/mysql.py +0 -0
- {seleniumbase-4.49.8 → seleniumbase-4.49.10}/seleniumbase/core/nest_asyncio.py +0 -0
- {seleniumbase-4.49.8 → seleniumbase-4.49.10}/seleniumbase/core/proxy_helper.py +0 -0
- {seleniumbase-4.49.8 → seleniumbase-4.49.10}/seleniumbase/core/recorder_helper.py +0 -0
- {seleniumbase-4.49.8 → seleniumbase-4.49.10}/seleniumbase/core/report_helper.py +0 -0
- {seleniumbase-4.49.8 → seleniumbase-4.49.10}/seleniumbase/core/s3_manager.py +0 -0
- {seleniumbase-4.49.8 → seleniumbase-4.49.10}/seleniumbase/core/sb_driver.py +0 -0
- {seleniumbase-4.49.8 → seleniumbase-4.49.10}/seleniumbase/core/session_helper.py +0 -0
- {seleniumbase-4.49.8 → seleniumbase-4.49.10}/seleniumbase/core/settings_parser.py +0 -0
- {seleniumbase-4.49.8 → seleniumbase-4.49.10}/seleniumbase/core/style_sheet.py +0 -0
- {seleniumbase-4.49.8 → seleniumbase-4.49.10}/seleniumbase/core/testcase_manager.py +0 -0
- {seleniumbase-4.49.8 → seleniumbase-4.49.10}/seleniumbase/core/tour_helper.py +0 -0
- {seleniumbase-4.49.8 → seleniumbase-4.49.10}/seleniumbase/core/visual_helper.py +0 -0
- {seleniumbase-4.49.8 → seleniumbase-4.49.10}/seleniumbase/drivers/__init__.py +0 -0
- {seleniumbase-4.49.8 → seleniumbase-4.49.10}/seleniumbase/drivers/atlas_drivers/__init__.py +0 -0
- {seleniumbase-4.49.8 → seleniumbase-4.49.10}/seleniumbase/drivers/brave_drivers/__init__.py +0 -0
- {seleniumbase-4.49.8 → seleniumbase-4.49.10}/seleniumbase/drivers/cft_drivers/__init__.py +0 -0
- {seleniumbase-4.49.8 → seleniumbase-4.49.10}/seleniumbase/drivers/chromium_drivers/__init__.py +0 -0
- {seleniumbase-4.49.8 → seleniumbase-4.49.10}/seleniumbase/drivers/chs_drivers/__init__.py +0 -0
- {seleniumbase-4.49.8 → seleniumbase-4.49.10}/seleniumbase/drivers/comet_drivers/__init__.py +0 -0
- {seleniumbase-4.49.8 → seleniumbase-4.49.10}/seleniumbase/drivers/opera_drivers/__init__.py +0 -0
- {seleniumbase-4.49.8 → seleniumbase-4.49.10}/seleniumbase/extensions/__init__.py +0 -0
- {seleniumbase-4.49.8 → seleniumbase-4.49.10}/seleniumbase/extensions/ad_block.zip +0 -0
- {seleniumbase-4.49.8 → seleniumbase-4.49.10}/seleniumbase/extensions/disable_csp.zip +0 -0
- {seleniumbase-4.49.8 → seleniumbase-4.49.10}/seleniumbase/extensions/recorder.zip +0 -0
- {seleniumbase-4.49.8 → seleniumbase-4.49.10}/seleniumbase/extensions/sbase_ext.zip +0 -0
- {seleniumbase-4.49.8 → seleniumbase-4.49.10}/seleniumbase/fixtures/__init__.py +0 -0
- {seleniumbase-4.49.8 → seleniumbase-4.49.10}/seleniumbase/fixtures/constants.py +0 -0
- {seleniumbase-4.49.8 → seleniumbase-4.49.10}/seleniumbase/fixtures/css_to_xpath.py +0 -0
- {seleniumbase-4.49.8 → seleniumbase-4.49.10}/seleniumbase/fixtures/errors.py +0 -0
- {seleniumbase-4.49.8 → seleniumbase-4.49.10}/seleniumbase/fixtures/js_utils.py +0 -0
- {seleniumbase-4.49.8 → seleniumbase-4.49.10}/seleniumbase/fixtures/page_actions.py +0 -0
- {seleniumbase-4.49.8 → seleniumbase-4.49.10}/seleniumbase/fixtures/page_utils.py +0 -0
- {seleniumbase-4.49.8 → seleniumbase-4.49.10}/seleniumbase/fixtures/shared_utils.py +0 -0
- {seleniumbase-4.49.8 → seleniumbase-4.49.10}/seleniumbase/fixtures/unittest_helper.py +0 -0
- {seleniumbase-4.49.8 → seleniumbase-4.49.10}/seleniumbase/fixtures/words.py +0 -0
- {seleniumbase-4.49.8 → seleniumbase-4.49.10}/seleniumbase/fixtures/xpath_to_css.py +0 -0
- {seleniumbase-4.49.8 → seleniumbase-4.49.10}/seleniumbase/js_code/__init__.py +0 -0
- {seleniumbase-4.49.8 → seleniumbase-4.49.10}/seleniumbase/js_code/active_css_js.py +0 -0
- {seleniumbase-4.49.8 → seleniumbase-4.49.10}/seleniumbase/js_code/live_js.py +0 -0
- {seleniumbase-4.49.8 → seleniumbase-4.49.10}/seleniumbase/js_code/recorder_js.py +0 -0
- {seleniumbase-4.49.8 → seleniumbase-4.49.10}/seleniumbase/masterqa/__init__.py +0 -0
- {seleniumbase-4.49.8 → seleniumbase-4.49.10}/seleniumbase/masterqa/master_qa.py +0 -0
- {seleniumbase-4.49.8 → seleniumbase-4.49.10}/seleniumbase/plugins/__init__.py +0 -0
- {seleniumbase-4.49.8 → seleniumbase-4.49.10}/seleniumbase/plugins/base_plugin.py +0 -0
- {seleniumbase-4.49.8 → seleniumbase-4.49.10}/seleniumbase/plugins/basic_test_info.py +0 -0
- {seleniumbase-4.49.8 → seleniumbase-4.49.10}/seleniumbase/plugins/db_reporting_plugin.py +0 -0
- {seleniumbase-4.49.8 → seleniumbase-4.49.10}/seleniumbase/plugins/driver_manager.py +0 -0
- {seleniumbase-4.49.8 → seleniumbase-4.49.10}/seleniumbase/plugins/page_source.py +0 -0
- {seleniumbase-4.49.8 → seleniumbase-4.49.10}/seleniumbase/plugins/pytest_plugin.py +0 -0
- {seleniumbase-4.49.8 → seleniumbase-4.49.10}/seleniumbase/plugins/s3_logging_plugin.py +0 -0
- {seleniumbase-4.49.8 → seleniumbase-4.49.10}/seleniumbase/plugins/sb_manager.py +0 -0
- {seleniumbase-4.49.8 → seleniumbase-4.49.10}/seleniumbase/plugins/screen_shots.py +0 -0
- {seleniumbase-4.49.8 → seleniumbase-4.49.10}/seleniumbase/plugins/selenium_plugin.py +0 -0
- {seleniumbase-4.49.8 → seleniumbase-4.49.10}/seleniumbase/resources/__init__.py +0 -0
- {seleniumbase-4.49.8 → seleniumbase-4.49.10}/seleniumbase/translate/__init__.py +0 -0
- {seleniumbase-4.49.8 → seleniumbase-4.49.10}/seleniumbase/translate/chinese.py +0 -0
- {seleniumbase-4.49.8 → seleniumbase-4.49.10}/seleniumbase/translate/dutch.py +0 -0
- {seleniumbase-4.49.8 → seleniumbase-4.49.10}/seleniumbase/translate/french.py +0 -0
- {seleniumbase-4.49.8 → seleniumbase-4.49.10}/seleniumbase/translate/italian.py +0 -0
- {seleniumbase-4.49.8 → seleniumbase-4.49.10}/seleniumbase/translate/japanese.py +0 -0
- {seleniumbase-4.49.8 → seleniumbase-4.49.10}/seleniumbase/translate/korean.py +0 -0
- {seleniumbase-4.49.8 → seleniumbase-4.49.10}/seleniumbase/translate/master_dict.py +0 -0
- {seleniumbase-4.49.8 → seleniumbase-4.49.10}/seleniumbase/translate/portuguese.py +0 -0
- {seleniumbase-4.49.8 → seleniumbase-4.49.10}/seleniumbase/translate/russian.py +0 -0
- {seleniumbase-4.49.8 → seleniumbase-4.49.10}/seleniumbase/translate/spanish.py +0 -0
- {seleniumbase-4.49.8 → seleniumbase-4.49.10}/seleniumbase/translate/translator.py +0 -0
- {seleniumbase-4.49.8 → seleniumbase-4.49.10}/seleniumbase/undetected/__init__.py +0 -0
- {seleniumbase-4.49.8 → seleniumbase-4.49.10}/seleniumbase/undetected/cdp.py +0 -0
- {seleniumbase-4.49.8 → seleniumbase-4.49.10}/seleniumbase/undetected/cdp_driver/__init__.py +0 -0
- {seleniumbase-4.49.8 → seleniumbase-4.49.10}/seleniumbase/undetected/cdp_driver/_contradict.py +0 -0
- {seleniumbase-4.49.8 → seleniumbase-4.49.10}/seleniumbase/undetected/cdp_driver/config.py +0 -0
- {seleniumbase-4.49.8 → seleniumbase-4.49.10}/seleniumbase/undetected/dprocess.py +0 -0
- {seleniumbase-4.49.8 → seleniumbase-4.49.10}/seleniumbase/undetected/options.py +0 -0
- {seleniumbase-4.49.8 → seleniumbase-4.49.10}/seleniumbase/undetected/patcher.py +0 -0
- {seleniumbase-4.49.8 → seleniumbase-4.49.10}/seleniumbase/undetected/reactor.py +0 -0
- {seleniumbase-4.49.8 → seleniumbase-4.49.10}/seleniumbase/undetected/webelement.py +0 -0
- {seleniumbase-4.49.8 → seleniumbase-4.49.10}/seleniumbase/utilities/__init__.py +0 -0
- {seleniumbase-4.49.8 → seleniumbase-4.49.10}/seleniumbase/utilities/selenium_grid/__init__.py +0 -0
- {seleniumbase-4.49.8 → seleniumbase-4.49.10}/seleniumbase/utilities/selenium_grid/download_selenium_server.py +0 -0
- {seleniumbase-4.49.8 → seleniumbase-4.49.10}/seleniumbase/utilities/selenium_grid/font_color +0 -0
- {seleniumbase-4.49.8 → seleniumbase-4.49.10}/seleniumbase/utilities/selenium_grid/grid-hub +0 -0
- {seleniumbase-4.49.8 → seleniumbase-4.49.10}/seleniumbase/utilities/selenium_grid/grid-node +0 -0
- {seleniumbase-4.49.8 → seleniumbase-4.49.10}/seleniumbase/utilities/selenium_grid/grid_hub.py +0 -0
- {seleniumbase-4.49.8 → seleniumbase-4.49.10}/seleniumbase/utilities/selenium_grid/grid_node.py +0 -0
- {seleniumbase-4.49.8 → seleniumbase-4.49.10}/seleniumbase/utilities/selenium_grid/register-grid-node.bat +0 -0
- {seleniumbase-4.49.8 → seleniumbase-4.49.10}/seleniumbase/utilities/selenium_grid/register-grid-node.sh +0 -0
- {seleniumbase-4.49.8 → seleniumbase-4.49.10}/seleniumbase/utilities/selenium_grid/start-grid-hub.bat +0 -0
- {seleniumbase-4.49.8 → seleniumbase-4.49.10}/seleniumbase/utilities/selenium_grid/start-grid-hub.sh +0 -0
- {seleniumbase-4.49.8 → seleniumbase-4.49.10}/seleniumbase/utilities/selenium_ide/__init__.py +0 -0
- {seleniumbase-4.49.8 → seleniumbase-4.49.10}/seleniumbase/utilities/selenium_ide/convert_ide.py +0 -0
- {seleniumbase-4.49.8 → seleniumbase-4.49.10}/seleniumbase.egg-info/SOURCES.txt +0 -0
- {seleniumbase-4.49.8 → seleniumbase-4.49.10}/seleniumbase.egg-info/dependency_links.txt +0 -0
- {seleniumbase-4.49.8 → seleniumbase-4.49.10}/seleniumbase.egg-info/entry_points.txt +0 -0
- {seleniumbase-4.49.8 → seleniumbase-4.49.10}/seleniumbase.egg-info/top_level.txt +0 -0
- {seleniumbase-4.49.8 → seleniumbase-4.49.10}/setup.cfg +0 -0
- {seleniumbase-4.49.8 → seleniumbase-4.49.10}/virtualenv_install.sh +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: seleniumbase
|
|
3
|
-
Version: 4.49.
|
|
3
|
+
Version: 4.49.10
|
|
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
|
|
@@ -71,7 +71,7 @@ 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"
|
|
73
73
|
Requires-Dist: filelock~=3.19.1; python_version < "3.10"
|
|
74
|
-
Requires-Dist: filelock>=3.29.
|
|
74
|
+
Requires-Dist: filelock>=3.29.3; python_version >= "3.10"
|
|
75
75
|
Requires-Dist: fasteners>=0.20
|
|
76
76
|
Requires-Dist: mycdp>=1.3.7
|
|
77
77
|
Requires-Dist: pynose>=1.5.5
|
|
@@ -187,8 +187,8 @@ Dynamic: summary
|
|
|
187
187
|
<!-- SeleniumBase Docs -->
|
|
188
188
|
|
|
189
189
|
<meta property="og:site_name" content="SeleniumBase">
|
|
190
|
-
<meta property="og:title" content="SeleniumBase: Stealthy Chromium Automation and E2E Testing
|
|
191
|
-
<meta property="og:description" content="Stealthy Chromium Automation and
|
|
190
|
+
<meta property="og:title" content="SeleniumBase: Stealthy Chromium Automation with Python; and E2E Testing." />
|
|
191
|
+
<meta property="og:description" content="Stealthy Chromium Automation, including fast, easy, and reliable Web/UI testing with Python." />
|
|
192
192
|
<meta property="og:keywords" content="Python, pytest, selenium, webdriver, testing, automation, seleniumbase, framework, dashboard, recorder, reports, screenshots, playwright, stealth, CAPTCHA">
|
|
193
193
|
<meta property="og:image" content="https://seleniumbase.github.io/cdn/img/mac_sb_logo_5b.png" />
|
|
194
194
|
<link rel="icon" href="https://seleniumbase.github.io/img/logo6.png" />
|
|
@@ -306,8 +306,8 @@ sb.quit()
|
|
|
306
306
|
```python
|
|
307
307
|
from seleniumbase import sb_cdp
|
|
308
308
|
|
|
309
|
-
|
|
310
|
-
sb
|
|
309
|
+
sb = sb_cdp.Chrome()
|
|
310
|
+
sb.goto("https://news.ycombinator.com/submitted?id=seleniumbase")
|
|
311
311
|
elements = sb.find_elements("span.titleline > a")
|
|
312
312
|
for element in elements:
|
|
313
313
|
print("* " + element.text)
|
|
@@ -346,7 +346,7 @@ Google Chrome is the default browser. Only unbranded Chromium and Chrome-for-Tes
|
|
|
346
346
|
The Chromium browser can also be set via method args, eg: `cft=True`, `use_chromium=True`, `browser="edge"`, `browser="brave"`, etc. Eg:
|
|
347
347
|
|
|
348
348
|
```python
|
|
349
|
-
sb = sb_cdp.Chrome(
|
|
349
|
+
sb = sb_cdp.Chrome(use_chromium=True)
|
|
350
350
|
```
|
|
351
351
|
|
|
352
352
|
--------
|
|
@@ -404,12 +404,13 @@ with SB(uc=True, test=True, locale="en") as sb:
|
|
|
404
404
|
```python
|
|
405
405
|
from seleniumbase import sb_cdp
|
|
406
406
|
|
|
407
|
-
|
|
408
|
-
sb
|
|
407
|
+
sb = sb_cdp.Chrome(incognito=True)
|
|
408
|
+
sb.goto("https://gitlab.com/users/sign_in")
|
|
409
409
|
sb.sleep(2)
|
|
410
410
|
sb.solve_captcha()
|
|
411
411
|
sb.highlight('h1:contains("GitLab")')
|
|
412
412
|
sb.highlight('button:contains("Sign in")')
|
|
413
|
+
sb.quit()
|
|
413
414
|
```
|
|
414
415
|
|
|
415
416
|
--------
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
<!-- SeleniumBase Docs -->
|
|
2
2
|
|
|
3
3
|
<meta property="og:site_name" content="SeleniumBase">
|
|
4
|
-
<meta property="og:title" content="SeleniumBase: Stealthy Chromium Automation and E2E Testing
|
|
5
|
-
<meta property="og:description" content="Stealthy Chromium Automation and
|
|
4
|
+
<meta property="og:title" content="SeleniumBase: Stealthy Chromium Automation with Python; and E2E Testing." />
|
|
5
|
+
<meta property="og:description" content="Stealthy Chromium Automation, including fast, easy, and reliable Web/UI testing with Python." />
|
|
6
6
|
<meta property="og:keywords" content="Python, pytest, selenium, webdriver, testing, automation, seleniumbase, framework, dashboard, recorder, reports, screenshots, playwright, stealth, CAPTCHA">
|
|
7
7
|
<meta property="og:image" content="https://seleniumbase.github.io/cdn/img/mac_sb_logo_5b.png" />
|
|
8
8
|
<link rel="icon" href="https://seleniumbase.github.io/img/logo6.png" />
|
|
@@ -120,8 +120,8 @@ sb.quit()
|
|
|
120
120
|
```python
|
|
121
121
|
from seleniumbase import sb_cdp
|
|
122
122
|
|
|
123
|
-
|
|
124
|
-
sb
|
|
123
|
+
sb = sb_cdp.Chrome()
|
|
124
|
+
sb.goto("https://news.ycombinator.com/submitted?id=seleniumbase")
|
|
125
125
|
elements = sb.find_elements("span.titleline > a")
|
|
126
126
|
for element in elements:
|
|
127
127
|
print("* " + element.text)
|
|
@@ -160,7 +160,7 @@ Google Chrome is the default browser. Only unbranded Chromium and Chrome-for-Tes
|
|
|
160
160
|
The Chromium browser can also be set via method args, eg: `cft=True`, `use_chromium=True`, `browser="edge"`, `browser="brave"`, etc. Eg:
|
|
161
161
|
|
|
162
162
|
```python
|
|
163
|
-
sb = sb_cdp.Chrome(
|
|
163
|
+
sb = sb_cdp.Chrome(use_chromium=True)
|
|
164
164
|
```
|
|
165
165
|
|
|
166
166
|
--------
|
|
@@ -218,12 +218,13 @@ with SB(uc=True, test=True, locale="en") as sb:
|
|
|
218
218
|
```python
|
|
219
219
|
from seleniumbase import sb_cdp
|
|
220
220
|
|
|
221
|
-
|
|
222
|
-
sb
|
|
221
|
+
sb = sb_cdp.Chrome(incognito=True)
|
|
222
|
+
sb.goto("https://gitlab.com/users/sign_in")
|
|
223
223
|
sb.sleep(2)
|
|
224
224
|
sb.solve_captcha()
|
|
225
225
|
sb.highlight('h1:contains("GitLab")')
|
|
226
226
|
sb.highlight('button:contains("Sign in")')
|
|
227
|
+
sb.quit()
|
|
227
228
|
```
|
|
228
229
|
|
|
229
230
|
--------
|
|
@@ -10,7 +10,7 @@ exceptiongroup>=1.3.1
|
|
|
10
10
|
websockets~=15.0.1;python_version<"3.10"
|
|
11
11
|
websockets>=16.0;python_version>="3.10"
|
|
12
12
|
filelock~=3.19.1;python_version<"3.10"
|
|
13
|
-
filelock>=3.29.
|
|
13
|
+
filelock>=3.29.3;python_version>="3.10"
|
|
14
14
|
fasteners>=0.20
|
|
15
15
|
mycdp>=1.3.7
|
|
16
16
|
pynose>=1.5.5
|
|
@@ -18,11 +18,7 @@ from selenium.common.exceptions import ElementClickInterceptedException
|
|
|
18
18
|
from selenium.common.exceptions import InvalidSessionIdException
|
|
19
19
|
from selenium.common.exceptions import SessionNotCreatedException
|
|
20
20
|
from selenium.webdriver.chrome.service import Service as ChromeService
|
|
21
|
-
from selenium.webdriver.common
|
|
22
|
-
from selenium.webdriver.common.service import utils as service_utils
|
|
23
|
-
from selenium.webdriver.edge.service import Service as EdgeService
|
|
24
|
-
from selenium.webdriver.firefox.service import Service as FirefoxService
|
|
25
|
-
from selenium.webdriver.safari.service import Service as SafariService
|
|
21
|
+
from selenium.webdriver.common import utils as common_utils
|
|
26
22
|
from seleniumbase import config as sb_config
|
|
27
23
|
from seleniumbase import decorators
|
|
28
24
|
from seleniumbase import drivers # webdriver storage folder for SeleniumBase
|
|
@@ -793,6 +789,7 @@ def uc_open_with_cdp_mode(driver, url=None, **kwargs):
|
|
|
793
789
|
cdp.grant_permissions = CDPM.grant_permissions
|
|
794
790
|
cdp.grant_all_permissions = CDPM.grant_all_permissions
|
|
795
791
|
cdp.reset_permissions = CDPM.reset_permissions
|
|
792
|
+
cdp.get_all_urls = CDPM.get_all_urls
|
|
796
793
|
cdp.get_all_cookies = CDPM.get_all_cookies
|
|
797
794
|
cdp.set_all_cookies = CDPM.set_all_cookies
|
|
798
795
|
cdp.save_cookies = CDPM.save_cookies
|
|
@@ -831,6 +828,11 @@ def uc_open_with_cdp_mode(driver, url=None, **kwargs):
|
|
|
831
828
|
cdp.activate_messenger = CDPM.activate_messenger
|
|
832
829
|
cdp.set_messenger_theme = CDPM.set_messenger_theme
|
|
833
830
|
cdp.post_message = CDPM.post_message
|
|
831
|
+
cdp.download_file = CDPM.download_file
|
|
832
|
+
cdp.save_file_as = CDPM.save_file_as
|
|
833
|
+
cdp.assert_downloaded_file = CDPM.assert_downloaded_file
|
|
834
|
+
cdp.get_path_of_downloaded_file = CDPM.get_path_of_downloaded_file
|
|
835
|
+
cdp.set_download_path = CDPM.set_download_path
|
|
834
836
|
cdp.set_locale = CDPM.set_locale
|
|
835
837
|
cdp.set_local_storage_item = CDPM.set_local_storage_item
|
|
836
838
|
cdp.set_session_storage_item = CDPM.set_session_storage_item
|
|
@@ -2668,7 +2670,7 @@ def _set_chrome_options(
|
|
|
2668
2670
|
args = " ".join(sys.argv)
|
|
2669
2671
|
debug_port = 9222
|
|
2670
2672
|
if ("-n" in sys.argv or " -n=" in args or args == "-c"):
|
|
2671
|
-
debug_port =
|
|
2673
|
+
debug_port = common_utils.free_port()
|
|
2672
2674
|
chrome_options.add_argument("--remote-debugging-port=%s" % debug_port)
|
|
2673
2675
|
if swiftshader:
|
|
2674
2676
|
chrome_options.add_argument("--use-gl=angle")
|
|
@@ -3672,6 +3674,7 @@ def get_remote_driver(
|
|
|
3672
3674
|
device_height,
|
|
3673
3675
|
device_pixel_ratio,
|
|
3674
3676
|
):
|
|
3677
|
+
from selenium.webdriver.common.options import ArgOptions
|
|
3675
3678
|
# Construct the address for connecting to a Selenium Grid
|
|
3676
3679
|
if servername.startswith("https://"):
|
|
3677
3680
|
protocol = "https"
|
|
@@ -4130,6 +4133,7 @@ def get_local_driver(
|
|
|
4130
4133
|
b_path = binary_location
|
|
4131
4134
|
use_uc = is_using_uc(undetectable, browser_name)
|
|
4132
4135
|
if browser_name == constants.Browser.FIREFOX:
|
|
4136
|
+
from selenium.webdriver.firefox.service import Service as FFService
|
|
4133
4137
|
firefox_options = _set_firefox_options(
|
|
4134
4138
|
downloads_path,
|
|
4135
4139
|
headless,
|
|
@@ -4184,7 +4188,7 @@ def get_local_driver(
|
|
|
4184
4188
|
sys.argv = sys_args # Put back original sys args
|
|
4185
4189
|
# Launch Firefox
|
|
4186
4190
|
if os.path.exists(local_geckodriver):
|
|
4187
|
-
service =
|
|
4191
|
+
service = FFService(
|
|
4188
4192
|
executable_path=local_geckodriver,
|
|
4189
4193
|
log_output=os.devnull,
|
|
4190
4194
|
)
|
|
@@ -4229,7 +4233,7 @@ def get_local_driver(
|
|
|
4229
4233
|
else:
|
|
4230
4234
|
raise # Not an obvious fix.
|
|
4231
4235
|
else:
|
|
4232
|
-
service =
|
|
4236
|
+
service = FFService(log_output=os.devnull)
|
|
4233
4237
|
try:
|
|
4234
4238
|
driver = webdriver.Firefox(
|
|
4235
4239
|
service=service,
|
|
@@ -4337,6 +4341,7 @@ def get_local_driver(
|
|
|
4337
4341
|
driver = webdriver.Ie(service=service, options=ie_options)
|
|
4338
4342
|
return extend_driver(driver)
|
|
4339
4343
|
elif browser_name == constants.Browser.EDGE:
|
|
4344
|
+
from selenium.webdriver.edge.service import Service as EdgeService
|
|
4340
4345
|
prefs = {
|
|
4341
4346
|
"download.default_directory": downloads_path,
|
|
4342
4347
|
"download.directory_upgrade": True,
|
|
@@ -4756,7 +4761,7 @@ def get_local_driver(
|
|
|
4756
4761
|
args = " ".join(sys.argv)
|
|
4757
4762
|
free_port = 9222
|
|
4758
4763
|
if ("-n" in sys.argv or " -n=" in args or args == "-c"):
|
|
4759
|
-
free_port =
|
|
4764
|
+
free_port = common_utils.free_port()
|
|
4760
4765
|
edge_options.add_argument("--remote-debugging-port=%s" % free_port)
|
|
4761
4766
|
if swiftshader:
|
|
4762
4767
|
edge_options.add_argument("--use-gl=angle")
|
|
@@ -4866,7 +4871,7 @@ def get_local_driver(
|
|
|
4866
4871
|
args = " ".join(sys.argv)
|
|
4867
4872
|
free_port = 9222
|
|
4868
4873
|
if ("-n" in sys.argv or " -n=" in args or args == "-c"):
|
|
4869
|
-
free_port =
|
|
4874
|
+
free_port = common_utils.free_port()
|
|
4870
4875
|
edge_options.add_argument(
|
|
4871
4876
|
"--remote-debugging-port=%s" % free_port
|
|
4872
4877
|
)
|
|
@@ -4904,6 +4909,7 @@ def get_local_driver(
|
|
|
4904
4909
|
raise Exception("Can't run Safari tests in multithreaded mode!")
|
|
4905
4910
|
warnings.simplefilter("ignore", category=DeprecationWarning)
|
|
4906
4911
|
from selenium.webdriver.safari.options import Options as SafariOptions
|
|
4912
|
+
from selenium.webdriver.safari.service import Service as SafariService
|
|
4907
4913
|
service = SafariService(quiet=False)
|
|
4908
4914
|
options = SafariOptions()
|
|
4909
4915
|
if (
|
|
@@ -152,6 +152,17 @@ class CDPMethods():
|
|
|
152
152
|
except Exception:
|
|
153
153
|
pass
|
|
154
154
|
|
|
155
|
+
def activate_cdp_mode(self, url=None, **kwargs):
|
|
156
|
+
"""If calling this method from here, then it was likely done
|
|
157
|
+
by accident because CDP Mode is already active at this point.
|
|
158
|
+
If URL, then navigate there with any kwargs that were passed.
|
|
159
|
+
If no URL (but kwargs are included) then refresh with kwargs.
|
|
160
|
+
If no URL and no kwargs either, then do nothing."""
|
|
161
|
+
if url:
|
|
162
|
+
self.get(url, **kwargs)
|
|
163
|
+
elif kwargs:
|
|
164
|
+
self.get(self.get_current_url(), **kwargs)
|
|
165
|
+
|
|
155
166
|
def open(self, url, **kwargs):
|
|
156
167
|
self.get(url, **kwargs)
|
|
157
168
|
|
|
@@ -752,6 +763,18 @@ class CDPMethods():
|
|
|
752
763
|
driver = driver.cdp_base
|
|
753
764
|
return self.loop.run_until_complete(driver.reset_permissions())
|
|
754
765
|
|
|
766
|
+
def get_all_urls(self, absolute=True):
|
|
767
|
+
"""
|
|
768
|
+
Convenience function that returns all links (a,link,img,script,meta).
|
|
769
|
+
:param absolute:
|
|
770
|
+
Try to build all the links in absolute form
|
|
771
|
+
instead of "as is", often relative.
|
|
772
|
+
:return: List of URLs.
|
|
773
|
+
"""
|
|
774
|
+
return self.loop.run_until_complete(
|
|
775
|
+
self.page.get_all_urls(absolute=absolute)
|
|
776
|
+
)
|
|
777
|
+
|
|
755
778
|
def get_all_cookies(self, *args, **kwargs):
|
|
756
779
|
driver = self.driver
|
|
757
780
|
if hasattr(driver, "cdp_base"):
|
|
@@ -1374,10 +1397,15 @@ class CDPMethods():
|
|
|
1374
1397
|
return self.find_element(selector).text_all
|
|
1375
1398
|
|
|
1376
1399
|
def get_title(self):
|
|
1400
|
+
"""Returns the title of the current web page."""
|
|
1377
1401
|
return self.loop.run_until_complete(
|
|
1378
1402
|
self.page.evaluate("document.title")
|
|
1379
1403
|
)
|
|
1380
1404
|
|
|
1405
|
+
def get_page_title(self):
|
|
1406
|
+
"""Same as get_title(), which returns the current page title."""
|
|
1407
|
+
return self.get_title()
|
|
1408
|
+
|
|
1381
1409
|
def get_current_url(self):
|
|
1382
1410
|
return self.loop.run_until_complete(
|
|
1383
1411
|
self.page.evaluate("window.location.href")
|
|
@@ -1725,6 +1753,80 @@ class CDPMethods():
|
|
|
1725
1753
|
duration = float(duration) + 0.15
|
|
1726
1754
|
time.sleep(float(duration))
|
|
1727
1755
|
|
|
1756
|
+
def download_file(self, file_url):
|
|
1757
|
+
"""Download a file from a URL.
|
|
1758
|
+
The default download location is: "./downloaded_files/"."""
|
|
1759
|
+
self.loop.run_until_complete(
|
|
1760
|
+
self.page.download_file(file_url)
|
|
1761
|
+
)
|
|
1762
|
+
|
|
1763
|
+
def save_file_as(self, file_url, new_file_name):
|
|
1764
|
+
"""Download a file from a URL and rename it.
|
|
1765
|
+
The default download location is: "./downloaded_files/"."""
|
|
1766
|
+
self.loop.run_until_complete(
|
|
1767
|
+
self.page.download_file(file_url, new_file_name)
|
|
1768
|
+
)
|
|
1769
|
+
|
|
1770
|
+
def assert_downloaded_file(self, file, timeout=None):
|
|
1771
|
+
"""Asserts that the file exists in SeleniumBase's [Downloads Folder].
|
|
1772
|
+
For browser click-initiated downloads, SeleniumBase will override
|
|
1773
|
+
the system [Downloads Folder] to be "./downloaded_files/".
|
|
1774
|
+
@Params
|
|
1775
|
+
file - The filename of the downloaded file.
|
|
1776
|
+
timeout - The time (seconds) to wait for the download to complete.
|
|
1777
|
+
browser - If True, uses the path set by click-initiated downloads."""
|
|
1778
|
+
downloads_folder = constants.Files.DOWNLOADS_FOLDER
|
|
1779
|
+
abs_path = os.path.abspath(".")
|
|
1780
|
+
downloads_path = os.path.join(abs_path, downloads_folder)
|
|
1781
|
+
if not timeout:
|
|
1782
|
+
timeout = settings.LARGE_TIMEOUT
|
|
1783
|
+
start_ms = time.time() * 1000.0
|
|
1784
|
+
stop_ms = start_ms + (timeout * 1000.0)
|
|
1785
|
+
downloaded_file_path = os.path.join(downloads_path, file)
|
|
1786
|
+
found = False
|
|
1787
|
+
for x in range(int(timeout)):
|
|
1788
|
+
shared_utils.check_if_time_limit_exceeded()
|
|
1789
|
+
try:
|
|
1790
|
+
self.assert_true(
|
|
1791
|
+
os.path.exists(downloaded_file_path),
|
|
1792
|
+
"File [%s] was not found in the downloads folder [%s]!"
|
|
1793
|
+
% (file, downloads_path),
|
|
1794
|
+
)
|
|
1795
|
+
found = True
|
|
1796
|
+
break
|
|
1797
|
+
except Exception:
|
|
1798
|
+
now_ms = time.time() * 1000.0
|
|
1799
|
+
if now_ms >= stop_ms:
|
|
1800
|
+
break
|
|
1801
|
+
time.sleep(1)
|
|
1802
|
+
if not found and not os.path.exists(downloaded_file_path):
|
|
1803
|
+
plural = "s"
|
|
1804
|
+
if timeout == 1:
|
|
1805
|
+
plural = ""
|
|
1806
|
+
message = (
|
|
1807
|
+
"File {%s} was not found in the downloads folder {%s} "
|
|
1808
|
+
"after %s second%s! (Or the download didn't complete!)"
|
|
1809
|
+
% (file, downloads_path, timeout, plural)
|
|
1810
|
+
)
|
|
1811
|
+
from seleniumbase.common.exceptions import NoSuchFileException
|
|
1812
|
+
raise NoSuchFileException(message)
|
|
1813
|
+
|
|
1814
|
+
def get_path_of_downloaded_file(self, file):
|
|
1815
|
+
"""This assumes the default location of SeleniumBase downloads,
|
|
1816
|
+
which is the "./downloaded_files/" folder where scripts run."""
|
|
1817
|
+
downloads_folder = constants.Files.DOWNLOADS_FOLDER
|
|
1818
|
+
abs_path = os.path.abspath(".")
|
|
1819
|
+
downloads_path = os.path.join(abs_path, downloads_folder)
|
|
1820
|
+
return os.path.join(downloads_path, file)
|
|
1821
|
+
|
|
1822
|
+
def set_download_path(self, path):
|
|
1823
|
+
"""Set a new download path for click-initiated downloads.
|
|
1824
|
+
(For Pure CDP Mode sync format only! -> sb_cdp.)
|
|
1825
|
+
The default download location is: "./downloaded_files/".
|
|
1826
|
+
Convenience methods such as assert_downloaded_file(file)
|
|
1827
|
+
will still expect the default location."""
|
|
1828
|
+
self.loop.run_until_complete(self.page.set_download_path(path))
|
|
1829
|
+
|
|
1728
1830
|
def set_locale(self, locale):
|
|
1729
1831
|
"""(Settings will take effect on the next page load)"""
|
|
1730
1832
|
self.loop.run_until_complete(self.page.set_locale(locale))
|
|
@@ -3233,13 +3335,23 @@ class CDPMethods():
|
|
|
3233
3335
|
)
|
|
3234
3336
|
return True
|
|
3235
3337
|
|
|
3236
|
-
def assert_true(self, expression):
|
|
3338
|
+
def assert_true(self, expression, msg=None):
|
|
3237
3339
|
if not expression:
|
|
3238
|
-
|
|
3340
|
+
if not msg:
|
|
3341
|
+
raise AssertionError("%s is not true" % expression)
|
|
3342
|
+
else:
|
|
3343
|
+
raise AssertionError(
|
|
3344
|
+
"%s is not true. (%s)" % (expression, msg)
|
|
3345
|
+
)
|
|
3239
3346
|
|
|
3240
|
-
def assert_false(self, expression):
|
|
3347
|
+
def assert_false(self, expression, msg=None):
|
|
3241
3348
|
if expression:
|
|
3242
|
-
|
|
3349
|
+
if not msg:
|
|
3350
|
+
raise AssertionError("%s is not false" % expression)
|
|
3351
|
+
else:
|
|
3352
|
+
raise AssertionError(
|
|
3353
|
+
"%s is not false. (%s)" % (expression, msg)
|
|
3354
|
+
)
|
|
3243
3355
|
|
|
3244
3356
|
def assert_equal(self, first, second):
|
|
3245
3357
|
if first != second:
|
|
@@ -5101,14 +5101,48 @@ class BaseCase(unittest.TestCase):
|
|
|
5101
5101
|
self.close_active_tab = self.cdp.close_active_tab
|
|
5102
5102
|
if hasattr(self.cdp, "find_element_by_text"):
|
|
5103
5103
|
self.find_element_by_text = self.cdp.find_element_by_text
|
|
5104
|
+
if hasattr(self.cdp, "find_elements_by_text"):
|
|
5105
|
+
self.find_elements_by_text = self.cdp.find_elements_by_text
|
|
5104
5106
|
if hasattr(self.cdp, "get_active_tab"):
|
|
5105
5107
|
self.get_active_tab = self.cdp.get_active_tab
|
|
5108
|
+
if hasattr(self.cdp, "get_all_cookies"):
|
|
5109
|
+
self.get_all_cookies = self.cdp.get_all_cookies
|
|
5110
|
+
if hasattr(self.cdp, "get_all_urls"):
|
|
5111
|
+
self.get_all_urls = self.cdp.get_all_urls
|
|
5112
|
+
if hasattr(self.cdp, "get_document"):
|
|
5113
|
+
self.get_document = self.cdp.get_document
|
|
5114
|
+
if hasattr(self.cdp, "get_element_attribute"):
|
|
5115
|
+
self.get_element_attribute = self.cdp.get_element_attribute
|
|
5116
|
+
if hasattr(self.cdp, "get_element_attributes"):
|
|
5117
|
+
self.get_element_attributes = self.cdp.get_element_attributes
|
|
5118
|
+
if hasattr(self.cdp, "get_element_html"):
|
|
5119
|
+
self.get_element_html = self.cdp.get_element_html
|
|
5106
5120
|
if hasattr(self.cdp, "get_endpoint_url"):
|
|
5107
5121
|
self.get_endpoint_url = self.cdp.get_endpoint_url
|
|
5108
5122
|
if hasattr(self.cdp, "get_event_loop"):
|
|
5109
5123
|
self.get_event_loop = self.cdp.get_event_loop
|
|
5124
|
+
if hasattr(self.cdp, "get_flattened_document"):
|
|
5125
|
+
self.get_flattened_document = self.cdp.get_flattened_document
|
|
5126
|
+
if hasattr(self.cdp, "get_navigation_history"):
|
|
5127
|
+
self.get_navigation_history = self.cdp.get_navigation_history
|
|
5128
|
+
if hasattr(self.cdp, "get_nested_element"):
|
|
5129
|
+
self.get_nested_element = self.cdp.get_nested_element
|
|
5130
|
+
if hasattr(self.cdp, "get_port"):
|
|
5131
|
+
self.get_port = self.cdp.get_port
|
|
5132
|
+
if hasattr(self.cdp, "get_rd_host"):
|
|
5133
|
+
self.get_rd_host = self.cdp.get_rd_host
|
|
5134
|
+
if hasattr(self.cdp, "get_rd_port"):
|
|
5135
|
+
self.get_rd_port = self.cdp.get_rd_port
|
|
5136
|
+
if hasattr(self.cdp, "get_rd_url"):
|
|
5137
|
+
self.get_rd_url = self.cdp.get_rd_url
|
|
5110
5138
|
if hasattr(self.cdp, "get_tabs"):
|
|
5111
5139
|
self.get_tabs = self.cdp.get_tabs
|
|
5140
|
+
if hasattr(self.cdp, "get_websocket_url"):
|
|
5141
|
+
self.get_websocket_url = self.cdp.get_websocket_url
|
|
5142
|
+
if hasattr(self.cdp, "grant_all_permissions"):
|
|
5143
|
+
self.grant_all_permissions = self.cdp.grant_all_permissions
|
|
5144
|
+
if hasattr(self.cdp, "grant_permissions"):
|
|
5145
|
+
self.grant_permissions = self.cdp.grant_permissions
|
|
5112
5146
|
if hasattr(self.cdp, "gui_click_and_hold"):
|
|
5113
5147
|
self.gui_click_and_hold = self.cdp.gui_click_and_hold
|
|
5114
5148
|
if hasattr(self.cdp, "gui_click_element"):
|
|
@@ -5119,6 +5153,26 @@ class BaseCase(unittest.TestCase):
|
|
|
5119
5153
|
self.gui_drag_drop_points = self.cdp.gui_drag_drop_points
|
|
5120
5154
|
if hasattr(self.cdp, "highlight_overlay"):
|
|
5121
5155
|
self.highlight_overlay = self.cdp.highlight_overlay
|
|
5156
|
+
if hasattr(self.cdp, "js_dumps"):
|
|
5157
|
+
self.js_dumps = self.cdp.js_dumps
|
|
5158
|
+
if hasattr(self.cdp, "js_scroll_into_view"):
|
|
5159
|
+
self.js_scroll_into_view = self.cdp.js_scroll_into_view
|
|
5160
|
+
if hasattr(self.cdp, "medimize"):
|
|
5161
|
+
self.medimize = self.cdp.medimize
|
|
5162
|
+
if hasattr(self.cdp, "mouse_click"):
|
|
5163
|
+
self.mouse_click = self.cdp.mouse_click
|
|
5164
|
+
if hasattr(self.cdp, "nested_click"):
|
|
5165
|
+
self.nested_click = self.cdp.nested_click
|
|
5166
|
+
if hasattr(self.cdp, "remove_from_dom"):
|
|
5167
|
+
self.remove_from_dom = self.cdp.remove_from_dom
|
|
5168
|
+
if hasattr(self.cdp, "reset_permissions"):
|
|
5169
|
+
self.reset_permissions = self.cdp.reset_permissions
|
|
5170
|
+
if hasattr(self.cdp, "set_all_cookies"):
|
|
5171
|
+
self.set_all_cookies = self.cdp.set_all_cookies
|
|
5172
|
+
if hasattr(self.cdp, "tile_windows"):
|
|
5173
|
+
self.tile_windows = self.cdp.tile_windows
|
|
5174
|
+
if hasattr(self.cdp, "get_window"):
|
|
5175
|
+
self.get_window = self.cdp.get_window
|
|
5122
5176
|
if getattr(self.driver, "_is_using_auth", None):
|
|
5123
5177
|
with suppress(Exception):
|
|
5124
5178
|
self.cdp.loop.run_until_complete(self.cdp.page.wait(0.25))
|
|
@@ -380,6 +380,7 @@ class Browser:
|
|
|
380
380
|
filter(lambda item: item.type_ == "page", self.targets)
|
|
381
381
|
)
|
|
382
382
|
await connection.sleep(0.005)
|
|
383
|
+
_cdp_downloads_path = None
|
|
383
384
|
_cdp_timezone = None
|
|
384
385
|
_cdp_user_agent = ""
|
|
385
386
|
_cdp_locale = None
|
|
@@ -389,6 +390,8 @@ class Browser:
|
|
|
389
390
|
_cdp_mobile_mode = None
|
|
390
391
|
_cdp_recorder = None
|
|
391
392
|
_cdp_ad_block = None
|
|
393
|
+
if getattr(sb_config, "_cdp_downloads_path", None):
|
|
394
|
+
_cdp_downloads_path = sb_config._cdp_downloads_path
|
|
392
395
|
if getattr(sb_config, "_cdp_timezone", None):
|
|
393
396
|
_cdp_timezone = sb_config._cdp_timezone
|
|
394
397
|
if getattr(sb_config, "_cdp_user_agent", None):
|
|
@@ -405,6 +408,8 @@ class Browser:
|
|
|
405
408
|
_cdp_ad_block = sb_config.ad_block_on
|
|
406
409
|
if getattr(sb_config, "disable_csp", None):
|
|
407
410
|
_cdp_disable_csp = sb_config.disable_csp
|
|
411
|
+
if "downloads_path" in kwargs:
|
|
412
|
+
_cdp_downloads_path = kwargs["downloads_path"]
|
|
408
413
|
if "timezone" in kwargs:
|
|
409
414
|
_cdp_timezone = kwargs["timezone"]
|
|
410
415
|
elif "tzone" in kwargs:
|
|
@@ -439,6 +444,7 @@ class Browser:
|
|
|
439
444
|
await connection.sleep(0.01)
|
|
440
445
|
await connection.send(cdp.network.enable())
|
|
441
446
|
await connection.sleep(0.01)
|
|
447
|
+
await connection.set_downloads_folder(_cdp_downloads_path)
|
|
442
448
|
if _cdp_timezone:
|
|
443
449
|
await connection.set_timezone(_cdp_timezone)
|
|
444
450
|
if _cdp_locale:
|
|
@@ -744,6 +744,8 @@ async def start(
|
|
|
744
744
|
sb_config._cdp_user_agent = kwargs["user_agent"]
|
|
745
745
|
else:
|
|
746
746
|
sb_config._cdp_user_agent = None
|
|
747
|
+
if "downloads_path" in kwargs:
|
|
748
|
+
sb_config._cdp_downloads_path = kwargs["downloads_path"]
|
|
747
749
|
if "platform" in kwargs:
|
|
748
750
|
sb_config._cdp_platform = kwargs["platform"]
|
|
749
751
|
elif "plat" in kwargs:
|
{seleniumbase-4.49.8 → seleniumbase-4.49.10}/seleniumbase/undetected/cdp_driver/connection.py
RENAMED
|
@@ -5,6 +5,7 @@ import inspect
|
|
|
5
5
|
import itertools
|
|
6
6
|
import json
|
|
7
7
|
import logging
|
|
8
|
+
import os
|
|
8
9
|
import sys
|
|
9
10
|
import types
|
|
10
11
|
import warnings
|
|
@@ -19,6 +20,7 @@ from typing import (
|
|
|
19
20
|
)
|
|
20
21
|
import websockets
|
|
21
22
|
from websockets.protocol import State
|
|
23
|
+
from seleniumbase.fixtures import constants
|
|
22
24
|
from . import cdp_util as util
|
|
23
25
|
import mycdp as cdp
|
|
24
26
|
import mycdp.network
|
|
@@ -335,6 +337,17 @@ class Connection(metaclass=CantTouchThis):
|
|
|
335
337
|
# No listener created yet.
|
|
336
338
|
pass
|
|
337
339
|
|
|
340
|
+
async def set_downloads_folder(self, downloads_path):
|
|
341
|
+
if not downloads_path:
|
|
342
|
+
downloads_dir = constants.Files.DOWNLOADS_FOLDER
|
|
343
|
+
abs_path = os.path.abspath(".")
|
|
344
|
+
downloads_path = os.path.join(abs_path, downloads_dir)
|
|
345
|
+
await self.send(
|
|
346
|
+
cdp.browser.set_download_behavior(
|
|
347
|
+
behavior="allow", download_path=str(downloads_path)
|
|
348
|
+
)
|
|
349
|
+
)
|
|
350
|
+
|
|
338
351
|
async def set_locale(self, locale: Optional[str] = None):
|
|
339
352
|
"""Sets the Language Locale code via set_user_agent_override."""
|
|
340
353
|
await self.set_user_agent(user_agent="", accept_language=locale)
|
|
@@ -373,7 +373,9 @@ class Element:
|
|
|
373
373
|
object_id=self._remote_object.object_id
|
|
374
374
|
)]
|
|
375
375
|
script = 'sessionStorage.getItem("pxsid") !== null;'
|
|
376
|
-
using_px =
|
|
376
|
+
using_px = True
|
|
377
|
+
with suppress(Exception):
|
|
378
|
+
using_px = await self.tab.evaluate(script)
|
|
377
379
|
if not using_px:
|
|
378
380
|
await self.flash_async(0.25)
|
|
379
381
|
await self._tab.send(
|
|
@@ -505,7 +507,9 @@ class Element:
|
|
|
505
507
|
return
|
|
506
508
|
logger.debug("Clicking on location: %.2f, %.2f" % center)
|
|
507
509
|
script = 'sessionStorage.getItem("pxsid") !== null;'
|
|
508
|
-
using_px =
|
|
510
|
+
using_px = True
|
|
511
|
+
with suppress(Exception):
|
|
512
|
+
using_px = await self.tab.evaluate(script)
|
|
509
513
|
if not using_px:
|
|
510
514
|
asyncio.create_task(self.flash_async(0.25))
|
|
511
515
|
asyncio.create_task(
|
|
@@ -567,7 +571,9 @@ class Element:
|
|
|
567
571
|
else:
|
|
568
572
|
logger.debug("Clicking on location: %.2f, %.2f" % (x_pos, y_pos))
|
|
569
573
|
script = 'sessionStorage.getItem("pxsid") !== null;'
|
|
570
|
-
using_px =
|
|
574
|
+
using_px = True
|
|
575
|
+
with suppress(Exception):
|
|
576
|
+
using_px = await self.tab.evaluate(script)
|
|
571
577
|
if not using_px:
|
|
572
578
|
asyncio.create_task(
|
|
573
579
|
self.flash_async(
|