seleniumbase 4.44.2__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.
Files changed (42) hide show
  1. seleniumbase/__version__.py +1 -1
  2. seleniumbase/behave/behave_sb.py +14 -0
  3. seleniumbase/console_scripts/run.py +1 -0
  4. seleniumbase/console_scripts/sb_install.py +142 -11
  5. seleniumbase/console_scripts/sb_mkdir.py +76 -0
  6. seleniumbase/console_scripts/sb_mkrec.py +25 -0
  7. seleniumbase/console_scripts/sb_recorder.py +40 -3
  8. seleniumbase/core/browser_launcher.py +279 -117
  9. seleniumbase/core/detect_b_ver.py +8 -6
  10. seleniumbase/core/log_helper.py +11 -16
  11. seleniumbase/core/mysql.py +1 -1
  12. seleniumbase/core/report_helper.py +3 -7
  13. seleniumbase/core/sb_cdp.py +275 -78
  14. seleniumbase/core/sb_driver.py +36 -5
  15. seleniumbase/core/session_helper.py +2 -4
  16. seleniumbase/drivers/chromium_drivers/__init__.py +0 -0
  17. seleniumbase/fixtures/base_case.py +251 -201
  18. seleniumbase/fixtures/constants.py +1 -0
  19. seleniumbase/fixtures/js_utils.py +52 -14
  20. seleniumbase/fixtures/page_actions.py +18 -7
  21. seleniumbase/fixtures/page_utils.py +4 -2
  22. seleniumbase/fixtures/shared_utils.py +2 -4
  23. seleniumbase/masterqa/master_qa.py +16 -2
  24. seleniumbase/plugins/base_plugin.py +8 -0
  25. seleniumbase/plugins/driver_manager.py +15 -5
  26. seleniumbase/plugins/pytest_plugin.py +43 -57
  27. seleniumbase/plugins/sb_manager.py +23 -19
  28. seleniumbase/plugins/selenium_plugin.py +20 -13
  29. seleniumbase/undetected/__init__.py +11 -10
  30. seleniumbase/undetected/cdp.py +1 -12
  31. seleniumbase/undetected/cdp_driver/browser.py +330 -128
  32. seleniumbase/undetected/cdp_driver/cdp_util.py +48 -14
  33. seleniumbase/undetected/cdp_driver/config.py +78 -11
  34. seleniumbase/undetected/cdp_driver/connection.py +15 -43
  35. seleniumbase/undetected/cdp_driver/element.py +37 -22
  36. seleniumbase/undetected/cdp_driver/tab.py +414 -39
  37. {seleniumbase-4.44.2.dist-info → seleniumbase-4.45.10.dist-info}/METADATA +140 -152
  38. {seleniumbase-4.44.2.dist-info → seleniumbase-4.45.10.dist-info}/RECORD +42 -41
  39. {seleniumbase-4.44.2.dist-info → seleniumbase-4.45.10.dist-info}/licenses/LICENSE +1 -1
  40. {seleniumbase-4.44.2.dist-info → seleniumbase-4.45.10.dist-info}/WHEEL +0 -0
  41. {seleniumbase-4.44.2.dist-info → seleniumbase-4.45.10.dist-info}/entry_points.txt +0 -0
  42. {seleniumbase-4.44.2.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.44.2
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
@@ -33,7 +33,6 @@ Classifier: Operating System :: Microsoft :: Windows
33
33
  Classifier: Operating System :: POSIX :: Linux
34
34
  Classifier: Programming Language :: Python
35
35
  Classifier: Programming Language :: Python :: 3
36
- Classifier: Programming Language :: Python :: 3.8
37
36
  Classifier: Programming Language :: Python :: 3.9
38
37
  Classifier: Programming Language :: Python :: 3.10
39
38
  Classifier: Programming Language :: Python :: 3.11
@@ -56,35 +55,28 @@ Classifier: Topic :: Software Development :: Testing
56
55
  Classifier: Topic :: Software Development :: Testing :: Acceptance
57
56
  Classifier: Topic :: Software Development :: Testing :: Traffic Generation
58
57
  Classifier: Topic :: Utilities
59
- Requires-Python: >=3.8
58
+ Requires-Python: >=3.9
60
59
  Description-Content-Type: text/markdown
61
60
  License-File: LICENSE
62
- Requires-Dist: pip>=25.0.1; python_version < "3.9"
63
- Requires-Dist: pip>=25.3; python_version >= "3.9"
61
+ Requires-Dist: pip>=25.3
64
62
  Requires-Dist: packaging>=25.0
65
63
  Requires-Dist: setuptools~=70.2; python_version < "3.10"
66
64
  Requires-Dist: setuptools>=80.9.0; python_version >= "3.10"
67
65
  Requires-Dist: wheel>=0.45.1
68
- Requires-Dist: attrs~=25.3.0; python_version < "3.9"
69
- Requires-Dist: attrs>=25.4.0; python_version >= "3.9"
70
- Requires-Dist: certifi>=2025.10.5
71
- Requires-Dist: exceptiongroup>=1.3.0
72
- Requires-Dist: websockets~=13.1; python_version < "3.9"
73
- Requires-Dist: websockets>=15.0.1; python_version >= "3.9"
74
- Requires-Dist: filelock~=3.16.1; python_version < "3.9"
75
- Requires-Dist: filelock~=3.19.1; python_version >= "3.9" and python_version < "3.10"
76
- Requires-Dist: filelock>=3.20.0; python_version >= "3.10"
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"
77
72
  Requires-Dist: fasteners>=0.20
78
- Requires-Dist: mycdp>=1.2.1
73
+ Requires-Dist: mycdp>=1.3.2
79
74
  Requires-Dist: pynose>=1.5.5
80
- Requires-Dist: platformdirs~=4.3.6; python_version < "3.9"
81
- Requires-Dist: platformdirs~=4.4.0; python_version >= "3.9" and python_version < "3.10"
82
- Requires-Dist: platformdirs>=4.5.0; python_version >= "3.10"
83
- Requires-Dist: typing-extensions~=4.13.2; python_version < "3.9"
84
- Requires-Dist: typing-extensions>=4.15.0; python_version >= "3.9"
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
85
78
  Requires-Dist: sbvirtualdisplay>=1.4.0
86
- Requires-Dist: MarkupSafe==2.1.5; python_version < "3.9"
87
- Requires-Dist: MarkupSafe>=3.0.3; python_version >= "3.9"
79
+ Requires-Dist: MarkupSafe>=3.0.3
88
80
  Requires-Dist: Jinja2>=3.1.6
89
81
  Requires-Dist: six>=1.17.0
90
82
  Requires-Dist: parse>=1.20.2
@@ -94,49 +86,44 @@ Requires-Dist: pyyaml>=6.0.3
94
86
  Requires-Dist: pygments>=2.19.2
95
87
  Requires-Dist: pyreadline3>=3.5.4; platform_system == "Windows"
96
88
  Requires-Dist: tabcompleter>=1.4.0
97
- Requires-Dist: pdbp>=1.8.0
89
+ Requires-Dist: pdbp>=1.8.1
98
90
  Requires-Dist: idna>=3.11
99
91
  Requires-Dist: chardet==5.2.0
100
92
  Requires-Dist: charset-normalizer<4,>=3.4.4
101
93
  Requires-Dist: urllib3<2,>=1.26.20; python_version < "3.10"
102
- Requires-Dist: urllib3<2.6.0,>=1.26.20; python_version >= "3.10"
103
- Requires-Dist: requests==2.32.4; python_version < "3.9"
104
- Requires-Dist: requests~=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
105
96
  Requires-Dist: sniffio==1.3.1
106
97
  Requires-Dist: h11==0.16.0
107
98
  Requires-Dist: outcome==1.3.0.post0
108
- Requires-Dist: trio==0.27.0; python_version < "3.9"
109
- Requires-Dist: trio<1,>=0.31.0; python_version >= "3.9"
99
+ Requires-Dist: trio<1,>=0.31.0; python_version < "3.10"
100
+ Requires-Dist: trio<1,>=0.32.0; python_version >= "3.10"
110
101
  Requires-Dist: trio-websocket~=0.12.2
111
- Requires-Dist: wsproto==1.2.0
112
- Requires-Dist: websocket-client~=1.8.0; python_version < "3.9"
113
- Requires-Dist: websocket-client~=1.9.0; python_version >= "3.9"
114
- Requires-Dist: selenium==4.27.1; python_version < "3.9"
115
- Requires-Dist: selenium==4.32.0; python_version >= "3.9" and python_version < "3.10"
116
- Requires-Dist: selenium==4.38.0; python_version >= "3.10"
117
- Requires-Dist: cssselect==1.2.0; python_version < "3.9"
118
- Requires-Dist: cssselect==1.3.0; python_version >= "3.9"
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
119
109
  Requires-Dist: sortedcontainers==2.4.0
120
- Requires-Dist: execnet==2.1.1
110
+ Requires-Dist: execnet==2.1.1; python_version < "3.10"
111
+ Requires-Dist: execnet==2.1.2; python_version >= "3.10"
121
112
  Requires-Dist: iniconfig==2.1.0; python_version < "3.10"
122
113
  Requires-Dist: iniconfig==2.3.0; python_version >= "3.10"
123
- Requires-Dist: pluggy==1.5.0; python_version < "3.9"
124
- Requires-Dist: pluggy==1.6.0; python_version >= "3.9"
125
- Requires-Dist: pytest==8.3.5; python_version < "3.9"
126
- Requires-Dist: pytest==8.4.2; python_version >= "3.9"
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"
127
117
  Requires-Dist: pytest-html==4.0.2
128
118
  Requires-Dist: pytest-metadata==3.1.1
129
119
  Requires-Dist: pytest-ordering==0.6
130
- Requires-Dist: pytest-rerunfailures==14.0; python_version < "3.9"
131
- Requires-Dist: pytest-rerunfailures==16.0.1; python_version >= "3.9" and python_version < "3.10"
120
+ Requires-Dist: pytest-rerunfailures==16.0.1; python_version < "3.10"
132
121
  Requires-Dist: pytest-rerunfailures==16.1; python_version >= "3.10"
133
- Requires-Dist: pytest-xdist==3.6.1; python_version < "3.9"
134
- Requires-Dist: pytest-xdist==3.8.0; python_version >= "3.9"
122
+ Requires-Dist: pytest-xdist==3.8.0
135
123
  Requires-Dist: parameterized==0.9.0
136
124
  Requires-Dist: behave==1.2.6
137
- Requires-Dist: soupsieve==2.7; python_version < "3.9"
138
- Requires-Dist: soupsieve~=2.8; python_version >= "3.9"
139
- Requires-Dist: beautifulsoup4~=4.14.2
125
+ Requires-Dist: soupsieve~=2.8.1
126
+ Requires-Dist: beautifulsoup4~=4.14.3
140
127
  Requires-Dist: pyotp==2.9.0
141
128
  Requires-Dist: python-xlib==0.33; platform_system == "Linux"
142
129
  Requires-Dist: PyAutoGUI>=0.9.54; platform_system == "Linux"
@@ -149,44 +136,36 @@ Requires-Dist: allure-pytest>=2.13.5; extra == "allure"
149
136
  Requires-Dist: allure-python-commons>=2.13.5; extra == "allure"
150
137
  Requires-Dist: allure-behave>=2.13.5; extra == "allure"
151
138
  Provides-Extra: coverage
152
- Requires-Dist: coverage>=7.6.1; python_version < "3.9" and extra == "coverage"
153
- Requires-Dist: coverage>=7.10.7; (python_version >= "3.9" and python_version < "3.10") and extra == "coverage"
154
- Requires-Dist: coverage>=7.11.0; python_version >= "3.10" and extra == "coverage"
155
- Requires-Dist: pytest-cov>=5.0.0; python_version < "3.9" and extra == "coverage"
156
- Requires-Dist: pytest-cov>=7.0.0; 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"
157
142
  Provides-Extra: flake8
158
- Requires-Dist: flake8==5.0.4; python_version < "3.9" and extra == "flake8"
159
- Requires-Dist: flake8==7.3.0; python_version >= "3.9" and extra == "flake8"
143
+ Requires-Dist: flake8==7.3.0; extra == "flake8"
160
144
  Requires-Dist: mccabe==0.7.0; extra == "flake8"
161
- Requires-Dist: pyflakes==2.5.0; python_version < "3.9" and extra == "flake8"
162
- Requires-Dist: pyflakes==3.4.0; python_version >= "3.9" and extra == "flake8"
163
- Requires-Dist: pycodestyle==2.9.1; python_version < "3.9" and extra == "flake8"
164
- 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"
165
147
  Provides-Extra: ipdb
166
148
  Requires-Dist: ipdb==0.13.13; extra == "ipdb"
167
149
  Requires-Dist: ipython==7.34.0; extra == "ipdb"
168
150
  Provides-Extra: mss
169
- Requires-Dist: mss==9.0.2; python_version < "3.9" and extra == "mss"
170
- Requires-Dist: mss==10.0.0; python_version >= "3.9" and extra == "mss"
151
+ Requires-Dist: mss==10.1.0; extra == "mss"
171
152
  Provides-Extra: pdfminer
172
- Requires-Dist: pdfminer.six==20250324; python_version < "3.9" and extra == "pdfminer"
173
- Requires-Dist: pdfminer.six==20250506; python_version >= "3.9" and extra == "pdfminer"
174
- Requires-Dist: cryptography==39.0.2; python_version < "3.9" and extra == "pdfminer"
175
- Requires-Dist: cryptography==46.0.3; python_version >= "3.9" and extra == "pdfminer"
176
- Requires-Dist: cffi==1.17.1; python_version < "3.9" and extra == "pdfminer"
177
- Requires-Dist: cffi==2.0.0; python_version >= "3.9" and extra == "pdfminer"
178
- Requires-Dist: pycparser==2.22; python_version < "3.9" and extra == "pdfminer"
179
- Requires-Dist: pycparser==2.23; python_version >= "3.9" and 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"
180
158
  Provides-Extra: pillow
181
- Requires-Dist: Pillow>=10.4.0; python_version < "3.9" and extra == "pillow"
182
- Requires-Dist: Pillow>=11.3.0; (python_version >= "3.9" and python_version < "3.10") and extra == "pillow"
183
- Requires-Dist: Pillow>=12.0.0; python_version >= "3.10" and extra == "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"
184
161
  Provides-Extra: pip-system-certs
185
162
  Requires-Dist: pip-system-certs==4.0; platform_system == "Windows" and extra == "pip-system-certs"
186
163
  Provides-Extra: proxy
187
164
  Requires-Dist: proxy.py==2.4.3; extra == "proxy"
165
+ Provides-Extra: playwright
166
+ Requires-Dist: playwright>=1.56.0; extra == "playwright"
188
167
  Provides-Extra: psutil
189
- Requires-Dist: psutil==7.1.2; extra == "psutil"
168
+ Requires-Dist: psutil>=7.1.3; extra == "psutil"
190
169
  Provides-Extra: pyautogui
191
170
  Requires-Dist: PyAutoGUI>=0.9.54; platform_system != "Linux" and extra == "pyautogui"
192
171
  Provides-Extra: selenium-stealth
@@ -240,62 +219,62 @@ Dynamic: summary
240
219
  <a href="https://github.com/seleniumbase/SeleniumBase/blob/master/help_docs/features_list.md">🏰 Features</a> |
241
220
  <a href="https://github.com/seleniumbase/SeleniumBase/blob/master/help_docs/customizing_test_runs.md">🎛️ Options</a> |
242
221
  <a href="https://github.com/seleniumbase/SeleniumBase/blob/master/examples/ReadMe.md">📚 Examples</a> |
243
- <a href="https://github.com/seleniumbase/SeleniumBase/blob/master/seleniumbase/console_scripts/ReadMe.md">🌠 Scripts</a> |
222
+ <a href="https://github.com/seleniumbase/SeleniumBase/blob/master/seleniumbase/console_scripts/ReadMe.md">🪄 Scripts</a> |
244
223
  <a href="https://github.com/seleniumbase/SeleniumBase/blob/master/help_docs/mobile_testing.md">📱 Mobile</a>
245
224
  <br />
246
- <a href="https://github.com/seleniumbase/SeleniumBase/blob/master/help_docs/method_summary.md">📘 APIs</a> |
247
- <a href="https://github.com/seleniumbase/SeleniumBase/blob/master/help_docs/syntax_formats.md"> 🔠 Formats</a> |
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> |
248
227
  <a href="https://github.com/seleniumbase/SeleniumBase/blob/master/help_docs/recorder_mode.md">🔴 Recorder</a> |
249
228
  <a href="https://github.com/seleniumbase/SeleniumBase/blob/master/examples/example_logs/ReadMe.md">📊 Dashboard</a> |
250
- <a href="https://github.com/seleniumbase/SeleniumBase/blob/master/help_docs/locale_codes.md">🗾 Locales</a> |
251
- <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>
252
230
  <br />
253
231
  <a href="https://github.com/seleniumbase/SeleniumBase/blob/master/help_docs/commander.md">🎖️ GUI</a> |
254
232
  <a href="https://seleniumbase.io/demo_page">📰 TestPage</a> |
255
233
  <a href="https://github.com/seleniumbase/SeleniumBase/blob/master/help_docs/uc_mode.md">👤 UC Mode</a> |
256
234
  <a href="https://github.com/seleniumbase/SeleniumBase/blob/master/examples/cdp_mode/ReadMe.md">🐙 CDP Mode</a> |
257
- <a href="https://github.com/seleniumbase/SeleniumBase/blob/master/examples/chart_maker/ReadMe.md">📶 Charts</a> |
258
- <a href="https://github.com/seleniumbase/SeleniumBase/blob/master/seleniumbase/utilities/selenium_grid/ReadMe.md">🌐 Grid</a>
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>
259
237
  <br />
260
238
  <a href="https://github.com/seleniumbase/SeleniumBase/blob/master/help_docs/how_it_works.md">👁️ How</a> |
261
- <a href="https://github.com/seleniumbase/SeleniumBase/tree/master/examples/migration/raw_selenium">🚝 Migrate</a> |
262
- <a href="https://github.com/seleniumbase/SeleniumBase/blob/master/help_docs/case_plans.md">🗂️ CasePlans</a> |
263
- <a href="https://github.com/seleniumbase/SeleniumBase/tree/master/examples/boilerplates">♻️ Template</a> |
264
- <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> |
265
242
  <a href="https://github.com/seleniumbase/SeleniumBase/blob/master/examples/tour_examples/ReadMe.md">🚎 Tours</a>
266
243
  <br />
267
244
  <a href="https://github.com/seleniumbase/SeleniumBase/blob/master/integrations/github/workflows/ReadMe.md">🤖 CI/CD</a> |
268
- <a href="https://github.com/seleniumbase/SeleniumBase/blob/master/help_docs/js_package_manager.md">🕹️ JSMgr</a> |
245
+ <a href="https://github.com/seleniumbase/SeleniumBase/blob/master/help_docs/js_package_manager.md">❇️ JSMgr</a> |
269
246
  <a href="https://github.com/seleniumbase/SeleniumBase/blob/master/help_docs/translations.md">🌏 Translator</a> |
270
247
  <a href="https://github.com/seleniumbase/SeleniumBase/blob/master/examples/presenter/ReadMe.md">🎞️ Presenter</a> |
271
- <a href="https://github.com/seleniumbase/SeleniumBase/blob/master/examples/dialog_boxes/ReadMe.md">🛂 Dialog</a> |
272
- <a href="https://github.com/seleniumbase/SeleniumBase/blob/master/examples/visual_testing/ReadMe.md">🖼️ Visual</a>
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>
273
250
  <br />
274
251
  </p>
275
252
 
276
- <p>SeleniumBase is a browser automation framework for the modern web. Both new and experienced Python users alike can easily get started. With special stealth features like UC Mode and CDP Mode, you'll be evading bot-detection and bypassing CAPTCHAs in minutes.</p>
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>
277
254
 
278
255
  --------
279
256
 
280
257
  📚 Learn from [**over 200 examples** in the **SeleniumBase/examples/** folder](https://github.com/seleniumbase/SeleniumBase/tree/master/examples).
281
258
 
282
- 🐙 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> help you evade bot-detection.
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>.
283
260
 
284
- ℹ️ Most scripts run with raw <code translate="no"><b>python</b></code>, although some scripts 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).
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).
285
262
 
286
263
  --------
287
264
 
288
- <p align="left">📗 Here's a test script that performs a Google Search using SeleniumBase UC Mode:<br /><a href="https://github.com/seleniumbase/SeleniumBase/blob/master/examples/raw_google.py">SeleniumBase/examples/raw_google.py</a> (Results are saved as PDF, HTML, and PNG)</p>
265
+ <p align="left">📗 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>
289
266
 
290
267
  ```python
291
268
  from seleniumbase import SB
292
269
 
293
- with SB(test=True, uc=True) as sb:
294
- sb.open("https://google.com/ncr")
270
+ with SB(uc=True, test=True) as sb:
271
+ url = "https://google.com/ncr"
272
+ sb.activate_cdp_mode(url)
295
273
  sb.type('[title="Search"]', "SeleniumBase GitHub page")
296
274
  sb.click("div:not([jsname]) > * > input")
275
+ sb.sleep(2)
297
276
  print(sb.get_page_title())
298
- sb.sleep(2) # Wait for the "AI Overview" result
277
+ sb.sleep(1) # Wait for the "AI Overview" result
299
278
  if sb.is_text_visible("Generating"):
300
279
  sb.wait_for_text("AI Overview")
301
280
  sb.save_as_pdf_to_logs() # Saved to ./latest_logs/
@@ -317,8 +296,8 @@ from seleniumbase import SB
317
296
  with SB(uc=True, test=True, locale="en") as sb:
318
297
  url = "https://gitlab.com/users/sign_in"
319
298
  sb.activate_cdp_mode(url)
320
- sb.sleep(2.2)
321
- sb.uc_gui_click_captcha()
299
+ sb.sleep(2)
300
+ sb.solve_captcha()
322
301
  # (The rest is for testing and demo purposes)
323
302
  sb.assert_text("Username", '[for="user_login"]', timeout=3)
324
303
  sb.assert_element('label[for="user_login"]')
@@ -335,9 +314,9 @@ with SB(uc=True, test=True, locale="en") as sb:
335
314
  from seleniumbase import sb_cdp
336
315
 
337
316
  url = "https://gitlab.com/users/sign_in"
338
- sb = sb_cdp.Chrome(url)
339
- sb.sleep(2.5)
340
- sb.gui_click_captcha()
317
+ sb = sb_cdp.Chrome(url, incognito=True)
318
+ sb.sleep(2)
319
+ sb.solve_captcha()
341
320
  sb.highlight('h1:contains("GitLab")')
342
321
  sb.highlight('button:contains("Sign in")')
343
322
  sb.driver.stop()
@@ -373,7 +352,7 @@ class MyTestClass(BaseCase):
373
352
 
374
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>
375
354
 
376
- > (The default browser is ``--chrome`` if not set.)
355
+ > (The default browser is `--chrome` if not set.)
377
356
 
378
357
  --------
379
358
 
@@ -537,18 +516,18 @@ finally:
537
516
  <a id="install_seleniumbase"></a>
538
517
  <h2><img src="https://seleniumbase.github.io/img/logo7.png" title="SeleniumBase" width="32" /> Install SeleniumBase:</h2>
539
518
 
540
- **You can install ``seleniumbase`` from [PyPI](https://pypi.org/project/seleniumbase/) or [GitHub](https://github.com/seleniumbase/SeleniumBase):**
519
+ **You can install `seleniumbase` from [PyPI](https://pypi.org/project/seleniumbase/) or [GitHub](https://github.com/seleniumbase/SeleniumBase):**
541
520
 
542
- 🔵 **How to install ``seleniumbase`` from PyPI:**
521
+ 🔵 **How to install `seleniumbase` from PyPI:**
543
522
 
544
523
  ```zsh
545
524
  pip install seleniumbase
546
525
  ```
547
526
 
548
- * (Add ``--upgrade`` OR ``-U`` to upgrade SeleniumBase.)
549
- * (Add ``--force-reinstall`` to upgrade indirect packages.)
527
+ * (Add `--upgrade` OR `-U` to upgrade SeleniumBase.)
528
+ * (Add `--force-reinstall` to upgrade indirect packages.)
550
529
 
551
- 🔵 **How to install ``seleniumbase`` from a GitHub clone:**
530
+ 🔵 **How to install `seleniumbase` from a GitHub clone:**
552
531
 
553
532
  ```zsh
554
533
  git clone https://github.com/seleniumbase/SeleniumBase.git
@@ -563,7 +542,7 @@ git pull
563
542
  pip install -e .
564
543
  ```
565
544
 
566
- 🔵 **Type ``seleniumbase`` or ``sbase`` to verify that SeleniumBase was installed successfully:**
545
+ 🔵 **Type `seleniumbase` or `sbase` to verify that SeleniumBase was installed successfully:**
567
546
 
568
547
  ```zsh
569
548
  ___ _ _ ___
@@ -613,7 +592,7 @@ pip install -e .
613
592
 
614
593
  <h3>🔵 Downloading webdrivers:</h3>
615
594
 
616
- ✅ SeleniumBase automatically downloads webdrivers as needed, such as ``chromedriver``.
595
+ ✅ SeleniumBase automatically downloads webdrivers as needed, such as `chromedriver`.
617
596
 
618
597
  <div></div>
619
598
  <details>
@@ -746,7 +725,7 @@ self.assert_no_js_errors() # Verify there are no JS errors.
746
725
  self.type("input", "dogs\n") # (The "\n" presses ENTER)
747
726
  ```
748
727
 
749
- 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>.
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>.
750
729
 
751
730
  ```zsh
752
731
  pytest coffee_cart_tests.py --rs
@@ -765,10 +744,10 @@ behave calculator.feature -D rs -D dashboard
765
744
 
766
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>
767
746
 
768
- * Python files that start with ``test_`` or end with ``_test.py``.
769
- * Python methods that start with ``test_``.
747
+ * Python files that start with `test_` or end with `_test.py`.
748
+ * Python methods that start with `test_`.
770
749
 
771
- 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.
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.
772
751
 
773
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>
774
753
 
@@ -810,7 +789,7 @@ pynose [FILE_NAME.py]:[CLASS_NAME].[METHOD_NAME]
810
789
  pytest my_first_test.py --demo
811
790
  ```
812
791
 
813
- 🔵 ``time.sleep(seconds)`` can be used to make a test wait at a specific spot:
792
+ 🔵 `time.sleep(seconds)` can be used to make a test wait at a specific spot:
814
793
 
815
794
  ```python
816
795
  import time; time.sleep(3) # Do nothing for 3 seconds.
@@ -824,15 +803,15 @@ import pytest; pytest.set_trace()
824
803
  breakpoint() # Shortcut for "import pdb; pdb.set_trace()"
825
804
  ```
826
805
 
827
- > (**``pdb``** commands: ``n``, ``c``, ``s``, ``u``, ``d`` => ``next``, ``continue``, ``step``, ``up``, ``down``)
806
+ > (**`pdb`** commands: `n`, `c`, `s`, `u`, `d` => `next`, `continue`, `step`, `up`, `down`)
828
807
 
829
- 🔵 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:
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:
830
809
 
831
810
  ```zsh
832
811
  pytest test_fail.py --pdb
833
812
  ```
834
813
 
835
- 🔵 To start tests in Debug Mode, add **``--trace``** as a ``pytest`` option:
814
+ 🔵 To start tests in Debug Mode, add **`--trace`** as a `pytest` option:
836
815
 
837
816
  ```zsh
838
817
  pytest test_coffee_cart.py --trace
@@ -977,7 +956,7 @@ pytest test_coffee_cart.py --trace
977
956
 
978
957
  --------
979
958
 
980
- 🔵 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.
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.
981
960
 
982
961
  ```zsh
983
962
  cd examples/
@@ -989,18 +968,18 @@ pytest test_suite.py --firefox
989
968
 
990
969
  An easy way to override seleniumbase/config/settings.py is by using a custom settings file.
991
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))
992
- ``--settings_file=custom_settings.py``
971
+ `--settings_file=custom_settings.py`
993
972
  (Settings include default timeout values, a two-factor auth key, DB credentials, S3 credentials, and other important settings used by tests.)
994
973
 
995
- 🔵 To pass additional data from the command-line to tests, add ``--data="ANY STRING"``.
996
- Inside your tests, you can use ``self.data`` to access that.
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.
997
976
 
998
977
  <a id="directory_configuration"></a>
999
978
  <h2><img src="https://seleniumbase.github.io/img/logo7.png" title="SeleniumBase" width="32" /> Directory Configuration:</h2>
1000
979
 
1001
- 🔵 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.
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.
1002
981
 
1003
- 🔵 ``sbase mkdir DIR`` creates a folder with config files and sample tests:
982
+ 🔵 `sbase mkdir DIR` creates a folder with config files and sample tests:
1004
983
 
1005
984
  ```zsh
1006
985
  sbase mkdir ui_tests
@@ -1032,7 +1011,7 @@ ui_tests/
1032
1011
  └── swag_labs_test.py
1033
1012
  ```
1034
1013
 
1035
- <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:
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:
1036
1015
 
1037
1016
  ```zsh
1038
1017
  sbase mkdir ui_tests --basic
@@ -1048,7 +1027,16 @@ ui_tests/
1048
1027
  └── setup.cfg
1049
1028
  ```
1050
1029
 
1051
- 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).
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
+ ```
1052
1040
 
1053
1041
  --------
1054
1042
 
@@ -1068,20 +1056,20 @@ class MyTestClass(BaseCase):
1068
1056
  self.assert_element("div#ARMY_OF_ROBOTS", timeout=1) # This should fail
1069
1057
  ```
1070
1058
 
1071
- You can run it from the ``examples/`` folder like this:
1059
+ You can run it from the `examples/` folder like this:
1072
1060
 
1073
1061
  ```zsh
1074
1062
  pytest test_fail.py
1075
1063
  ```
1076
1064
 
1077
- 🔵 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.
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.
1078
1066
 
1079
1067
  --------
1080
1068
 
1081
1069
  <a id="seleniumbase_dashboard"></a>
1082
1070
  <h2><img src="https://seleniumbase.github.io/img/logo7.png" title="SeleniumBase" width="32" /> SeleniumBase Dashboard:</h2>
1083
1071
 
1084
- 🔵 The ``--dashboard`` option for pytest generates a SeleniumBase Dashboard located at ``dashboard.html``, which updates automatically as tests run and produce results. Example:
1072
+ 🔵 The `--dashboard` option for pytest generates a SeleniumBase Dashboard located at `dashboard.html`, which updates automatically as tests run and produce results. Example:
1085
1073
 
1086
1074
  ```zsh
1087
1075
  pytest --dashboard --rs --headless
@@ -1089,13 +1077,13 @@ pytest --dashboard --rs --headless
1089
1077
 
1090
1078
  <img src="https://seleniumbase.github.io/cdn/img/dashboard_1.png" alt="The SeleniumBase Dashboard" title="The SeleniumBase Dashboard" width="380" />
1091
1079
 
1092
- 🔵 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``:
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`:
1093
1081
 
1094
1082
  ```zsh
1095
1083
  python -m http.server 1948
1096
1084
  ```
1097
1085
 
1098
- 🔵 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.)
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.)
1099
1087
 
1100
1088
  🔵 Here's a full example of what the SeleniumBase Dashboard may look like:
1101
1089
 
@@ -1112,7 +1100,7 @@ pytest test_suite.py test_image_saving.py --dashboard --rs --headless
1112
1100
 
1113
1101
  <h3>🔵 <code>pytest</code> HTML Reports:</h3>
1114
1102
 
1115
- ✅ Using ``--html=report.html`` gives you a fancy report of the name specified after your test suite completes.
1103
+ ✅ Using `--html=report.html` gives you a fancy report of the name specified after your test suite completes.
1116
1104
 
1117
1105
  ```zsh
1118
1106
  pytest test_suite.py --html=report.html
@@ -1120,7 +1108,7 @@ pytest test_suite.py --html=report.html
1120
1108
 
1121
1109
  <img src="https://seleniumbase.github.io/cdn/img/html_report.png" alt="Example Pytest Report" title="Example Pytest Report" width="520" />
1122
1110
 
1123
- ✅ 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.
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.
1124
1112
 
1125
1113
  ✅ Here's an example of an upgraded html report:
1126
1114
 
@@ -1132,7 +1120,7 @@ pytest test_suite.py --dashboard --html=report.html
1132
1120
 
1133
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/).
1134
1122
 
1135
- 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.
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.
1136
1124
 
1137
1125
  ```zsh
1138
1126
  pytest test_suite.py --junit-xml=report.xml
@@ -1140,7 +1128,7 @@ pytest test_suite.py --junit-xml=report.xml
1140
1128
 
1141
1129
  <h3>🔵 <code>pynose</code> Reports:</h3>
1142
1130
 
1143
- The ``--report`` option gives you a fancy report after your test suite completes.
1131
+ The `--report` option gives you a fancy report after your test suite completes.
1144
1132
 
1145
1133
  ```zsh
1146
1134
  pynose test_suite.py --report
@@ -1148,7 +1136,7 @@ pynose test_suite.py --report
1148
1136
 
1149
1137
  <img src="https://seleniumbase.github.io/cdn/img/nose_report.png" alt="Example pynose Report" title="Example pynose Report" width="320" />
1150
1138
 
1151
- (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.)
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.)
1152
1140
 
1153
1141
  <h3>🔵 <code>behave</code> Dashboard & Reports:</h3>
1154
1142
 
@@ -1160,7 +1148,7 @@ behave behave_bdd/features/ -D dashboard -D headless
1160
1148
 
1161
1149
  <img src="https://seleniumbase.github.io/cdn/img/sb_behave_dashboard.png" title="SeleniumBase" width="520">
1162
1150
 
1163
- 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.
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.
1164
1152
 
1165
1153
  ```zsh
1166
1154
  behave behave_bdd/features/ --junit -D rs -D headless
@@ -1170,7 +1158,7 @@ behave behave_bdd/features/ --junit -D rs -D headless
1170
1158
 
1171
1159
  See: [https://allurereport.org/docs/pytest/](https://allurereport.org/docs/pytest/)
1172
1160
 
1173
- SeleniumBase no longer includes ``allure-pytest`` as part of installed dependencies. If you want to use it, install it first:
1161
+ SeleniumBase no longer includes `allure-pytest` as part of installed dependencies. If you want to use it, install it first:
1174
1162
 
1175
1163
  ```zsh
1176
1164
  pip install allure-pytest
@@ -1186,7 +1174,7 @@ pytest test_suite.py --alluredir=allure_results
1186
1174
 
1187
1175
  <h3><img src="https://seleniumbase.github.io/img/logo7.png" title="SeleniumBase" width="32" /> Using a Proxy Server:</h3>
1188
1176
 
1189
- 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.
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.
1190
1178
 
1191
1179
  ```zsh
1192
1180
  pytest proxy_test.py --proxy=IP_ADDRESS:PORT
@@ -1206,7 +1194,7 @@ pytest proxy_test.py --proxy="socks4://IP_ADDRESS:PORT"
1206
1194
  pytest proxy_test.py --proxy="socks5://IP_ADDRESS:PORT"
1207
1195
  ```
1208
1196
 
1209
- 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.
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.
1210
1198
 
1211
1199
  ```zsh
1212
1200
  pytest proxy_test.py --proxy=proxy1
@@ -1215,7 +1203,7 @@ pytest proxy_test.py --proxy=proxy1
1215
1203
 
1216
1204
  <h3><img src="https://seleniumbase.github.io/img/logo7.png" title="SeleniumBase" width="32" /> Changing the User-Agent:</h3>
1217
1205
 
1218
- 🔵 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.
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.
1219
1207
 
1220
1208
  ```zsh
1221
1209
  pytest user_agent_test.py --agent="Mozilla/5.0 (Nintendo 3DS; U; ; en) Version/1.7412.EU"
@@ -1229,7 +1217,7 @@ pytest user_agent_test.py --agent="Mozilla/5.0 (Nintendo 3DS; U; ; en) Version/1
1229
1217
 
1230
1218
  <h3><img src="https://seleniumbase.github.io/img/logo7.png" title="SeleniumBase" width="32" /> Building Guided Tours for Websites:</h3>
1231
1219
 
1232
- 🔵 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.
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.
1233
1221
 
1234
1222
 
1235
1223
  <a id="utilizing_advanced_features"></a>
@@ -1298,7 +1286,7 @@ To click an element on the page:
1298
1286
  self.click("div#my_id")
1299
1287
  ```
1300
1288
 
1301
- **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.
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.
1302
1290
 
1303
1291
  🔵 **Typing Text:**
1304
1292
 
@@ -1328,7 +1316,7 @@ attribute = self.get_attribute("#comic img", "title")
1328
1316
  self.wait_for_element_present("div.my_class", timeout=10)
1329
1317
  ```
1330
1318
 
1331
- (NOTE: You can also use: ``self.assert_element_present(ELEMENT)``)
1319
+ (NOTE: You can also use: `self.assert_element_present(ELEMENT)`)
1332
1320
 
1333
1321
  🔵 **Asserting visibility of an element on a page within some number of seconds:**
1334
1322
 
@@ -1336,9 +1324,9 @@ self.wait_for_element_present("div.my_class", timeout=10)
1336
1324
  self.wait_for_element_visible("a.my_class", timeout=5)
1337
1325
  ```
1338
1326
 
1339
- (NOTE: The short versions of that are ``self.find_element(ELEMENT)`` and ``self.assert_element(ELEMENT)``. The ``find_element()`` version returns the element.)
1327
+ (NOTE: The short versions of that are `self.find_element(ELEMENT)` and `self.assert_element(ELEMENT)`. The `find_element()` version returns the element.)
1340
1328
 
1341
- Since the line above returns the element, you can combine that with ``.click()`` as shown below:
1329
+ Since the line above returns the element, you can combine that with `.click()` as shown below:
1342
1330
 
1343
1331
  ```python
1344
1332
  self.find_element("a.my_class", timeout=5).click()
@@ -1348,9 +1336,9 @@ self.find_element("a.my_class", timeout=5).click()
1348
1336
  self.click("a.my_class") # DO IT THIS WAY!
1349
1337
  ```
1350
1338
 
1351
- **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.
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.
1352
1340
 
1353
- You can also use ``*=`` to search for any partial value in a CSS selector as shown below:
1341
+ You can also use `*=` to search for any partial value in a CSS selector as shown below:
1354
1342
 
1355
1343
  ```python
1356
1344
  self.click('a[name*="partial_name"]')
@@ -1363,7 +1351,7 @@ self.assert_text("Make it so!", "div#trek div.picard div.quotes")
1363
1351
  self.assert_text("Tea. Earl Grey. Hot.", "div#trek div.picard div.quotes", timeout=3)
1364
1352
  ```
1365
1353
 
1366
- (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.)
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.)
1367
1355
 
1368
1356
  🔵 **Asserting Anything:**
1369
1357
 
@@ -1377,14 +1365,14 @@ self.assert_equal(var1, var2)
1377
1365
 
1378
1366
  🔵 **Useful Conditional Statements: (with creative examples)**
1379
1367
 
1380
- ``is_element_visible(selector):`` (visible on the page)
1368
+ `is_element_visible(selector):` (visible on the page)
1381
1369
 
1382
1370
  ```python
1383
1371
  if self.is_element_visible('div#warning'):
1384
1372
  print("Red Alert: Something bad might be happening!")
1385
1373
  ```
1386
1374
 
1387
- ``is_element_present(selector):`` (present in the HTML)
1375
+ `is_element_present(selector):` (present in the HTML)
1388
1376
 
1389
1377
  ```python
1390
1378
  if self.is_element_present('div#top_secret img.tracking_cookie'):
@@ -1401,7 +1389,7 @@ def is_there_a_cloaked_klingon_ship_on_this_page():
1401
1389
  return False
1402
1390
  ```
1403
1391
 
1404
- ``is_text_visible(text, selector):`` (text visible on element)
1392
+ `is_text_visible(text, selector):` (text visible on element)
1405
1393
 
1406
1394
  ```python
1407
1395
  if self.is_text_visible("You Shall Not Pass!", "h1"):
@@ -1441,7 +1429,7 @@ def get_mirror_universe_captain_picard_superbowl_ad(superbowl_year):
1441
1429
 
1442
1430
  </details>
1443
1431
 
1444
- ``is_link_text_visible(link_text):``
1432
+ `is_link_text_visible(link_text):`
1445
1433
 
1446
1434
  ```python
1447
1435
  if self.is_link_text_visible("Stop! Hammer time!"):
@@ -1466,7 +1454,7 @@ self.switch_to_frame("iframe")
1466
1454
  self.switch_to_parent_frame() # Exit the current iframe
1467
1455
  ```
1468
1456
 
1469
- 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()``.)
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()`.)
1470
1458
 
1471
1459
  ```python
1472
1460
  self.switch_to_frame('iframe[name="frame1"]')
@@ -1539,7 +1527,7 @@ self.execute_script("return jQuery('textarea')[2].value") # Returns the css "va
1539
1527
 
1540
1528
  <h3>🔵 How to handle a restrictive CSP:</h3>
1541
1529
 
1542
- ❗ 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.
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.
1543
1531
 
1544
1532
  <h3>🔵 More JavaScript fun:</h3>
1545
1533