seleniumbase 4.41.3__py3-none-any.whl → 4.45.10__py3-none-any.whl
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.
- sbase/steps.py +9 -0
- seleniumbase/__version__.py +1 -1
- seleniumbase/behave/behave_helper.py +2 -0
- seleniumbase/behave/behave_sb.py +21 -8
- seleniumbase/common/decorators.py +3 -1
- seleniumbase/console_scripts/run.py +1 -0
- seleniumbase/console_scripts/sb_caseplans.py +3 -4
- seleniumbase/console_scripts/sb_install.py +142 -11
- seleniumbase/console_scripts/sb_mkchart.py +1 -2
- seleniumbase/console_scripts/sb_mkdir.py +99 -29
- seleniumbase/console_scripts/sb_mkfile.py +1 -2
- seleniumbase/console_scripts/sb_mkpres.py +1 -2
- seleniumbase/console_scripts/sb_mkrec.py +26 -2
- seleniumbase/console_scripts/sb_objectify.py +4 -5
- seleniumbase/console_scripts/sb_print.py +1 -1
- seleniumbase/console_scripts/sb_recorder.py +40 -3
- seleniumbase/core/browser_launcher.py +474 -151
- seleniumbase/core/detect_b_ver.py +258 -16
- seleniumbase/core/log_helper.py +15 -21
- seleniumbase/core/mysql.py +1 -1
- seleniumbase/core/recorder_helper.py +3 -0
- seleniumbase/core/report_helper.py +9 -12
- seleniumbase/core/sb_cdp.py +734 -215
- seleniumbase/core/sb_driver.py +46 -5
- seleniumbase/core/session_helper.py +2 -4
- seleniumbase/core/tour_helper.py +1 -2
- seleniumbase/drivers/atlas_drivers/__init__.py +0 -0
- seleniumbase/drivers/brave_drivers/__init__.py +0 -0
- seleniumbase/drivers/chromium_drivers/__init__.py +0 -0
- seleniumbase/drivers/comet_drivers/__init__.py +0 -0
- seleniumbase/drivers/opera_drivers/__init__.py +0 -0
- seleniumbase/fixtures/base_case.py +448 -251
- seleniumbase/fixtures/constants.py +36 -9
- seleniumbase/fixtures/js_utils.py +77 -18
- seleniumbase/fixtures/page_actions.py +41 -13
- seleniumbase/fixtures/page_utils.py +19 -12
- seleniumbase/fixtures/shared_utils.py +64 -6
- seleniumbase/masterqa/master_qa.py +16 -2
- seleniumbase/plugins/base_plugin.py +8 -0
- seleniumbase/plugins/basic_test_info.py +2 -3
- seleniumbase/plugins/driver_manager.py +131 -5
- seleniumbase/plugins/page_source.py +2 -3
- seleniumbase/plugins/pytest_plugin.py +244 -79
- seleniumbase/plugins/sb_manager.py +143 -20
- seleniumbase/plugins/selenium_plugin.py +144 -12
- seleniumbase/translate/translator.py +2 -3
- seleniumbase/undetected/__init__.py +17 -13
- seleniumbase/undetected/cdp.py +1 -12
- seleniumbase/undetected/cdp_driver/browser.py +330 -129
- seleniumbase/undetected/cdp_driver/cdp_util.py +328 -61
- seleniumbase/undetected/cdp_driver/config.py +110 -14
- seleniumbase/undetected/cdp_driver/connection.py +18 -48
- seleniumbase/undetected/cdp_driver/element.py +105 -33
- seleniumbase/undetected/cdp_driver/tab.py +414 -39
- seleniumbase/utilities/selenium_grid/download_selenium_server.py +1 -1
- seleniumbase/utilities/selenium_grid/grid_hub.py +1 -2
- seleniumbase/utilities/selenium_grid/grid_node.py +2 -3
- seleniumbase/utilities/selenium_ide/convert_ide.py +2 -3
- {seleniumbase-4.41.3.dist-info → seleniumbase-4.45.10.dist-info}/METADATA +193 -166
- {seleniumbase-4.41.3.dist-info → seleniumbase-4.45.10.dist-info}/RECORD +64 -59
- {seleniumbase-4.41.3.dist-info → seleniumbase-4.45.10.dist-info}/licenses/LICENSE +1 -1
- {seleniumbase-4.41.3.dist-info → seleniumbase-4.45.10.dist-info}/WHEEL +0 -0
- {seleniumbase-4.41.3.dist-info → seleniumbase-4.45.10.dist-info}/entry_points.txt +0 -0
- {seleniumbase-4.41.3.dist-info → seleniumbase-4.45.10.dist-info}/top_level.txt +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: seleniumbase
|
|
3
|
-
Version: 4.
|
|
3
|
+
Version: 4.45.10
|
|
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
|
|
@@ -28,13 +28,11 @@ Classifier: Environment :: Web Environment
|
|
|
28
28
|
Classifier: Framework :: Pytest
|
|
29
29
|
Classifier: Intended Audience :: Developers
|
|
30
30
|
Classifier: Intended Audience :: Information Technology
|
|
31
|
-
Classifier: License :: OSI Approved :: MIT License
|
|
32
31
|
Classifier: Operating System :: MacOS :: MacOS X
|
|
33
32
|
Classifier: Operating System :: Microsoft :: Windows
|
|
34
33
|
Classifier: Operating System :: POSIX :: Linux
|
|
35
34
|
Classifier: Programming Language :: Python
|
|
36
35
|
Classifier: Programming Language :: Python :: 3
|
|
37
|
-
Classifier: Programming Language :: Python :: 3.8
|
|
38
36
|
Classifier: Programming Language :: Python :: 3.9
|
|
39
37
|
Classifier: Programming Language :: Python :: 3.10
|
|
40
38
|
Classifier: Programming Language :: Python :: 3.11
|
|
@@ -57,132 +55,124 @@ Classifier: Topic :: Software Development :: Testing
|
|
|
57
55
|
Classifier: Topic :: Software Development :: Testing :: Acceptance
|
|
58
56
|
Classifier: Topic :: Software Development :: Testing :: Traffic Generation
|
|
59
57
|
Classifier: Topic :: Utilities
|
|
60
|
-
Requires-Python: >=3.
|
|
58
|
+
Requires-Python: >=3.9
|
|
61
59
|
Description-Content-Type: text/markdown
|
|
62
60
|
License-File: LICENSE
|
|
63
|
-
Requires-Dist: pip>=25.
|
|
64
|
-
Requires-Dist: pip>=25.2; python_version >= "3.9"
|
|
61
|
+
Requires-Dist: pip>=25.3
|
|
65
62
|
Requires-Dist: packaging>=25.0
|
|
66
63
|
Requires-Dist: setuptools~=70.2; python_version < "3.10"
|
|
67
64
|
Requires-Dist: setuptools>=80.9.0; python_version >= "3.10"
|
|
68
65
|
Requires-Dist: wheel>=0.45.1
|
|
69
|
-
Requires-Dist: attrs>=25.
|
|
70
|
-
Requires-Dist: certifi>=
|
|
71
|
-
Requires-Dist: exceptiongroup>=1.3.
|
|
72
|
-
Requires-Dist: websockets
|
|
73
|
-
Requires-Dist:
|
|
74
|
-
Requires-Dist: filelock
|
|
75
|
-
Requires-Dist: filelock>=3.19.1; python_version >= "3.9"
|
|
66
|
+
Requires-Dist: attrs>=25.4.0
|
|
67
|
+
Requires-Dist: certifi>=2026.1.4
|
|
68
|
+
Requires-Dist: exceptiongroup>=1.3.1
|
|
69
|
+
Requires-Dist: websockets>=15.0.1
|
|
70
|
+
Requires-Dist: filelock~=3.19.1; python_version < "3.10"
|
|
71
|
+
Requires-Dist: filelock>=3.20.2; python_version >= "3.10"
|
|
76
72
|
Requires-Dist: fasteners>=0.20
|
|
77
|
-
Requires-Dist: mycdp>=1.2
|
|
78
|
-
Requires-Dist: pynose>=1.5.
|
|
79
|
-
Requires-Dist: platformdirs
|
|
80
|
-
Requires-Dist: platformdirs>=4.
|
|
81
|
-
Requires-Dist: typing-extensions>=4.
|
|
73
|
+
Requires-Dist: mycdp>=1.3.2
|
|
74
|
+
Requires-Dist: pynose>=1.5.5
|
|
75
|
+
Requires-Dist: platformdirs~=4.4.0; python_version < "3.10"
|
|
76
|
+
Requires-Dist: platformdirs>=4.5.1; python_version >= "3.10"
|
|
77
|
+
Requires-Dist: typing-extensions>=4.15.0
|
|
82
78
|
Requires-Dist: sbvirtualdisplay>=1.4.0
|
|
83
|
-
Requires-Dist: MarkupSafe
|
|
84
|
-
Requires-Dist: MarkupSafe>=3.0.2; python_version >= "3.9"
|
|
79
|
+
Requires-Dist: MarkupSafe>=3.0.3
|
|
85
80
|
Requires-Dist: Jinja2>=3.1.6
|
|
86
81
|
Requires-Dist: six>=1.17.0
|
|
87
82
|
Requires-Dist: parse>=1.20.2
|
|
88
83
|
Requires-Dist: parse-type>=0.6.6
|
|
89
84
|
Requires-Dist: colorama>=0.4.6
|
|
90
|
-
Requires-Dist: pyyaml>=6.0.
|
|
85
|
+
Requires-Dist: pyyaml>=6.0.3
|
|
91
86
|
Requires-Dist: pygments>=2.19.2
|
|
92
|
-
Requires-Dist: pyreadline3>=3.5.
|
|
87
|
+
Requires-Dist: pyreadline3>=3.5.4; platform_system == "Windows"
|
|
93
88
|
Requires-Dist: tabcompleter>=1.4.0
|
|
94
|
-
Requires-Dist: pdbp>=1.
|
|
95
|
-
Requires-Dist: idna
|
|
89
|
+
Requires-Dist: pdbp>=1.8.1
|
|
90
|
+
Requires-Dist: idna>=3.11
|
|
96
91
|
Requires-Dist: chardet==5.2.0
|
|
97
|
-
Requires-Dist: charset-normalizer<4,>=3.4.
|
|
92
|
+
Requires-Dist: charset-normalizer<4,>=3.4.4
|
|
98
93
|
Requires-Dist: urllib3<2,>=1.26.20; python_version < "3.10"
|
|
99
|
-
Requires-Dist: urllib3<
|
|
100
|
-
Requires-Dist: requests
|
|
101
|
-
Requires-Dist: requests<2.33,>=2.32.5; python_version >= "3.9"
|
|
94
|
+
Requires-Dist: urllib3<3,>=1.26.20; python_version >= "3.10"
|
|
95
|
+
Requires-Dist: requests~=2.32.5
|
|
102
96
|
Requires-Dist: sniffio==1.3.1
|
|
103
97
|
Requires-Dist: h11==0.16.0
|
|
104
98
|
Requires-Dist: outcome==1.3.0.post0
|
|
105
|
-
Requires-Dist: trio
|
|
106
|
-
Requires-Dist: trio
|
|
107
|
-
Requires-Dist: trio-websocket
|
|
108
|
-
Requires-Dist: wsproto==1.2.0
|
|
109
|
-
Requires-Dist:
|
|
110
|
-
Requires-Dist:
|
|
111
|
-
Requires-Dist: selenium==4.32.0; python_version
|
|
112
|
-
Requires-Dist: selenium==4.
|
|
113
|
-
Requires-Dist: cssselect==1.
|
|
114
|
-
Requires-Dist:
|
|
99
|
+
Requires-Dist: trio<1,>=0.31.0; python_version < "3.10"
|
|
100
|
+
Requires-Dist: trio<1,>=0.32.0; python_version >= "3.10"
|
|
101
|
+
Requires-Dist: trio-websocket~=0.12.2
|
|
102
|
+
Requires-Dist: wsproto==1.2.0; python_version < "3.10"
|
|
103
|
+
Requires-Dist: wsproto~=1.3.2; python_version >= "3.10"
|
|
104
|
+
Requires-Dist: websocket-client~=1.9.0
|
|
105
|
+
Requires-Dist: selenium==4.32.0; python_version < "3.10"
|
|
106
|
+
Requires-Dist: selenium==4.39.0; python_version >= "3.10"
|
|
107
|
+
Requires-Dist: cssselect==1.3.0
|
|
108
|
+
Requires-Dist: nest-asyncio==1.6.0
|
|
115
109
|
Requires-Dist: sortedcontainers==2.4.0
|
|
116
|
-
Requires-Dist: execnet==2.1.1
|
|
117
|
-
Requires-Dist:
|
|
118
|
-
Requires-Dist:
|
|
119
|
-
Requires-Dist:
|
|
120
|
-
Requires-Dist:
|
|
121
|
-
Requires-Dist: pytest==8.4.
|
|
110
|
+
Requires-Dist: execnet==2.1.1; python_version < "3.10"
|
|
111
|
+
Requires-Dist: execnet==2.1.2; python_version >= "3.10"
|
|
112
|
+
Requires-Dist: iniconfig==2.1.0; python_version < "3.10"
|
|
113
|
+
Requires-Dist: iniconfig==2.3.0; python_version >= "3.10"
|
|
114
|
+
Requires-Dist: pluggy==1.6.0
|
|
115
|
+
Requires-Dist: pytest==8.4.2; python_version < "3.11"
|
|
116
|
+
Requires-Dist: pytest==9.0.2; python_version >= "3.11"
|
|
122
117
|
Requires-Dist: pytest-html==4.0.2
|
|
123
118
|
Requires-Dist: pytest-metadata==3.1.1
|
|
124
119
|
Requires-Dist: pytest-ordering==0.6
|
|
125
|
-
Requires-Dist: pytest-rerunfailures==
|
|
126
|
-
Requires-Dist: pytest-rerunfailures==
|
|
127
|
-
Requires-Dist: pytest-xdist==3.
|
|
128
|
-
Requires-Dist: pytest-xdist==3.8.0; python_version >= "3.9"
|
|
120
|
+
Requires-Dist: pytest-rerunfailures==16.0.1; python_version < "3.10"
|
|
121
|
+
Requires-Dist: pytest-rerunfailures==16.1; python_version >= "3.10"
|
|
122
|
+
Requires-Dist: pytest-xdist==3.8.0
|
|
129
123
|
Requires-Dist: parameterized==0.9.0
|
|
130
124
|
Requires-Dist: behave==1.2.6
|
|
131
|
-
Requires-Dist: soupsieve
|
|
132
|
-
Requires-Dist:
|
|
133
|
-
Requires-Dist: beautifulsoup4~=4.13.5
|
|
125
|
+
Requires-Dist: soupsieve~=2.8.1
|
|
126
|
+
Requires-Dist: beautifulsoup4~=4.14.3
|
|
134
127
|
Requires-Dist: pyotp==2.9.0
|
|
135
128
|
Requires-Dist: python-xlib==0.33; platform_system == "Linux"
|
|
129
|
+
Requires-Dist: PyAutoGUI>=0.9.54; platform_system == "Linux"
|
|
136
130
|
Requires-Dist: markdown-it-py==3.0.0; python_version < "3.10"
|
|
137
131
|
Requires-Dist: markdown-it-py==4.0.0; python_version >= "3.10"
|
|
138
132
|
Requires-Dist: mdurl==0.1.2
|
|
139
|
-
Requires-Dist: rich<15,>=14.
|
|
133
|
+
Requires-Dist: rich<15,>=14.2.0
|
|
140
134
|
Provides-Extra: allure
|
|
141
135
|
Requires-Dist: allure-pytest>=2.13.5; extra == "allure"
|
|
142
136
|
Requires-Dist: allure-python-commons>=2.13.5; extra == "allure"
|
|
143
137
|
Requires-Dist: allure-behave>=2.13.5; extra == "allure"
|
|
144
138
|
Provides-Extra: coverage
|
|
145
|
-
Requires-Dist: coverage>=7.
|
|
146
|
-
Requires-Dist: coverage>=7.
|
|
147
|
-
Requires-Dist: pytest-cov>=
|
|
148
|
-
Requires-Dist: pytest-cov>=6.2.1; python_version >= "3.9" and extra == "coverage"
|
|
139
|
+
Requires-Dist: coverage>=7.10.7; python_version < "3.10" and extra == "coverage"
|
|
140
|
+
Requires-Dist: coverage>=7.13.1; python_version >= "3.10" and extra == "coverage"
|
|
141
|
+
Requires-Dist: pytest-cov>=7.0.0; extra == "coverage"
|
|
149
142
|
Provides-Extra: flake8
|
|
150
|
-
Requires-Dist: flake8==
|
|
151
|
-
Requires-Dist: flake8==7.3.0; python_version >= "3.9" and extra == "flake8"
|
|
143
|
+
Requires-Dist: flake8==7.3.0; extra == "flake8"
|
|
152
144
|
Requires-Dist: mccabe==0.7.0; extra == "flake8"
|
|
153
|
-
Requires-Dist: pyflakes==
|
|
154
|
-
Requires-Dist:
|
|
155
|
-
Requires-Dist: pycodestyle==2.9.1; python_version < "3.9" and extra == "flake8"
|
|
156
|
-
Requires-Dist: pycodestyle==2.14.0; python_version >= "3.9" and extra == "flake8"
|
|
145
|
+
Requires-Dist: pyflakes==3.4.0; extra == "flake8"
|
|
146
|
+
Requires-Dist: pycodestyle==2.14.0; extra == "flake8"
|
|
157
147
|
Provides-Extra: ipdb
|
|
158
148
|
Requires-Dist: ipdb==0.13.13; extra == "ipdb"
|
|
159
149
|
Requires-Dist: ipython==7.34.0; extra == "ipdb"
|
|
160
150
|
Provides-Extra: mss
|
|
161
|
-
Requires-Dist: mss==
|
|
162
|
-
Requires-Dist: mss==10.0.0; python_version >= "3.9" and extra == "mss"
|
|
151
|
+
Requires-Dist: mss==10.1.0; extra == "mss"
|
|
163
152
|
Provides-Extra: pdfminer
|
|
164
|
-
Requires-Dist: pdfminer.six==
|
|
165
|
-
Requires-Dist: pdfminer.six==
|
|
166
|
-
Requires-Dist: cryptography==
|
|
167
|
-
Requires-Dist:
|
|
168
|
-
Requires-Dist:
|
|
169
|
-
Requires-Dist: pycparser==2.22; extra == "pdfminer"
|
|
153
|
+
Requires-Dist: pdfminer.six==20251107; python_version < "3.10" and extra == "pdfminer"
|
|
154
|
+
Requires-Dist: pdfminer.six==20260107; python_version >= "3.10" and extra == "pdfminer"
|
|
155
|
+
Requires-Dist: cryptography==46.0.3; extra == "pdfminer"
|
|
156
|
+
Requires-Dist: cffi==2.0.0; extra == "pdfminer"
|
|
157
|
+
Requires-Dist: pycparser==2.23; extra == "pdfminer"
|
|
170
158
|
Provides-Extra: pillow
|
|
171
|
-
Requires-Dist: Pillow>=
|
|
172
|
-
Requires-Dist: Pillow>=
|
|
159
|
+
Requires-Dist: Pillow>=11.3.0; python_version < "3.10" and extra == "pillow"
|
|
160
|
+
Requires-Dist: Pillow>=12.1.0; python_version >= "3.10" and extra == "pillow"
|
|
173
161
|
Provides-Extra: pip-system-certs
|
|
174
162
|
Requires-Dist: pip-system-certs==4.0; platform_system == "Windows" and extra == "pip-system-certs"
|
|
175
163
|
Provides-Extra: proxy
|
|
176
164
|
Requires-Dist: proxy.py==2.4.3; extra == "proxy"
|
|
165
|
+
Provides-Extra: playwright
|
|
166
|
+
Requires-Dist: playwright>=1.56.0; extra == "playwright"
|
|
177
167
|
Provides-Extra: psutil
|
|
178
|
-
Requires-Dist: psutil
|
|
168
|
+
Requires-Dist: psutil>=7.1.3; extra == "psutil"
|
|
179
169
|
Provides-Extra: pyautogui
|
|
180
|
-
Requires-Dist: PyAutoGUI
|
|
170
|
+
Requires-Dist: PyAutoGUI>=0.9.54; platform_system != "Linux" and extra == "pyautogui"
|
|
181
171
|
Provides-Extra: selenium-stealth
|
|
182
172
|
Requires-Dist: selenium-stealth==1.0.6; extra == "selenium-stealth"
|
|
183
173
|
Provides-Extra: selenium-wire
|
|
184
174
|
Requires-Dist: selenium-wire==5.1.0; extra == "selenium-wire"
|
|
185
|
-
Requires-Dist: pyOpenSSL
|
|
175
|
+
Requires-Dist: pyOpenSSL>=24.2.1; extra == "selenium-wire"
|
|
186
176
|
Requires-Dist: pyparsing>=3.1.4; extra == "selenium-wire"
|
|
187
177
|
Requires-Dist: Brotli==1.1.0; extra == "selenium-wire"
|
|
188
178
|
Requires-Dist: blinker==1.7.0; extra == "selenium-wire"
|
|
@@ -191,7 +181,7 @@ Requires-Dist: hpack==4.0.0; extra == "selenium-wire"
|
|
|
191
181
|
Requires-Dist: hyperframe==6.0.1; extra == "selenium-wire"
|
|
192
182
|
Requires-Dist: kaitaistruct==0.10; extra == "selenium-wire"
|
|
193
183
|
Requires-Dist: pyasn1==0.6.1; extra == "selenium-wire"
|
|
194
|
-
Requires-Dist: zstandard
|
|
184
|
+
Requires-Dist: zstandard>=0.23.0; extra == "selenium-wire"
|
|
195
185
|
Dynamic: author
|
|
196
186
|
Dynamic: author-email
|
|
197
187
|
Dynamic: classifier
|
|
@@ -219,80 +209,86 @@ Dynamic: summary
|
|
|
219
209
|
|
|
220
210
|
<p align="center"><a href="https://github.com/seleniumbase/SeleniumBase/"><img src="https://seleniumbase.github.io/cdn/img/super_logo_sb3.png" alt="SeleniumBase" title="SeleniumBase" width="350" /></a></p>
|
|
221
211
|
|
|
222
|
-
<p align="center" class="hero__title"><b>
|
|
212
|
+
<p align="center" class="hero__title"><b>Automate, test, and scrape the web — on your own terms.<br /></b></p>
|
|
223
213
|
|
|
224
|
-
<p align="center"><a href="https://pypi.python.org/pypi/seleniumbase" target="_blank"><img src="https://img.shields.io/pypi/v/seleniumbase.svg?color=3399EE" alt="PyPI version" /></a> <a href="https://github.com/seleniumbase/SeleniumBase/releases" target="_blank"><img src="https://img.shields.io/github/v/release/seleniumbase/SeleniumBase.svg?color=22AAEE" alt="GitHub version" /></a> <a href="https://seleniumbase.io"><img src="https://img.shields.io/badge/docs-seleniumbase.io-11BBAA.svg" alt="SeleniumBase Docs" /></a
|
|
214
|
+
<p align="center"><a href="https://pypi.python.org/pypi/seleniumbase" target="_blank"><img src="https://img.shields.io/pypi/v/seleniumbase.svg?color=3399EE" alt="PyPI version" /></a> <a href="https://github.com/seleniumbase/SeleniumBase/releases" target="_blank"><img src="https://img.shields.io/github/v/release/seleniumbase/SeleniumBase.svg?color=22AAEE" alt="GitHub version" /></a> <a href="https://seleniumbase.io"><img src="https://img.shields.io/badge/docs-seleniumbase.io-11BBAA.svg" alt="SeleniumBase Docs" /></a></p>
|
|
215
|
+
<p align="center"><a href="https://github.com/seleniumbase/SeleniumBase/actions" target="_blank"><img src="https://github.com/seleniumbase/SeleniumBase/workflows/CI%20build/badge.svg" alt="SeleniumBase GitHub Actions" /></a> <a href="https://github.com/seleniumbase/SeleniumBase/stargazers"><img src="https://img.shields.io/github/stars/seleniumbase/SeleniumBase?style=social"></a> <a href="https://pepy.tech/projects/seleniumbase?timeRange=threeMonths&category=version&includeCIDownloads=true&granularity=daily&viewType=line&versions=*" target="_blank"><img src="https://static.pepy.tech/badge/seleniumbase" alt="SeleniumBase PyPI downloads" /></a> <a href="https://discord.gg/EdhQTn3EyE" target="_blank"><img src="https://img.shields.io/discord/727927627830001734?color=7289DA&label=Discord&logo=discord&logoColor=white"/></a></p>
|
|
225
216
|
|
|
226
217
|
<p align="center">
|
|
227
218
|
<a href="#python_installation">🚀 Start</a> |
|
|
228
219
|
<a href="https://github.com/seleniumbase/SeleniumBase/blob/master/help_docs/features_list.md">🏰 Features</a> |
|
|
229
220
|
<a href="https://github.com/seleniumbase/SeleniumBase/blob/master/help_docs/customizing_test_runs.md">🎛️ Options</a> |
|
|
230
221
|
<a href="https://github.com/seleniumbase/SeleniumBase/blob/master/examples/ReadMe.md">📚 Examples</a> |
|
|
231
|
-
<a href="https://github.com/seleniumbase/SeleniumBase/blob/master/seleniumbase/console_scripts/ReadMe.md"
|
|
222
|
+
<a href="https://github.com/seleniumbase/SeleniumBase/blob/master/seleniumbase/console_scripts/ReadMe.md">🪄 Scripts</a> |
|
|
232
223
|
<a href="https://github.com/seleniumbase/SeleniumBase/blob/master/help_docs/mobile_testing.md">📱 Mobile</a>
|
|
233
224
|
<br />
|
|
234
|
-
<a href="https://github.com/seleniumbase/SeleniumBase/blob/master/help_docs/method_summary.md">📘
|
|
235
|
-
<a href="https://github.com/seleniumbase/SeleniumBase/blob/master/help_docs/syntax_formats.md"> 🔠
|
|
225
|
+
<a href="https://github.com/seleniumbase/SeleniumBase/blob/master/help_docs/method_summary.md">📘 The API</a> |
|
|
226
|
+
<a href="https://github.com/seleniumbase/SeleniumBase/blob/master/help_docs/syntax_formats.md"> 🔠 SyntaxFormats</a> |
|
|
236
227
|
<a href="https://github.com/seleniumbase/SeleniumBase/blob/master/help_docs/recorder_mode.md">🔴 Recorder</a> |
|
|
237
228
|
<a href="https://github.com/seleniumbase/SeleniumBase/blob/master/examples/example_logs/ReadMe.md">📊 Dashboard</a> |
|
|
238
|
-
<a href="https://github.com/seleniumbase/SeleniumBase/blob/master/help_docs/locale_codes.md">🗾
|
|
239
|
-
<a href="https://seleniumbase.io/devices/?url=seleniumbase.com">💻 Farm</a>
|
|
229
|
+
<a href="https://github.com/seleniumbase/SeleniumBase/blob/master/help_docs/locale_codes.md">🗾 Locale</a>
|
|
240
230
|
<br />
|
|
241
231
|
<a href="https://github.com/seleniumbase/SeleniumBase/blob/master/help_docs/commander.md">🎖️ GUI</a> |
|
|
242
232
|
<a href="https://seleniumbase.io/demo_page">📰 TestPage</a> |
|
|
243
233
|
<a href="https://github.com/seleniumbase/SeleniumBase/blob/master/help_docs/uc_mode.md">👤 UC Mode</a> |
|
|
244
234
|
<a href="https://github.com/seleniumbase/SeleniumBase/blob/master/examples/cdp_mode/ReadMe.md">🐙 CDP Mode</a> |
|
|
245
|
-
<a href="https://github.com/seleniumbase/SeleniumBase/blob/master/examples/chart_maker/ReadMe.md">📶 Charts</a>
|
|
246
|
-
<a href="https://
|
|
235
|
+
<a href="https://github.com/seleniumbase/SeleniumBase/blob/master/examples/chart_maker/ReadMe.md">📶 Charts</a> |
|
|
236
|
+
<a href="https://seleniumbase.io/devices/?url=seleniumbase.com">🖥️ Farm</a>
|
|
247
237
|
<br />
|
|
248
238
|
<a href="https://github.com/seleniumbase/SeleniumBase/blob/master/help_docs/how_it_works.md">👁️ How</a> |
|
|
249
|
-
<a href="https://github.com/seleniumbase/SeleniumBase/tree/master/examples/migration/raw_selenium">🚝
|
|
250
|
-
<a href="https://github.com/seleniumbase/SeleniumBase/blob/master/
|
|
251
|
-
<a href="https://github.com/seleniumbase/SeleniumBase/
|
|
252
|
-
<a href="https://github.com/seleniumbase/SeleniumBase/blob/master/examples/master_qa/ReadMe.md">🧬 Hybrid</a> |
|
|
239
|
+
<a href="https://github.com/seleniumbase/SeleniumBase/tree/master/examples/migration/raw_selenium">🚝 Migration</a> |
|
|
240
|
+
<a href="https://github.com/seleniumbase/SeleniumBase/blob/master/examples/cdp_mode/playwright/ReadMe.md">🎭 Stealthy Playwright</a> |
|
|
241
|
+
<a href="https://github.com/seleniumbase/SeleniumBase/blob/master/examples/master_qa/ReadMe.md">🛂 MasterQA</a> |
|
|
253
242
|
<a href="https://github.com/seleniumbase/SeleniumBase/blob/master/examples/tour_examples/ReadMe.md">🚎 Tours</a>
|
|
254
243
|
<br />
|
|
255
244
|
<a href="https://github.com/seleniumbase/SeleniumBase/blob/master/integrations/github/workflows/ReadMe.md">🤖 CI/CD</a> |
|
|
256
|
-
<a href="https://github.com/seleniumbase/SeleniumBase/blob/master/help_docs/js_package_manager.md"
|
|
245
|
+
<a href="https://github.com/seleniumbase/SeleniumBase/blob/master/help_docs/js_package_manager.md">❇️ JSMgr</a> |
|
|
257
246
|
<a href="https://github.com/seleniumbase/SeleniumBase/blob/master/help_docs/translations.md">🌏 Translator</a> |
|
|
258
247
|
<a href="https://github.com/seleniumbase/SeleniumBase/blob/master/examples/presenter/ReadMe.md">🎞️ Presenter</a> |
|
|
259
|
-
<a href="https://github.com/seleniumbase/SeleniumBase/blob/master/examples/
|
|
260
|
-
<a href="https://github.com/seleniumbase/SeleniumBase/blob/master/
|
|
248
|
+
<a href="https://github.com/seleniumbase/SeleniumBase/blob/master/examples/visual_testing/ReadMe.md">🖼️ Visual</a> |
|
|
249
|
+
<a href="https://github.com/seleniumbase/SeleniumBase/blob/master/help_docs/case_plans.md">🗂️ CPlans</a>
|
|
261
250
|
<br />
|
|
262
251
|
</p>
|
|
263
252
|
|
|
264
|
-
<p>SeleniumBase is
|
|
253
|
+
<p>SeleniumBase is a browser automation framework that empowers software teams to innovate faster and handle modern web challenges with ease. With stealth options like CDP Mode, you'll avoid the usual restrictions imposed by websites deploying bot-detection services.</p>
|
|
265
254
|
|
|
266
255
|
--------
|
|
267
256
|
|
|
268
257
|
📚 Learn from [**over 200 examples** in the **SeleniumBase/examples/** folder](https://github.com/seleniumbase/SeleniumBase/tree/master/examples).
|
|
269
258
|
|
|
270
|
-
🐙
|
|
259
|
+
🐙 Stealth modes: <a translate="no" href="https://github.com/seleniumbase/SeleniumBase/blob/master/help_docs/uc_mode.md"><b>UC Mode</b></a> and <a translate="no" href="https://github.com/seleniumbase/SeleniumBase/blob/master/examples/cdp_mode/ReadMe.md"><b>CDP Mode</b></a> can bypass bot-detection, solve CAPTCHAs, and call advanced methods from the <a href="https://chromedevtools.github.io/devtools-protocol/" translate="no">Chrome Devtools Protocol</a>.
|
|
271
260
|
|
|
272
|
-
ℹ️
|
|
261
|
+
ℹ️ Many examples run with raw <code translate="no"><b>python</b></code>, although some use <a href="https://github.com/seleniumbase/SeleniumBase/blob/master/help_docs/syntax_formats.md">Syntax Formats</a> that expect <a href="https://docs.pytest.org/en/latest/how-to/usage.html" translate="no"><b>pytest</b></a> (a Python unit-testing framework included with SeleniumBase that can discover, collect, and run tests automatically).
|
|
273
262
|
|
|
274
263
|
--------
|
|
275
264
|
|
|
276
|
-
<p align="left">📗
|
|
265
|
+
<p align="left">📗 This script performs a Google Search using SeleniumBase UC Mode + CDP Mode:<br /><a href="https://github.com/seleniumbase/SeleniumBase/blob/master/examples/raw_google.py">SeleniumBase/examples/raw_google.py</a> (Results are saved as PDF, HTML, and PNG)</p>
|
|
277
266
|
|
|
278
267
|
```python
|
|
279
268
|
from seleniumbase import SB
|
|
280
269
|
|
|
281
|
-
with SB(
|
|
282
|
-
|
|
283
|
-
sb.
|
|
284
|
-
sb.
|
|
285
|
-
sb.
|
|
270
|
+
with SB(uc=True, test=True) as sb:
|
|
271
|
+
url = "https://google.com/ncr"
|
|
272
|
+
sb.activate_cdp_mode(url)
|
|
273
|
+
sb.type('[title="Search"]', "SeleniumBase GitHub page")
|
|
274
|
+
sb.click("div:not([jsname]) > * > input")
|
|
275
|
+
sb.sleep(2)
|
|
286
276
|
print(sb.get_page_title())
|
|
277
|
+
sb.sleep(1) # Wait for the "AI Overview" result
|
|
278
|
+
if sb.is_text_visible("Generating"):
|
|
279
|
+
sb.wait_for_text("AI Overview")
|
|
280
|
+
sb.save_as_pdf_to_logs() # Saved to ./latest_logs/
|
|
281
|
+
sb.save_page_source_to_logs()
|
|
282
|
+
sb.save_screenshot_to_logs()
|
|
287
283
|
```
|
|
288
284
|
|
|
289
285
|
> `python raw_google.py`
|
|
290
286
|
|
|
291
|
-
<a href="https://github.com/seleniumbase/SeleniumBase/blob/master/examples/raw_google.py"><img src="https://seleniumbase.github.io/cdn/
|
|
287
|
+
<a href="https://github.com/seleniumbase/SeleniumBase/blob/master/examples/raw_google.py"><img src="https://seleniumbase.github.io/cdn/img/google_sb_result.png" alt="SeleniumBase on Google" title="SeleniumBase on Google" width="480" /></a>
|
|
292
288
|
|
|
293
289
|
--------
|
|
294
290
|
|
|
295
|
-
<p align="left">📗 Here's
|
|
291
|
+
<p align="left">📗 Here's a script that bypasses Cloudflare's challenge page with UC Mode + CDP Mode: <a href="https://github.com/seleniumbase/SeleniumBase/blob/master/examples/cdp_mode/raw_gitlab.py">SeleniumBase/examples/cdp_mode/raw_gitlab.py</a></p>
|
|
296
292
|
|
|
297
293
|
```python
|
|
298
294
|
from seleniumbase import SB
|
|
@@ -300,16 +296,35 @@ from seleniumbase import SB
|
|
|
300
296
|
with SB(uc=True, test=True, locale="en") as sb:
|
|
301
297
|
url = "https://gitlab.com/users/sign_in"
|
|
302
298
|
sb.activate_cdp_mode(url)
|
|
303
|
-
sb.sleep(1)
|
|
304
|
-
sb.uc_gui_click_captcha()
|
|
305
299
|
sb.sleep(2)
|
|
300
|
+
sb.solve_captcha()
|
|
301
|
+
# (The rest is for testing and demo purposes)
|
|
302
|
+
sb.assert_text("Username", '[for="user_login"]', timeout=3)
|
|
303
|
+
sb.assert_element('label[for="user_login"]')
|
|
304
|
+
sb.highlight('button:contains("Sign in")')
|
|
305
|
+
sb.highlight('h1:contains("GitLab")')
|
|
306
|
+
sb.post_message("SeleniumBase wasn't detected", duration=4)
|
|
306
307
|
```
|
|
307
308
|
|
|
308
309
|
<img src="https://seleniumbase.github.io/other/cf_sec.jpg" title="SeleniumBase" width="332"> <img src="https://seleniumbase.github.io/other/gitlab_bypass.png" title="SeleniumBase" width="288">
|
|
309
310
|
|
|
311
|
+
<p align="left">📙 There's also SeleniumBase's "Pure CDP Mode", which doesn't use WebDriver or Selenium at all: <a href="https://github.com/seleniumbase/SeleniumBase/blob/master/examples/cdp_mode/raw_cdp_gitlab.py">SeleniumBase/examples/cdp_mode/raw_cdp_gitlab.py</a></p>
|
|
312
|
+
|
|
313
|
+
```python
|
|
314
|
+
from seleniumbase import sb_cdp
|
|
315
|
+
|
|
316
|
+
url = "https://gitlab.com/users/sign_in"
|
|
317
|
+
sb = sb_cdp.Chrome(url, incognito=True)
|
|
318
|
+
sb.sleep(2)
|
|
319
|
+
sb.solve_captcha()
|
|
320
|
+
sb.highlight('h1:contains("GitLab")')
|
|
321
|
+
sb.highlight('button:contains("Sign in")')
|
|
322
|
+
sb.driver.stop()
|
|
323
|
+
```
|
|
324
|
+
|
|
310
325
|
--------
|
|
311
326
|
|
|
312
|
-
<p align="left">📗 Here's <a href="https://github.com/seleniumbase/SeleniumBase/blob/master/examples/test_get_swag.py">test_get_swag.py</a>, which tests an e-commerce site:</p>
|
|
327
|
+
<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>
|
|
313
328
|
|
|
314
329
|
```python
|
|
315
330
|
from seleniumbase import BaseCase
|
|
@@ -337,11 +352,11 @@ class MyTestClass(BaseCase):
|
|
|
337
352
|
|
|
338
353
|
<a href="https://github.com/seleniumbase/SeleniumBase/blob/master/examples/test_get_swag.py"><img src="https://seleniumbase.github.io/cdn/gif/fast_swag_2.gif" alt="SeleniumBase Test" title="SeleniumBase Test" width="480" /></a>
|
|
339
354
|
|
|
340
|
-
> (The default browser is
|
|
355
|
+
> (The default browser is `--chrome` if not set.)
|
|
341
356
|
|
|
342
357
|
--------
|
|
343
358
|
|
|
344
|
-
<p align="left">📗 Here's <a href="https://github.com/seleniumbase/SeleniumBase/blob/master/examples/test_coffee_cart.py" target="_blank">test_coffee_cart.py</a>, which verifies an e-commerce site:</p>
|
|
359
|
+
<p align="left">📗 Here's <a href="https://github.com/seleniumbase/SeleniumBase/blob/master/examples/test_coffee_cart.py" target="_blank">SeleniumBase/examples/test_coffee_cart.py</a>, which verifies an e-commerce site:</p>
|
|
345
360
|
|
|
346
361
|
```zsh
|
|
347
362
|
pytest test_coffee_cart.py --demo
|
|
@@ -355,7 +370,7 @@ pytest test_coffee_cart.py --demo
|
|
|
355
370
|
|
|
356
371
|
<a id="multiple_examples"></a>
|
|
357
372
|
|
|
358
|
-
<p align="left">📗 Here's <a href="https://github.com/seleniumbase/SeleniumBase/blob/master/examples/test_demo_site.py" target="_blank">test_demo_site.py</a>, which covers several actions:</p>
|
|
373
|
+
<p align="left">📗 Here's <a href="https://github.com/seleniumbase/SeleniumBase/blob/master/examples/test_demo_site.py" target="_blank">SeleniumBase/examples/test_demo_site.py</a>, which covers several actions:</p>
|
|
359
374
|
|
|
360
375
|
```zsh
|
|
361
376
|
pytest test_demo_site.py
|
|
@@ -501,19 +516,18 @@ finally:
|
|
|
501
516
|
<a id="install_seleniumbase"></a>
|
|
502
517
|
<h2><img src="https://seleniumbase.github.io/img/logo7.png" title="SeleniumBase" width="32" /> Install SeleniumBase:</h2>
|
|
503
518
|
|
|
504
|
-
**You can install
|
|
519
|
+
**You can install `seleniumbase` from [PyPI](https://pypi.org/project/seleniumbase/) or [GitHub](https://github.com/seleniumbase/SeleniumBase):**
|
|
505
520
|
|
|
506
|
-
🔵 **How to install
|
|
521
|
+
🔵 **How to install `seleniumbase` from PyPI:**
|
|
507
522
|
|
|
508
523
|
```zsh
|
|
509
524
|
pip install seleniumbase
|
|
510
525
|
```
|
|
511
526
|
|
|
512
|
-
* (Add
|
|
513
|
-
* (Add
|
|
514
|
-
* (Use ``pip3`` if multiple versions of Python are present.)
|
|
527
|
+
* (Add `--upgrade` OR `-U` to upgrade SeleniumBase.)
|
|
528
|
+
* (Add `--force-reinstall` to upgrade indirect packages.)
|
|
515
529
|
|
|
516
|
-
🔵 **How to install
|
|
530
|
+
🔵 **How to install `seleniumbase` from a GitHub clone:**
|
|
517
531
|
|
|
518
532
|
```zsh
|
|
519
533
|
git clone https://github.com/seleniumbase/SeleniumBase.git
|
|
@@ -528,7 +542,7 @@ git pull
|
|
|
528
542
|
pip install -e .
|
|
529
543
|
```
|
|
530
544
|
|
|
531
|
-
🔵 **Type
|
|
545
|
+
🔵 **Type `seleniumbase` or `sbase` to verify that SeleniumBase was installed successfully:**
|
|
532
546
|
|
|
533
547
|
```zsh
|
|
534
548
|
___ _ _ ___
|
|
@@ -578,17 +592,17 @@ pip install -e .
|
|
|
578
592
|
|
|
579
593
|
<h3>🔵 Downloading webdrivers:</h3>
|
|
580
594
|
|
|
581
|
-
✅ SeleniumBase automatically downloads webdrivers as needed, such as
|
|
595
|
+
✅ SeleniumBase automatically downloads webdrivers as needed, such as `chromedriver`.
|
|
582
596
|
|
|
583
597
|
<div></div>
|
|
584
598
|
<details>
|
|
585
599
|
<summary> ▶️ Here's sample output from a chromedriver download. (<b>click to expand</b>)</summary>
|
|
586
600
|
|
|
587
601
|
```zsh
|
|
588
|
-
*** chromedriver to download =
|
|
602
|
+
*** chromedriver to download = 141.0.7390.78 (Latest Stable)
|
|
589
603
|
|
|
590
604
|
Downloading chromedriver-mac-arm64.zip from:
|
|
591
|
-
https://storage.googleapis.com/chrome-for-testing-public/
|
|
605
|
+
https://storage.googleapis.com/chrome-for-testing-public/141.0.7390.78/mac-arm64/chromedriver-mac-arm64.zip ...
|
|
592
606
|
Download Complete!
|
|
593
607
|
|
|
594
608
|
Extracting ['chromedriver'] from chromedriver-mac-arm64.zip ...
|
|
@@ -598,8 +612,8 @@ The file [chromedriver] was saved to:
|
|
|
598
612
|
~/github/SeleniumBase/seleniumbase/drivers/
|
|
599
613
|
chromedriver
|
|
600
614
|
|
|
601
|
-
Making [chromedriver
|
|
602
|
-
[chromedriver
|
|
615
|
+
Making [chromedriver 141.0.7390.78] executable ...
|
|
616
|
+
[chromedriver 141.0.7390.78] is now ready for use!
|
|
603
617
|
```
|
|
604
618
|
|
|
605
619
|
</details>
|
|
@@ -711,7 +725,7 @@ self.assert_no_js_errors() # Verify there are no JS errors.
|
|
|
711
725
|
self.type("input", "dogs\n") # (The "\n" presses ENTER)
|
|
712
726
|
```
|
|
713
727
|
|
|
714
|
-
Most SeleniumBase scripts can be run with <code translate="no">pytest</code>, <code translate="no">pynose</code>, or pure <code translate="no">python</code>. Not all test runners can run all test formats. For example, tests that use the
|
|
728
|
+
Most SeleniumBase scripts can be run with <code translate="no">pytest</code>, <code translate="no">pynose</code>, or pure <code translate="no">python</code>. Not all test runners can run all test formats. For example, tests that use the `sb` pytest fixture can only be run with `pytest`. (See <a href="https://github.com/seleniumbase/SeleniumBase/blob/master/help_docs/syntax_formats.md">Syntax Formats</a>) There's also a <a href="https://behave.readthedocs.io/en/stable/gherkin.html#features" target="_blank">Gherkin</a> test format that runs with <a href="https://github.com/seleniumbase/SeleniumBase/blob/master/examples/behave_bdd/ReadMe.md">behave</a>.
|
|
715
729
|
|
|
716
730
|
```zsh
|
|
717
731
|
pytest coffee_cart_tests.py --rs
|
|
@@ -730,10 +744,10 @@ behave calculator.feature -D rs -D dashboard
|
|
|
730
744
|
|
|
731
745
|
<p>✅ <code translate="no">pytest</code> includes automatic test discovery. If you don't specify a specific file or folder to run, <code translate="no">pytest</code> will automatically search through all subdirectories for tests to run based on the following criteria:</p>
|
|
732
746
|
|
|
733
|
-
* Python files that start with
|
|
734
|
-
* Python methods that start with
|
|
747
|
+
* Python files that start with `test_` or end with `_test.py`.
|
|
748
|
+
* Python methods that start with `test_`.
|
|
735
749
|
|
|
736
|
-
With a SeleniumBase [pytest.ini](https://github.com/seleniumbase/SeleniumBase/blob/master/examples/pytest.ini) file present, you can modify default discovery settings. The Python class name can be anything because
|
|
750
|
+
With a SeleniumBase [pytest.ini](https://github.com/seleniumbase/SeleniumBase/blob/master/examples/pytest.ini) file present, you can modify default discovery settings. The Python class name can be anything because `seleniumbase.BaseCase` inherits `unittest.TestCase` to trigger autodiscovery.
|
|
737
751
|
|
|
738
752
|
<p>✅ You can do a pre-flight check to see which tests would get discovered by <code translate="no">pytest</code> before the actual run:</p>
|
|
739
753
|
|
|
@@ -775,7 +789,7 @@ pynose [FILE_NAME.py]:[CLASS_NAME].[METHOD_NAME]
|
|
|
775
789
|
pytest my_first_test.py --demo
|
|
776
790
|
```
|
|
777
791
|
|
|
778
|
-
🔵
|
|
792
|
+
🔵 `time.sleep(seconds)` can be used to make a test wait at a specific spot:
|
|
779
793
|
|
|
780
794
|
```python
|
|
781
795
|
import time; time.sleep(3) # Do nothing for 3 seconds.
|
|
@@ -789,15 +803,15 @@ import pytest; pytest.set_trace()
|
|
|
789
803
|
breakpoint() # Shortcut for "import pdb; pdb.set_trace()"
|
|
790
804
|
```
|
|
791
805
|
|
|
792
|
-
> (
|
|
806
|
+
> (**`pdb`** commands: `n`, `c`, `s`, `u`, `d` => `next`, `continue`, `step`, `up`, `down`)
|
|
793
807
|
|
|
794
|
-
🔵 To pause an active test that throws an exception or error, (*and keep the browser window open while **Debug Mode** begins in the console*), add
|
|
808
|
+
🔵 To pause an active test that throws an exception or error, (*and keep the browser window open while **Debug Mode** begins in the console*), add **`--pdb`** as a `pytest` option:
|
|
795
809
|
|
|
796
810
|
```zsh
|
|
797
811
|
pytest test_fail.py --pdb
|
|
798
812
|
```
|
|
799
813
|
|
|
800
|
-
🔵 To start tests in Debug Mode, add
|
|
814
|
+
🔵 To start tests in Debug Mode, add **`--trace`** as a `pytest` option:
|
|
801
815
|
|
|
802
816
|
```zsh
|
|
803
817
|
pytest test_coffee_cart.py --trace
|
|
@@ -836,6 +850,10 @@ pytest test_coffee_cart.py --trace
|
|
|
836
850
|
--edge # (Shortcut for "--browser=edge".)
|
|
837
851
|
--firefox # (Shortcut for "--browser=firefox".)
|
|
838
852
|
--safari # (Shortcut for "--browser=safari".)
|
|
853
|
+
--opera # (Shortcut for "--browser=opera".)
|
|
854
|
+
--brave # (Shortcut for "--browser=brave".)
|
|
855
|
+
--comet # (Shortcut for "--browser=comet".)
|
|
856
|
+
--atlas # (Shortcut for "--browser=atlas".)
|
|
839
857
|
--settings-file=FILE # (Override default SeleniumBase settings.)
|
|
840
858
|
--env=ENV # (Set the test env. Access with "self.env" in tests.)
|
|
841
859
|
--account=STR # (Set account. Access with "self.account" in tests.)
|
|
@@ -938,7 +956,7 @@ pytest test_coffee_cart.py --trace
|
|
|
938
956
|
|
|
939
957
|
--------
|
|
940
958
|
|
|
941
|
-
🔵 During test failures, logs and screenshots from the most recent test run will get saved to the
|
|
959
|
+
🔵 During test failures, logs and screenshots from the most recent test run will get saved to the `latest_logs/` folder. Those logs will get moved to `archived_logs/` if you add --archive_logs to command-line options, or have `ARCHIVE_EXISTING_LOGS` set to True in [settings.py](https://github.com/seleniumbase/SeleniumBase/blob/master/seleniumbase/config/settings.py), otherwise log files with be cleaned up at the start of the next test run. The `test_suite.py` collection contains tests that fail on purpose so that you can see how logging works.
|
|
942
960
|
|
|
943
961
|
```zsh
|
|
944
962
|
cd examples/
|
|
@@ -950,18 +968,18 @@ pytest test_suite.py --firefox
|
|
|
950
968
|
|
|
951
969
|
An easy way to override seleniumbase/config/settings.py is by using a custom settings file.
|
|
952
970
|
Here's the command-line option to add to tests: (See [examples/custom_settings.py](https://github.com/seleniumbase/SeleniumBase/blob/master/examples/custom_settings.py))
|
|
953
|
-
|
|
971
|
+
`--settings_file=custom_settings.py`
|
|
954
972
|
(Settings include default timeout values, a two-factor auth key, DB credentials, S3 credentials, and other important settings used by tests.)
|
|
955
973
|
|
|
956
|
-
🔵 To pass additional data from the command-line to tests, add
|
|
957
|
-
Inside your tests, you can use
|
|
974
|
+
🔵 To pass additional data from the command-line to tests, add `--data="ANY STRING"`.
|
|
975
|
+
Inside your tests, you can use `self.data` to access that.
|
|
958
976
|
|
|
959
977
|
<a id="directory_configuration"></a>
|
|
960
978
|
<h2><img src="https://seleniumbase.github.io/img/logo7.png" title="SeleniumBase" width="32" /> Directory Configuration:</h2>
|
|
961
979
|
|
|
962
|
-
🔵 When running tests with
|
|
980
|
+
🔵 When running tests with **`pytest`**, you'll want a copy of **[pytest.ini](https://github.com/seleniumbase/SeleniumBase/blob/master/pytest.ini)** in your root folders. When running tests with **`pynose`**, you'll want a copy of **[setup.cfg](https://github.com/seleniumbase/SeleniumBase/blob/master/setup.cfg)** in your root folders. These files specify default configuration details for tests. Test folders should also include a blank **[__init__.py](https://github.com/seleniumbase/SeleniumBase/blob/master/examples/offline_examples/__init__.py)** file to allow your test files to import other files from that folder.
|
|
963
981
|
|
|
964
|
-
🔵
|
|
982
|
+
🔵 `sbase mkdir DIR` creates a folder with config files and sample tests:
|
|
965
983
|
|
|
966
984
|
```zsh
|
|
967
985
|
sbase mkdir ui_tests
|
|
@@ -993,7 +1011,7 @@ ui_tests/
|
|
|
993
1011
|
└── swag_labs_test.py
|
|
994
1012
|
```
|
|
995
1013
|
|
|
996
|
-
<b>ProTip™:</b> You can also create a boilerplate folder without any sample tests in it by adding
|
|
1014
|
+
<b>ProTip™:</b> You can also create a boilerplate folder without any sample tests in it by adding `-b` or `--basic` to the `sbase mkdir` command:
|
|
997
1015
|
|
|
998
1016
|
```zsh
|
|
999
1017
|
sbase mkdir ui_tests --basic
|
|
@@ -1009,7 +1027,16 @@ ui_tests/
|
|
|
1009
1027
|
└── setup.cfg
|
|
1010
1028
|
```
|
|
1011
1029
|
|
|
1012
|
-
Of those files, the
|
|
1030
|
+
Of those files, the `pytest.ini` config file is the most important, followed by a blank `__init__.py` file. There's also a `setup.cfg` file (for pynose). Finally, the `requirements.txt` file can be used to help you install seleniumbase into your environments (if it's not already installed).
|
|
1031
|
+
|
|
1032
|
+
<b>ProTip™:</b> Add `--gha` to include a GitHub Actions `.yml` file with default settings:
|
|
1033
|
+
|
|
1034
|
+
```zsh
|
|
1035
|
+
ui_tests/
|
|
1036
|
+
└── .github
|
|
1037
|
+
└── workflows/
|
|
1038
|
+
└── python-package.yml
|
|
1039
|
+
```
|
|
1013
1040
|
|
|
1014
1041
|
--------
|
|
1015
1042
|
|
|
@@ -1029,20 +1056,20 @@ class MyTestClass(BaseCase):
|
|
|
1029
1056
|
self.assert_element("div#ARMY_OF_ROBOTS", timeout=1) # This should fail
|
|
1030
1057
|
```
|
|
1031
1058
|
|
|
1032
|
-
You can run it from the
|
|
1059
|
+
You can run it from the `examples/` folder like this:
|
|
1033
1060
|
|
|
1034
1061
|
```zsh
|
|
1035
1062
|
pytest test_fail.py
|
|
1036
1063
|
```
|
|
1037
1064
|
|
|
1038
|
-
🔵 You'll notice that a logs folder,
|
|
1065
|
+
🔵 You'll notice that a logs folder, `./latest_logs/`, was created to hold information (and screenshots) about the failing test. During test runs, past results get moved to the archived_logs folder if you have ARCHIVE_EXISTING_LOGS set to True in [settings.py](https://github.com/seleniumbase/SeleniumBase/blob/master/seleniumbase/config/settings.py), or if your run tests with `--archive-logs`. If you choose not to archive existing logs, they will be deleted and replaced by the logs of the latest test run.
|
|
1039
1066
|
|
|
1040
1067
|
--------
|
|
1041
1068
|
|
|
1042
1069
|
<a id="seleniumbase_dashboard"></a>
|
|
1043
1070
|
<h2><img src="https://seleniumbase.github.io/img/logo7.png" title="SeleniumBase" width="32" /> SeleniumBase Dashboard:</h2>
|
|
1044
1071
|
|
|
1045
|
-
🔵 The
|
|
1072
|
+
🔵 The `--dashboard` option for pytest generates a SeleniumBase Dashboard located at `dashboard.html`, which updates automatically as tests run and produce results. Example:
|
|
1046
1073
|
|
|
1047
1074
|
```zsh
|
|
1048
1075
|
pytest --dashboard --rs --headless
|
|
@@ -1050,13 +1077,13 @@ pytest --dashboard --rs --headless
|
|
|
1050
1077
|
|
|
1051
1078
|
<img src="https://seleniumbase.github.io/cdn/img/dashboard_1.png" alt="The SeleniumBase Dashboard" title="The SeleniumBase Dashboard" width="380" />
|
|
1052
1079
|
|
|
1053
|
-
🔵 Additionally, you can host your own SeleniumBase Dashboard Server on a port of your choice. Here's an example of that using Python's
|
|
1080
|
+
🔵 Additionally, you can host your own SeleniumBase Dashboard Server on a port of your choice. Here's an example of that using Python's `http.server`:
|
|
1054
1081
|
|
|
1055
1082
|
```zsh
|
|
1056
1083
|
python -m http.server 1948
|
|
1057
1084
|
```
|
|
1058
1085
|
|
|
1059
|
-
🔵 Now you can navigate to
|
|
1086
|
+
🔵 Now you can navigate to `http://localhost:1948/dashboard.html` in order to view the dashboard as a web app. This requires two different terminal windows: one for running the server, and another for running the tests, which should be run from the same directory. (Use <kbd>Ctrl+C</kbd> to stop the http server.)
|
|
1060
1087
|
|
|
1061
1088
|
🔵 Here's a full example of what the SeleniumBase Dashboard may look like:
|
|
1062
1089
|
|
|
@@ -1073,7 +1100,7 @@ pytest test_suite.py test_image_saving.py --dashboard --rs --headless
|
|
|
1073
1100
|
|
|
1074
1101
|
<h3>🔵 <code>pytest</code> HTML Reports:</h3>
|
|
1075
1102
|
|
|
1076
|
-
✅ Using
|
|
1103
|
+
✅ Using `--html=report.html` gives you a fancy report of the name specified after your test suite completes.
|
|
1077
1104
|
|
|
1078
1105
|
```zsh
|
|
1079
1106
|
pytest test_suite.py --html=report.html
|
|
@@ -1081,7 +1108,7 @@ pytest test_suite.py --html=report.html
|
|
|
1081
1108
|
|
|
1082
1109
|
<img src="https://seleniumbase.github.io/cdn/img/html_report.png" alt="Example Pytest Report" title="Example Pytest Report" width="520" />
|
|
1083
1110
|
|
|
1084
|
-
✅ When combining pytest html reports with SeleniumBase Dashboard usage, the pie chart from the Dashboard will get added to the html report. Additionally, if you set the html report URL to be the same as the Dashboard URL when also using the dashboard, (example:
|
|
1111
|
+
✅ When combining pytest html reports with SeleniumBase Dashboard usage, the pie chart from the Dashboard will get added to the html report. Additionally, if you set the html report URL to be the same as the Dashboard URL when also using the dashboard, (example: `--dashboard --html=dashboard.html`), then the Dashboard will become an advanced html report when all the tests complete.
|
|
1085
1112
|
|
|
1086
1113
|
✅ Here's an example of an upgraded html report:
|
|
1087
1114
|
|
|
@@ -1093,7 +1120,7 @@ pytest test_suite.py --dashboard --html=report.html
|
|
|
1093
1120
|
|
|
1094
1121
|
If viewing pytest html reports in [Jenkins](https://www.jenkins.io/), you may need to [configure Jenkins settings](https://stackoverflow.com/a/46197356/7058266) for the html to render correctly. This is due to [Jenkins CSP changes](https://www.jenkins.io/doc/book/system-administration/security/configuring-content-security-policy/).
|
|
1095
1122
|
|
|
1096
|
-
You can also use
|
|
1123
|
+
You can also use `--junit-xml=report.xml` to get an xml report instead. Jenkins can use this file to display better reporting for your tests.
|
|
1097
1124
|
|
|
1098
1125
|
```zsh
|
|
1099
1126
|
pytest test_suite.py --junit-xml=report.xml
|
|
@@ -1101,7 +1128,7 @@ pytest test_suite.py --junit-xml=report.xml
|
|
|
1101
1128
|
|
|
1102
1129
|
<h3>🔵 <code>pynose</code> Reports:</h3>
|
|
1103
1130
|
|
|
1104
|
-
The
|
|
1131
|
+
The `--report` option gives you a fancy report after your test suite completes.
|
|
1105
1132
|
|
|
1106
1133
|
```zsh
|
|
1107
1134
|
pynose test_suite.py --report
|
|
@@ -1109,7 +1136,7 @@ pynose test_suite.py --report
|
|
|
1109
1136
|
|
|
1110
1137
|
<img src="https://seleniumbase.github.io/cdn/img/nose_report.png" alt="Example pynose Report" title="Example pynose Report" width="320" />
|
|
1111
1138
|
|
|
1112
|
-
(NOTE: You can add
|
|
1139
|
+
(NOTE: You can add `--show-report` to immediately display pynose reports after the test suite completes. Only use `--show-report` when running tests locally because it pauses the test run.)
|
|
1113
1140
|
|
|
1114
1141
|
<h3>🔵 <code>behave</code> Dashboard & Reports:</h3>
|
|
1115
1142
|
|
|
@@ -1121,7 +1148,7 @@ behave behave_bdd/features/ -D dashboard -D headless
|
|
|
1121
1148
|
|
|
1122
1149
|
<img src="https://seleniumbase.github.io/cdn/img/sb_behave_dashboard.png" title="SeleniumBase" width="520">
|
|
1123
1150
|
|
|
1124
|
-
You can also use
|
|
1151
|
+
You can also use `--junit` to get `.xml` reports for each <code translate="no">behave</code> feature. Jenkins can use these files to display better reporting for your tests.
|
|
1125
1152
|
|
|
1126
1153
|
```zsh
|
|
1127
1154
|
behave behave_bdd/features/ --junit -D rs -D headless
|
|
@@ -1131,7 +1158,7 @@ behave behave_bdd/features/ --junit -D rs -D headless
|
|
|
1131
1158
|
|
|
1132
1159
|
See: [https://allurereport.org/docs/pytest/](https://allurereport.org/docs/pytest/)
|
|
1133
1160
|
|
|
1134
|
-
SeleniumBase no longer includes
|
|
1161
|
+
SeleniumBase no longer includes `allure-pytest` as part of installed dependencies. If you want to use it, install it first:
|
|
1135
1162
|
|
|
1136
1163
|
```zsh
|
|
1137
1164
|
pip install allure-pytest
|
|
@@ -1147,7 +1174,7 @@ pytest test_suite.py --alluredir=allure_results
|
|
|
1147
1174
|
|
|
1148
1175
|
<h3><img src="https://seleniumbase.github.io/img/logo7.png" title="SeleniumBase" width="32" /> Using a Proxy Server:</h3>
|
|
1149
1176
|
|
|
1150
|
-
If you wish to use a proxy server for your browser tests (Chromium or Firefox), you can add
|
|
1177
|
+
If you wish to use a proxy server for your browser tests (Chromium or Firefox), you can add `--proxy=IP_ADDRESS:PORT` as an argument on the command line.
|
|
1151
1178
|
|
|
1152
1179
|
```zsh
|
|
1153
1180
|
pytest proxy_test.py --proxy=IP_ADDRESS:PORT
|
|
@@ -1167,7 +1194,7 @@ pytest proxy_test.py --proxy="socks4://IP_ADDRESS:PORT"
|
|
|
1167
1194
|
pytest proxy_test.py --proxy="socks5://IP_ADDRESS:PORT"
|
|
1168
1195
|
```
|
|
1169
1196
|
|
|
1170
|
-
To make things easier, you can add your frequently-used proxies to PROXY_LIST in [proxy_list.py](https://github.com/seleniumbase/SeleniumBase/blob/master/seleniumbase/config/proxy_list.py), and then use
|
|
1197
|
+
To make things easier, you can add your frequently-used proxies to PROXY_LIST in [proxy_list.py](https://github.com/seleniumbase/SeleniumBase/blob/master/seleniumbase/config/proxy_list.py), and then use `--proxy=KEY_FROM_PROXY_LIST` to use the IP_ADDRESS:PORT of that key.
|
|
1171
1198
|
|
|
1172
1199
|
```zsh
|
|
1173
1200
|
pytest proxy_test.py --proxy=proxy1
|
|
@@ -1176,7 +1203,7 @@ pytest proxy_test.py --proxy=proxy1
|
|
|
1176
1203
|
|
|
1177
1204
|
<h3><img src="https://seleniumbase.github.io/img/logo7.png" title="SeleniumBase" width="32" /> Changing the User-Agent:</h3>
|
|
1178
1205
|
|
|
1179
|
-
🔵 If you wish to change the User-Agent for your browser tests (Chromium and Firefox only), you can add
|
|
1206
|
+
🔵 If you wish to change the User-Agent for your browser tests (Chromium and Firefox only), you can add `--agent="USER AGENT STRING"` as an argument on the command-line.
|
|
1180
1207
|
|
|
1181
1208
|
```zsh
|
|
1182
1209
|
pytest user_agent_test.py --agent="Mozilla/5.0 (Nintendo 3DS; U; ; en) Version/1.7412.EU"
|
|
@@ -1190,7 +1217,7 @@ pytest user_agent_test.py --agent="Mozilla/5.0 (Nintendo 3DS; U; ; en) Version/1
|
|
|
1190
1217
|
|
|
1191
1218
|
<h3><img src="https://seleniumbase.github.io/img/logo7.png" title="SeleniumBase" width="32" /> Building Guided Tours for Websites:</h3>
|
|
1192
1219
|
|
|
1193
|
-
🔵 Learn about <a href="https://github.com/seleniumbase/SeleniumBase/blob/master/examples/tour_examples/ReadMe.md">SeleniumBase Interactive Walkthroughs</a> (in the
|
|
1220
|
+
🔵 Learn about <a href="https://github.com/seleniumbase/SeleniumBase/blob/master/examples/tour_examples/ReadMe.md">SeleniumBase Interactive Walkthroughs</a> (in the `examples/tour_examples/` folder). It's great for prototyping a website onboarding experience.
|
|
1194
1221
|
|
|
1195
1222
|
|
|
1196
1223
|
<a id="utilizing_advanced_features"></a>
|
|
@@ -1259,7 +1286,7 @@ To click an element on the page:
|
|
|
1259
1286
|
self.click("div#my_id")
|
|
1260
1287
|
```
|
|
1261
1288
|
|
|
1262
|
-
**ProTip™:** In most web browsers, you can right-click on a page and select
|
|
1289
|
+
**ProTip™:** In most web browsers, you can right-click on a page and select `Inspect Element` to see the CSS selector details that you'll need to create your own scripts.
|
|
1263
1290
|
|
|
1264
1291
|
🔵 **Typing Text:**
|
|
1265
1292
|
|
|
@@ -1289,7 +1316,7 @@ attribute = self.get_attribute("#comic img", "title")
|
|
|
1289
1316
|
self.wait_for_element_present("div.my_class", timeout=10)
|
|
1290
1317
|
```
|
|
1291
1318
|
|
|
1292
|
-
(NOTE: You can also use:
|
|
1319
|
+
(NOTE: You can also use: `self.assert_element_present(ELEMENT)`)
|
|
1293
1320
|
|
|
1294
1321
|
🔵 **Asserting visibility of an element on a page within some number of seconds:**
|
|
1295
1322
|
|
|
@@ -1297,9 +1324,9 @@ self.wait_for_element_present("div.my_class", timeout=10)
|
|
|
1297
1324
|
self.wait_for_element_visible("a.my_class", timeout=5)
|
|
1298
1325
|
```
|
|
1299
1326
|
|
|
1300
|
-
(NOTE: The short versions of that are
|
|
1327
|
+
(NOTE: The short versions of that are `self.find_element(ELEMENT)` and `self.assert_element(ELEMENT)`. The `find_element()` version returns the element.)
|
|
1301
1328
|
|
|
1302
|
-
Since the line above returns the element, you can combine that with
|
|
1329
|
+
Since the line above returns the element, you can combine that with `.click()` as shown below:
|
|
1303
1330
|
|
|
1304
1331
|
```python
|
|
1305
1332
|
self.find_element("a.my_class", timeout=5).click()
|
|
@@ -1309,9 +1336,9 @@ self.find_element("a.my_class", timeout=5).click()
|
|
|
1309
1336
|
self.click("a.my_class") # DO IT THIS WAY!
|
|
1310
1337
|
```
|
|
1311
1338
|
|
|
1312
|
-
**ProTip™:** You can use dots to signify class names (Ex:
|
|
1339
|
+
**ProTip™:** You can use dots to signify class names (Ex: `div.class_name`) as a simplified version of `div[class="class_name"]` within a CSS selector.
|
|
1313
1340
|
|
|
1314
|
-
You can also use
|
|
1341
|
+
You can also use `*=` to search for any partial value in a CSS selector as shown below:
|
|
1315
1342
|
|
|
1316
1343
|
```python
|
|
1317
1344
|
self.click('a[name*="partial_name"]')
|
|
@@ -1324,7 +1351,7 @@ self.assert_text("Make it so!", "div#trek div.picard div.quotes")
|
|
|
1324
1351
|
self.assert_text("Tea. Earl Grey. Hot.", "div#trek div.picard div.quotes", timeout=3)
|
|
1325
1352
|
```
|
|
1326
1353
|
|
|
1327
|
-
(NOTE:
|
|
1354
|
+
(NOTE: `self.find_text(TEXT, ELEMENT)` and `self.wait_for_text(TEXT, ELEMENT)` also do this. For backwards compatibility, older method names were kept, but the default timeout may be different.)
|
|
1328
1355
|
|
|
1329
1356
|
🔵 **Asserting Anything:**
|
|
1330
1357
|
|
|
@@ -1338,14 +1365,14 @@ self.assert_equal(var1, var2)
|
|
|
1338
1365
|
|
|
1339
1366
|
🔵 **Useful Conditional Statements: (with creative examples)**
|
|
1340
1367
|
|
|
1341
|
-
❓
|
|
1368
|
+
❓ `is_element_visible(selector):` (visible on the page)
|
|
1342
1369
|
|
|
1343
1370
|
```python
|
|
1344
1371
|
if self.is_element_visible('div#warning'):
|
|
1345
1372
|
print("Red Alert: Something bad might be happening!")
|
|
1346
1373
|
```
|
|
1347
1374
|
|
|
1348
|
-
❓
|
|
1375
|
+
❓ `is_element_present(selector):` (present in the HTML)
|
|
1349
1376
|
|
|
1350
1377
|
```python
|
|
1351
1378
|
if self.is_element_present('div#top_secret img.tracking_cookie'):
|
|
@@ -1362,7 +1389,7 @@ def is_there_a_cloaked_klingon_ship_on_this_page():
|
|
|
1362
1389
|
return False
|
|
1363
1390
|
```
|
|
1364
1391
|
|
|
1365
|
-
❓
|
|
1392
|
+
❓ `is_text_visible(text, selector):` (text visible on element)
|
|
1366
1393
|
|
|
1367
1394
|
```python
|
|
1368
1395
|
if self.is_text_visible("You Shall Not Pass!", "h1"):
|
|
@@ -1402,7 +1429,7 @@ def get_mirror_universe_captain_picard_superbowl_ad(superbowl_year):
|
|
|
1402
1429
|
|
|
1403
1430
|
</details>
|
|
1404
1431
|
|
|
1405
|
-
❓
|
|
1432
|
+
❓ `is_link_text_visible(link_text):`
|
|
1406
1433
|
|
|
1407
1434
|
```python
|
|
1408
1435
|
if self.is_link_text_visible("Stop! Hammer time!"):
|
|
@@ -1427,7 +1454,7 @@ self.switch_to_frame("iframe")
|
|
|
1427
1454
|
self.switch_to_parent_frame() # Exit the current iframe
|
|
1428
1455
|
```
|
|
1429
1456
|
|
|
1430
|
-
To exit from multiple iframes, use
|
|
1457
|
+
To exit from multiple iframes, use `self.switch_to_default_content()`. (If inside a single iframe, this has the same effect as `self.switch_to_parent_frame()`.)
|
|
1431
1458
|
|
|
1432
1459
|
```python
|
|
1433
1460
|
self.switch_to_frame('iframe[name="frame1"]')
|
|
@@ -1500,7 +1527,7 @@ self.execute_script("return jQuery('textarea')[2].value") # Returns the css "va
|
|
|
1500
1527
|
|
|
1501
1528
|
<h3>🔵 How to handle a restrictive CSP:</h3>
|
|
1502
1529
|
|
|
1503
|
-
❗ Some websites have a restrictive [Content Security Policy](https://developer.mozilla.org/en-US/docs/Web/HTTP/CSP) to prevent users from loading jQuery and other external libraries onto their websites. If you need to use jQuery or another JS library on those websites, add
|
|
1530
|
+
❗ Some websites have a restrictive [Content Security Policy](https://developer.mozilla.org/en-US/docs/Web/HTTP/CSP) to prevent users from loading jQuery and other external libraries onto their websites. If you need to use jQuery or another JS library on those websites, add `--disable-csp` as a `pytest` command-line option to load a Chromium extension that bypasses the CSP.
|
|
1504
1531
|
|
|
1505
1532
|
<h3>🔵 More JavaScript fun:</h3>
|
|
1506
1533
|
|