pytest-seleniumbase 4.13.11__py3-none-any.whl → 4.44.8__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.

Potentially problematic release.


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

@@ -1,19 +1,20 @@
1
- Metadata-Version: 2.1
1
+ Metadata-Version: 2.4
2
2
  Name: pytest-seleniumbase
3
- Version: 4.13.11
3
+ Version: 4.44.8
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
7
7
  Author-email: mdmintz@gmail.com
8
8
  Maintainer: Michael Mintz
9
9
  License: MIT
10
+ Project-URL: Homepage, https://github.com/seleniumbase/SeleniumBase
10
11
  Project-URL: Changelog, https://github.com/seleniumbase/SeleniumBase/releases
11
12
  Project-URL: Download, https://pypi.org/project/seleniumbase/#files
12
- Project-URL: Gitter, https://gitter.im/seleniumbase/SeleniumBase
13
- Project-URL: Slack, https://app.slack.com/client/T0ABCRTNX/C01SM888REZ
14
13
  Project-URL: Blog, https://seleniumbase.com/
14
+ Project-URL: Discord, https://discord.gg/EdhQTn3EyE
15
15
  Project-URL: PyPI, https://pypi.org/project/seleniumbase/
16
16
  Project-URL: Source, https://github.com/seleniumbase/SeleniumBase
17
+ Project-URL: Repository, https://github.com/seleniumbase/SeleniumBase
17
18
  Project-URL: Documentation, https://seleniumbase.io/
18
19
  Platform: Windows
19
20
  Platform: Linux
@@ -26,234 +27,334 @@ Classifier: Environment :: Web Environment
26
27
  Classifier: Framework :: Pytest
27
28
  Classifier: Intended Audience :: Developers
28
29
  Classifier: Intended Audience :: Information Technology
29
- Classifier: License :: OSI Approved :: MIT License
30
30
  Classifier: Operating System :: MacOS :: MacOS X
31
31
  Classifier: Operating System :: Microsoft :: Windows
32
32
  Classifier: Operating System :: POSIX :: Linux
33
33
  Classifier: Programming Language :: Python
34
34
  Classifier: Programming Language :: Python :: 3
35
- Classifier: Programming Language :: Python :: 2.7
36
- Classifier: Programming Language :: Python :: 3.6
37
- Classifier: Programming Language :: Python :: 3.7
38
35
  Classifier: Programming Language :: Python :: 3.8
39
36
  Classifier: Programming Language :: Python :: 3.9
40
37
  Classifier: Programming Language :: Python :: 3.10
41
38
  Classifier: Programming Language :: Python :: 3.11
39
+ Classifier: Programming Language :: Python :: 3.12
40
+ Classifier: Programming Language :: Python :: 3.13
41
+ Classifier: Programming Language :: Python :: 3.14
42
42
  Classifier: Topic :: Internet
43
43
  Classifier: Topic :: Scientific/Engineering
44
44
  Classifier: Topic :: Software Development
45
45
  Classifier: Topic :: Software Development :: Quality Assurance
46
46
  Classifier: Topic :: Software Development :: Libraries
47
+ Classifier: Topic :: Software Development :: Libraries :: Application Frameworks
48
+ Classifier: Topic :: Software Development :: Libraries :: Python Modules
47
49
  Classifier: Topic :: Software Development :: Testing
48
50
  Classifier: Topic :: Software Development :: Testing :: Acceptance
49
51
  Classifier: Topic :: Software Development :: Testing :: Traffic Generation
50
52
  Classifier: Topic :: Utilities
51
- Requires-Python: >=3.6
53
+ Requires-Python: >=3.8
52
54
  Description-Content-Type: text/markdown
53
- Requires-Dist: seleniumbase (>=4.13.11)
55
+ Requires-Dist: seleniumbase>=4.44.8
56
+ Dynamic: author
57
+ Dynamic: author-email
58
+ Dynamic: classifier
59
+ Dynamic: home-page
60
+ Dynamic: license
61
+ Dynamic: maintainer
62
+ Dynamic: platform
63
+ Dynamic: requires-dist
64
+ Dynamic: requires-python
65
+ Dynamic: summary
54
66
 
55
67
  **[<img src="https://img.shields.io/badge/pypi-pytest--seleniumbase-22AAEE.svg" alt="pypi" />](https://pypi.python.org/pypi/pytest-seleniumbase) is a proxy for [<img src="https://img.shields.io/badge/pypi-seleniumbase-22AAEE.svg" alt="pypi" />](https://pypi.python.org/pypi/seleniumbase)**
56
68
  ****
57
69
 
58
70
  <!-- SeleniumBase Docs -->
59
71
 
72
+ <meta property="og:site_name" content="SeleniumBase">
73
+ <meta property="og:title" content="SeleniumBase: Python Web Automation and E2E Testing" />
74
+ <meta property="og:description" content="Fast, easy, and reliable Web/UI testing with Python." />
75
+ <meta property="og:keywords" content="Python, pytest, selenium, webdriver, testing, automation, seleniumbase, framework, dashboard, recorder, reports, screenshots">
76
+ <meta property="og:image" content="https://seleniumbase.github.io/cdn/img/mac_sb_logo_5b.png" />
77
+ <link rel="icon" href="https://seleniumbase.github.io/img/logo7.png" />
60
78
 
61
79
  <h1>SeleniumBase</h1>
62
80
 
63
- <h3 align="center"><a href="https://github.com/seleniumbase/SeleniumBase/"><img src="https://seleniumbase.io/cdn/img/sb_logo_10t.png" alt="SeleniumBase" title="SeleniumBase" width="266" /></a></h3>
81
+ <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>
64
82
 
65
- <h3 align="center">Create reliable end-to-end browser tests with Python</h3>
66
83
 
67
- <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> <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://gitter.im/seleniumbase/SeleniumBase" target="_blank"><img src="https://badges.gitter.im/seleniumbase/SeleniumBase.svg" alt="SeleniumBase" /></a></p>
84
+ <p align="center" class="hero__title"><b>All-in-one Browser Automation Framework:<br />Web Crawling / Testing / Scraping / Stealth</b></p>
85
+
86
+ <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> <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://discord.gg/EdhQTn3EyE" target="_blank"><img src="https://img.shields.io/badge/join-discord-infomational" alt="Join the SeleniumBase chat on Discord"/></a></p>
68
87
 
69
88
  <p align="center">
70
89
  <a href="#python_installation">🚀 Start</a> |
71
90
  <a href="https://github.com/seleniumbase/SeleniumBase/blob/master/help_docs/features_list.md">🏰 Features</a> |
72
- <a href="https://github.com/seleniumbase/SeleniumBase/blob/master/examples/ReadMe.md">📚 Examples</a> |
73
91
  <a href="https://github.com/seleniumbase/SeleniumBase/blob/master/help_docs/customizing_test_runs.md">🎛️ Options</a> |
92
+ <a href="https://github.com/seleniumbase/SeleniumBase/blob/master/examples/ReadMe.md">📚 Examples</a> |
74
93
  <a href="https://github.com/seleniumbase/SeleniumBase/blob/master/seleniumbase/console_scripts/ReadMe.md">🌠 Scripts</a> |
75
- <a href="https://github.com/seleniumbase/SeleniumBase/blob/master/help_docs/mobile_testing.md">📱 Phone</a>
94
+ <a href="https://github.com/seleniumbase/SeleniumBase/blob/master/help_docs/mobile_testing.md">📱 Mobile</a>
76
95
  <br />
77
96
  <a href="https://github.com/seleniumbase/SeleniumBase/blob/master/help_docs/method_summary.md">📘 APIs</a> |
78
- <a href="https://github.com/seleniumbase/SeleniumBase/blob/master/help_docs/syntax_formats.md"> 🔡 Formats</a> |
79
- <a href="https://github.com/seleniumbase/SeleniumBase/blob/master/examples/example_logs/ReadMe.md">📊 Dashboard</a> |
97
+ <a href="https://github.com/seleniumbase/SeleniumBase/blob/master/help_docs/syntax_formats.md"> 🔠 Formats</a> |
80
98
  <a href="https://github.com/seleniumbase/SeleniumBase/blob/master/help_docs/recorder_mode.md">🔴 Recorder</a> |
99
+ <a href="https://github.com/seleniumbase/SeleniumBase/blob/master/examples/example_logs/ReadMe.md">📊 Dashboard</a> |
81
100
  <a href="https://github.com/seleniumbase/SeleniumBase/blob/master/help_docs/locale_codes.md">🗾 Locales</a> |
82
- <a href="https://github.com/seleniumbase/SeleniumBase/blob/master/seleniumbase/utilities/selenium_grid/ReadMe.md">🌐 Grid</a>
101
+ <a href="https://seleniumbase.io/devices/?url=seleniumbase.com">💻 Farm</a>
83
102
  <br />
84
103
  <a href="https://github.com/seleniumbase/SeleniumBase/blob/master/help_docs/commander.md">🎖️ GUI</a> |
85
104
  <a href="https://seleniumbase.io/demo_page">📰 TestPage</a> |
86
- <a href="https://github.com/seleniumbase/SeleniumBase/blob/master/help_docs/case_plans.md">🗂️ CasePlans</a> |
87
- <a href="https://github.com/seleniumbase/SeleniumBase/blob/master/help_docs/html_inspector.md">🕵️ Inspector</a> |
88
- <a href="https://github.com/seleniumbase/SeleniumBase/blob/master/examples/master_qa/ReadMe.md">🧬 Hybrid</a> |
89
- <a href="https://seleniumbase.io/devices/?url=seleniumbase.com">💻 Farm</a>
105
+ <a href="https://github.com/seleniumbase/SeleniumBase/blob/master/help_docs/uc_mode.md">👤 UC Mode</a> |
106
+ <a href="https://github.com/seleniumbase/SeleniumBase/blob/master/examples/cdp_mode/ReadMe.md">🐙 CDP Mode</a> |
107
+ <a href="https://github.com/seleniumbase/SeleniumBase/blob/master/examples/chart_maker/ReadMe.md">📶 Charts</a> |
108
+ <a href="https://github.com/seleniumbase/SeleniumBase/blob/master/seleniumbase/utilities/selenium_grid/ReadMe.md">🌐 Grid</a>
90
109
  <br />
91
110
  <a href="https://github.com/seleniumbase/SeleniumBase/blob/master/help_docs/how_it_works.md">👁️ How</a> |
92
111
  <a href="https://github.com/seleniumbase/SeleniumBase/tree/master/examples/migration/raw_selenium">🚝 Migrate</a> |
93
- <a href="https://github.com/seleniumbase/SeleniumBase/tree/master/examples/boilerplates">♻️ Templates</a> |
94
- <a href="https://github.com/seleniumbase/SeleniumBase/tree/master/integrations/node_js">🚉 NodeGUI</a> |
95
- <a href="https://github.com/seleniumbase/SeleniumBase/blob/master/examples/chart_maker/ReadMe.md">📶 Charts</a> |
112
+ <a href="https://github.com/seleniumbase/SeleniumBase/blob/master/help_docs/case_plans.md">🗂️ CasePlans</a> |
113
+ <a href="https://github.com/seleniumbase/SeleniumBase/tree/master/examples/boilerplates">♻️ Template</a> |
114
+ <a href="https://github.com/seleniumbase/SeleniumBase/blob/master/examples/master_qa/ReadMe.md">🧬 Hybrid</a> |
96
115
  <a href="https://github.com/seleniumbase/SeleniumBase/blob/master/examples/tour_examples/ReadMe.md">🚎 Tours</a>
97
116
  <br />
98
117
  <a href="https://github.com/seleniumbase/SeleniumBase/blob/master/integrations/github/workflows/ReadMe.md">🤖 CI/CD</a> |
99
118
  <a href="https://github.com/seleniumbase/SeleniumBase/blob/master/help_docs/js_package_manager.md">🕹️ JSMgr</a> |
100
119
  <a href="https://github.com/seleniumbase/SeleniumBase/blob/master/help_docs/translations.md">🌏 Translator</a> |
101
120
  <a href="https://github.com/seleniumbase/SeleniumBase/blob/master/examples/presenter/ReadMe.md">🎞️ Presenter</a> |
102
- <a href="https://github.com/seleniumbase/SeleniumBase/blob/master/examples/dialog_boxes/ReadMe.md">🛂 Boxes</a> |
121
+ <a href="https://github.com/seleniumbase/SeleniumBase/blob/master/examples/dialog_boxes/ReadMe.md">🛂 Dialog</a> |
103
122
  <a href="https://github.com/seleniumbase/SeleniumBase/blob/master/examples/visual_testing/ReadMe.md">🖼️ Visual</a>
104
123
  <br />
105
124
  </p>
106
125
 
126
+ <p>SeleniumBase is the professional toolkit for web automation activities. Built for testing websites, bypassing CAPTCHAs, enhancing productivity, completing tasks, and scaling your business.</p>
127
+
107
128
  --------
108
129
 
109
- <a id="multiple_examples"></a>
110
- <p align="left"><b>Example:</b> <a href="https://github.com/seleniumbase/SeleniumBase/blob/master/examples/test_coffee_cart.py" target="_blank">test_coffee_cart.py</a> from <a href="https://github.com/seleniumbase/SeleniumBase/tree/master/examples" target="_blank">./examples/</a></p>
130
+ 📚 Learn from [**over 200 examples** in the **SeleniumBase/examples/** folder](https://github.com/seleniumbase/SeleniumBase/tree/master/examples).
111
131
 
112
- ```bash
113
- cd examples/
114
- pytest test_coffee_cart.py --demo
132
+ 🐙 Note that <a translate="no" href="https://github.com/seleniumbase/SeleniumBase/blob/master/help_docs/uc_mode.md"><b>UC Mode</b></a> / <a href="https://github.com/seleniumbase/SeleniumBase/blob/master/examples/cdp_mode/ReadMe.md"><b>CDP Mode</b></a> (Stealth Mode) have their own ReadMe files.
133
+
134
+ ℹ️ 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).
135
+
136
+ --------
137
+
138
+ <p align="left">📗 Here's <a href="https://github.com/seleniumbase/SeleniumBase/blob/master/examples/raw_google.py">raw_google.py</a>, which performs a Google search:</p>
139
+
140
+ ```python
141
+ from seleniumbase import SB
142
+
143
+ with SB(test=True, uc=True) as sb:
144
+ sb.open("https://google.com/ncr")
145
+ sb.type('[title="Search"]', "SeleniumBase GitHub page\n")
146
+ sb.click('[href*="github.com/seleniumbase/"]')
147
+ sb.save_screenshot_to_logs() # ./latest_logs/
148
+ print(sb.get_page_title())
115
149
  ```
116
150
 
117
- <p>(<code>--demo</code> mode slows down tests and highlights actions)</p>
151
+ > `python raw_google.py`
118
152
 
119
- <p align="left"><a href="https://seleniumbase.io/coffee/" target="_blank"><img src="https://seleniumbase.github.io/cdn/gif/coffee_cart.gif" width="480" alt="SeleniumBase Coffee Cart Test" title="SeleniumBase Coffee Cart Test" /></a></p>
153
+ <a href="https://github.com/seleniumbase/SeleniumBase/blob/master/examples/raw_google.py"><img src="https://seleniumbase.github.io/cdn/gif/google_search.gif" alt="SeleniumBase Test" title="SeleniumBase Test" width="420" /></a>
154
+
155
+ --------
156
+
157
+ <p align="left">📗 Here's an example of bypassing Cloudflare's challenge page: <a href="https://github.com/seleniumbase/SeleniumBase/blob/master/examples/cdp_mode/raw_gitlab.py">SeleniumBase/examples/cdp_mode/raw_gitlab.py</a></p>
158
+
159
+ ```python
160
+ from seleniumbase import SB
161
+
162
+ with SB(uc=True, test=True, locale="en") as sb:
163
+ url = "https://gitlab.com/users/sign_in"
164
+ sb.activate_cdp_mode(url)
165
+ sb.uc_gui_click_captcha()
166
+ sb.sleep(2)
167
+ ```
168
+
169
+ <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">
120
170
 
121
- * Here's a preview of that test:
171
+ --------
172
+
173
+ <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>
122
174
 
123
175
  ```python
124
176
  from seleniumbase import BaseCase
125
- BaseCase.main(__name__, __file__)
177
+ BaseCase.main(__name__, __file__) # Call pytest
178
+
179
+ class MyTestClass(BaseCase):
180
+ def test_swag_labs(self):
181
+ self.open("https://www.saucedemo.com")
182
+ self.type("#user-name", "standard_user")
183
+ self.type("#password", "secret_sauce\n")
184
+ self.assert_element("div.inventory_list")
185
+ self.click('button[name*="backpack"]')
186
+ self.click("#shopping_cart_container a")
187
+ self.assert_text("Backpack", "div.cart_item")
188
+ self.click("button#checkout")
189
+ self.type("input#first-name", "SeleniumBase")
190
+ self.type("input#last-name", "Automation")
191
+ self.type("input#postal-code", "77123")
192
+ self.click("input#continue")
193
+ self.click("button#finish")
194
+ self.assert_text("Thank you for your order!")
195
+ ```
196
+
197
+ > `pytest test_get_swag.py`
198
+
199
+ <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>
200
+
201
+ > (The default browser is ``--chrome`` if not set.)
202
+
203
+ --------
204
+
205
+ <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>
206
+
207
+ ```bash
208
+ pytest test_coffee_cart.py --demo
209
+ ```
210
+
211
+ <p align="left"><a href="https://seleniumbase.io/coffee/" target="_blank"><img src="https://seleniumbase.github.io/cdn/gif/coffee_cart.gif" width="480" alt="SeleniumBase Coffee Cart Test" title="SeleniumBase Coffee Cart Test" /></a></p>
212
+
213
+ > <p>(<code translate="no">--demo</code> mode slows down tests and highlights actions)</p>
214
+
215
+ --------
216
+
217
+ <a id="multiple_examples"></a>
126
218
 
127
- class CoffeeCartTest(BaseCase):
128
- def test_coffee_cart(self):
129
- self.open("https://seleniumbase.io/coffee/")
130
- self.assert_title("Coffee Cart")
131
- self.click('div[data-sb="Cappuccino"]')
132
- self.click('div[data-sb="Flat-White"]')
133
- self.click('div[data-sb="Cafe-Latte"]')
134
- self.click('a[aria-label="Cart page"]')
135
- self.assert_exact_text("Total: $53.00", "button.pay")
136
- self.click("button.pay")
137
- self.type("input#name", "Selenium Coffee")
138
- self.type("input#email", "test@test.test")
139
- self.click("button#submit-payment")
140
- self.assert_text("Thanks for your purchase.", "#app .success")
219
+ <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>
220
+
221
+ ```bash
222
+ pytest test_demo_site.py
141
223
  ```
142
224
 
225
+ <p align="left"><a href="https://seleniumbase.io/demo_page" target="_blank"><img src="https://seleniumbase.github.io/cdn/gif/demo_page_5.gif" width="480" alt="SeleniumBase Example" title="SeleniumBase Example" /></a></p>
226
+
227
+ > Easy to type, click, select, toggle, drag & drop, and more.
228
+
229
+ (For more examples, see the <a href="https://github.com/seleniumbase/SeleniumBase/blob/master/examples/ReadMe.md">SeleniumBase/examples/</a> folder.)
230
+
231
+ --------
232
+
233
+ <p align="left"><a href="https://github.com/seleniumbase/SeleniumBase/"><img src="https://seleniumbase.github.io/cdn/img/super_logo_sb3.png" alt="SeleniumBase" title="SeleniumBase" width="232" /></a></p>
234
+
235
+ <blockquote>
236
+ <p dir="auto"><strong>Explore the README:</strong></p>
237
+ <ul dir="auto">
238
+ <li><a href="#install_seleniumbase" ><strong>Get Started / Installation</strong></a></li>
239
+ <li><a href="#basic_example_and_usage"><strong>Basic Example / Usage</strong></a></li>
240
+ <li><a href="#common_methods" ><strong>Common Test Methods</strong></a></li>
241
+ <li><a href="#fun_facts" ><strong>Fun Facts / Learn More</strong></a></li>
242
+ <li><a href="#demo_mode_and_debugging"><strong>Demo Mode / Debugging</strong></a></li>
243
+ <li><a href="#command_line_options" ><strong>Command-line Options</strong></a></li>
244
+ <li><a href="#directory_configuration"><strong>Directory Configuration</strong></a></li>
245
+ <li><a href="#seleniumbase_dashboard" ><strong>SeleniumBase Dashboard</strong></a></li>
246
+ <li><a href="#creating_visual_reports"><strong>Generating Test Reports</strong></a></li>
247
+ </ul>
248
+ </blockquote>
249
+
143
250
  --------
144
251
 
145
252
  <details>
146
253
  <summary> ▶️ How is <b>SeleniumBase</b> different from raw Selenium? (<b>click to expand</b>)</summary>
147
254
  <div>
148
255
 
149
- <p>💡 SeleniumBase is a Python framework for browser automation and testing. SeleniumBase uses <a href="https://www.w3.org/TR/webdriver2/#endpoints" target="_blank">Selenium/WebDriver</a> APIs, and incorporates test-runners such as <code>pytest</code>, <code>nosetests</code>, and <code>behave</code> to provide organized structure, test discovery, test execution, test state (<i>eg. passed, failed, or skipped</i>), and command-line options for changing default settings (<i>such as choosing the browser to use</i>). With raw Selenium, you would need to set up your own options-parser for configuring tests from the command-line.</p>
256
+ <p>💡 SeleniumBase is a Python framework for browser automation and testing. SeleniumBase uses <a href="https://www.w3.org/TR/webdriver2/#endpoints" target="_blank">Selenium/WebDriver</a> APIs and incorporates test-runners such as <code translate="no">pytest</code>, <code translate="no">pynose</code>, and <code translate="no">behave</code> to provide organized structure, test discovery, test execution, test state (<i>eg. passed, failed, or skipped</i>), and command-line options for changing default settings (<i>eg. browser selection</i>). With raw Selenium, you would need to set up your own options-parser for configuring tests from the command-line.</p>
257
+
258
+ <p>💡 SeleniumBase's driver manager gives you more control over automatic driver downloads. (Use <code translate="no">--driver-version=VER</code> with your <code translate="no">pytest</code> run command to specify the version.) By default, SeleniumBase will download a driver version that matches your major browser version if not set.</p>
150
259
 
151
- <p>💡 With raw Selenium, commands that use selectors need to specify the type of selector (eg. <code>"css selector", "button#myButton"</code>). With SeleniumBase, there's auto-detection between CSS Selectors and XPath, which means you don't need to specify the type of selector in your commands (<i>but optionally you could</i>).</p>
260
+ <p>💡 SeleniumBase automatically detects between CSS Selectors and XPath, which means you don't need to specify the type of selector in your commands (<i>but optionally you could</i>).</p>
152
261
 
153
- <p>💡 SeleniumBase methods often perform multiple actions in a single method call. For example, <code>self.type(selector,text)</code> does the following:<br />1. Waits for the element to be visible.<br />2. Waits for the element to be interactive.<br />3. Clears the text field.<br />4. Types in the new text.<br />5. Presses Enter/Submit if the text ends in "\n".<br />With raw Selenium, those actions require multiple method calls.</p>
262
+ <p>💡 SeleniumBase methods often perform multiple actions in a single method call. For example, <code translate="no">self.type(selector, text)</code> does the following:<br />1. Waits for the element to be visible.<br />2. Waits for the element to be interactive.<br />3. Clears the text field.<br />4. Types in the new text.<br />5. Presses Enter/Submit if the text ends in <code translate="no">"\n"</code>.<br />With raw Selenium, those actions require multiple method calls.</p>
154
263
 
155
264
  <p>💡 SeleniumBase uses default timeout values when not set:<br />
156
- ✅<code>self.click("button")</code><br />
265
+ ✅ <code translate="no">self.click("button")</code><br />
157
266
  With raw Selenium, methods would fail instantly (<i>by default</i>) if an element needed more time to load:<br />
158
- ❌<code>self.driver.find_element(by="css selector", value="button").click()</code><br />
267
+ ❌ <code translate="no">self.driver.find_element(by="css selector", value="button").click()</code><br />
159
268
  (Reliable code is better than unreliable code.)</p>
160
269
 
161
270
  <p>💡 SeleniumBase lets you change the explicit timeout values of methods:<br />
162
- ✅<code>self.click("button",timeout=10)</code><br />
271
+ ✅ <code translate="no">self.click("button", timeout=10)</code><br />
163
272
  With raw Selenium, that requires more code:<br />
164
- ❌<code>WebDriverWait(driver,10).until(EC.element_to_be_clickable("css selector", "button")).click()</code><br />
273
+ ❌ <code translate="no">WebDriverWait(driver, 10).until(EC.element_to_be_clickable("css selector", "button")).click()</code><br />
165
274
  (Simple code is better than complex code.)</p>
166
275
 
167
276
  <p>💡 SeleniumBase gives you clean error output when a test fails. With raw Selenium, error messages can get very messy.</p>
168
277
 
169
- <p>💡 SeleniumBase gives you the option to generate a dashboard and reports for tests. It also saves screenshots from failing tests to the <code>./latest_logs/</code> folder. Raw <a href="https://www.selenium.dev/documentation/webdriver/" target="_blank">Selenium</a> does not have these options out-of-the-box.</p>
278
+ <p>💡 SeleniumBase gives you the option to generate a dashboard and reports for tests. It also saves screenshots from failing tests to the <code translate="no">./latest_logs/</code> folder. Raw <a href="https://www.selenium.dev/documentation/webdriver/" translate="no" target="_blank">Selenium</a> does not have these options out-of-the-box.</p>
279
+
280
+ <p>💡 SeleniumBase includes desktop GUI apps for running tests, such as <a href="https://github.com/seleniumbase/SeleniumBase/blob/master/help_docs/commander.md" translate="no">SeleniumBase Commander</a> for <code translate="no">pytest</code> and <a href="https://github.com/seleniumbase/SeleniumBase/blob/master/examples/behave_bdd/ReadMe.md" translate="no">SeleniumBase Behave GUI</a> for <code translate="no">behave</code>.</p>
170
281
 
171
- <p>💡 SeleniumBase includes desktop GUI apps for running tests, such as <b>SeleniumBase Commander</b> for <code>pytest</code>, and <b>SeleniumBase Behave GUI.</b></p>
282
+ <p>💡 SeleniumBase has its own <a href="https://github.com/seleniumbase/SeleniumBase/blob/master/help_docs/recorder_mode.md">Recorder / Test Generator</a> for creating tests from manual browser actions.</p>
172
283
 
173
- <p>💡 SeleniumBase has its own Recorder & Test Generator that can create tests from manual browser actions. SeleniumBase also has many other useful tools and console scripts for getting things done quickly. (<i>See the documentation for more details!</i>)</p>
284
+ <p>💡 SeleniumBase comes with <a href="https://github.com/seleniumbase/SeleniumBase/blob/master/help_docs/case_plans.md">test case management software, ("CasePlans")</a>, for organizing tests and step descriptions.</p>
285
+
286
+ <p>💡 SeleniumBase includes tools for <a href="https://github.com/seleniumbase/SeleniumBase/blob/master/examples/chart_maker/ReadMe.md">building data apps, ("ChartMaker")</a>, which can generate JavaScript from Python.</p>
174
287
 
175
288
  </div>
176
289
  </details>
177
290
 
178
291
  --------
179
292
 
180
- <details>
181
- <summary> ▶️ Learn about different ways of writing tests (<b>click to expand</b>)</summary>
182
- <div>
293
+ <p>📚 <b>Learn about different ways of writing tests:</b></p>
183
294
 
184
- <p align="left">📘📝 An example test with the <b>BaseCase</b> class. Runs with <b><a href="https://docs.pytest.org/en/latest/how-to/usage.html">pytest</a></b> or <b>nosetests</b>. (<a href="https://github.com/seleniumbase/SeleniumBase/blob/master/examples/ReadMe.md">Learn more</a>)</p>
295
+ <p align="left">📗📝 Here's <a href="https://github.com/seleniumbase/SeleniumBase/blob/master/examples/test_simple_login.py">test_simple_login.py</a>, which uses <code translate="no"><a href="https://github.com/seleniumbase/SeleniumBase/blob/master/seleniumbase/fixtures/base_case.py">BaseCase</a></code> class inheritance, and runs with <a href="https://docs.pytest.org/en/latest/how-to/usage.html">pytest</a> or <a href="https://github.com/mdmintz/pynose">pynose</a>. (Use <code translate="no">self.driver</code> to access Selenium's raw <code translate="no">driver</code>.)</p>
185
296
 
186
297
  ```python
187
298
  from seleniumbase import BaseCase
299
+ BaseCase.main(__name__, __file__)
188
300
 
189
- class TestMFALogin(BaseCase):
190
- def test_mfa_login(self):
191
- self.open("https://seleniumbase.io/realworld/login")
301
+ class TestSimpleLogin(BaseCase):
302
+ def test_simple_login(self):
303
+ self.open("seleniumbase.io/simple/login")
192
304
  self.type("#username", "demo_user")
193
305
  self.type("#password", "secret_pass")
194
- self.enter_mfa_code("#totpcode", "GAXG2MTEOR3DMMDG") # 6-digit
306
+ self.click('a:contains("Sign in")')
195
307
  self.assert_exact_text("Welcome!", "h1")
196
308
  self.assert_element("img#image1")
197
- self.click('a:contains("This Page")')
198
- self.save_screenshot_to_logs()
309
+ self.highlight("#image1")
310
+ self.click_link("Sign out")
311
+ self.assert_text("signed out", "#top_message")
199
312
  ```
200
313
 
201
- <p align="left">📗📝 An example test with the <b><code>sb</code></b> <code>pytest</code> fixture. Runs with <b><a href="https://docs.pytest.org/en/latest/how-to/usage.html">pytest</a></b>.</p>
314
+ <p align="left">📘📝 Here's <a href="https://github.com/seleniumbase/SeleniumBase/blob/master/examples/raw_login_sb.py">raw_login_sb.py</a>, which uses the <b><code translate="no">SB</code></b> Context Manager. Runs with pure <code translate="no">python</code>. (Use <code translate="no">sb.driver</code> to access Selenium's raw <code translate="no">driver</code>.)</p>
202
315
 
203
316
  ```python
204
- def test_mfa_login(sb):
205
- sb.open("https://seleniumbase.io/realworld/login")
317
+ from seleniumbase import SB
318
+
319
+ with SB() as sb:
320
+ sb.open("seleniumbase.io/simple/login")
206
321
  sb.type("#username", "demo_user")
207
322
  sb.type("#password", "secret_pass")
208
- sb.enter_mfa_code("#totpcode", "GAXG2MTEOR3DMMDG") # 6-digit
323
+ sb.click('a:contains("Sign in")')
209
324
  sb.assert_exact_text("Welcome!", "h1")
210
325
  sb.assert_element("img#image1")
211
- sb.click('a:contains("This Page")')
212
- sb.save_screenshot_to_logs()
326
+ sb.highlight("#image1")
327
+ sb.click_link("Sign out")
328
+ sb.assert_text("signed out", "#top_message")
213
329
  ```
214
330
 
215
- <p align="left">📙📝 An example test with the <b><code>SB</code></b> Context Manager. Runs with pure <b><code>python</code></b>.</p>
331
+ <p align="left">📙📝 Here's <a href="https://github.com/seleniumbase/SeleniumBase/blob/master/examples/raw_login_driver.py">raw_login_driver.py</a>, which uses the <b><code translate="no">Driver</code></b> Manager. Runs with pure <code translate="no">python</code>. (The <code>driver</code> is an improved version of Selenium's raw <code translate="no">driver</code>, with more methods.)</p>
216
332
 
217
333
  ```python
218
- from seleniumbase import SB
219
-
220
- with SB() as sb: # By default, browser="chrome" if not set.
221
- sb.open("https://seleniumbase.io/realworld/login")
222
- sb.type("#username", "demo_user")
223
- sb.type("#password", "secret_pass")
224
- sb.enter_mfa_code("#totpcode", "GAXG2MTEOR3DMMDG") # 6-digit
225
- sb.assert_text("Welcome!", "h1")
226
- sb.highlight("img#image1") # A fancier assert_element() call
227
- sb.click('a:contains("This Page")') # Use :contains() on any tag
228
- sb.click_link("Sign out") # Link must be "a" tag. Not "button".
229
- sb.assert_element('a:contains("Sign in")')
230
- sb.assert_exact_text("You have been signed out!", "#top_message")
334
+ from seleniumbase import Driver
335
+
336
+ driver = Driver()
337
+ try:
338
+ driver.open("seleniumbase.io/simple/login")
339
+ driver.type("#username", "demo_user")
340
+ driver.type("#password", "secret_pass")
341
+ driver.click('a:contains("Sign in")')
342
+ driver.assert_exact_text("Welcome!", "h1")
343
+ driver.assert_element("img#image1")
344
+ driver.highlight("#image1")
345
+ driver.click_link("Sign out")
346
+ driver.assert_text("signed out", "#top_message")
347
+ finally:
348
+ driver.quit()
231
349
  ```
232
350
 
233
- <p align="left">📕📝 An example test with <b>behave-BDD</b> <a href="https://behave.readthedocs.io/en/stable/gherkin.html" target="_blank">Gherkin</a> structure. Runs with <b><code>behave</code></b>. (<a href="https://github.com/seleniumbase/SeleniumBase/blob/master/examples/behave_bdd/ReadMe.md">Learn more</a>)</p>
234
-
235
- ```gherkin
236
- Feature: SeleniumBase scenarios for the RealWorld App
237
-
238
- Scenario: Verify RealWorld App
239
- Given Open "seleniumbase.io/realworld/login"
240
- When Type "demo_user" into "#username"
241
- And Type "secret_pass" into "#password"
242
- And Do MFA "GAXG2MTEOR3DMMDG" into "#totpcode"
243
- Then Assert exact text "Welcome!" in "h1"
244
- And Assert element "img#image1"
245
- And Click 'a:contains("This Page")'
246
- And Save screenshot to logs
247
- ```
248
-
249
- </div>
250
- </details>
251
-
252
351
  --------
253
352
 
254
353
  <a id="python_installation"></a>
255
354
  <h2><img src="https://seleniumbase.github.io/cdn/img/python_logo.png" title="SeleniumBase" width="42" /> Set up Python & Git:</h2>
256
355
 
356
+ <a href="https://www.python.org/downloads/"><img src="https://img.shields.io/pypi/pyversions/seleniumbase.svg?color=FACE42" title="Supported Python Versions" /></a>
357
+
257
358
  🔵 Add <b><a href="https://www.python.org/downloads/">Python</a></b> and <b><a href="https://git-scm.com/">Git</a></b> to your System PATH.
258
359
 
259
360
  🔵 Using a <a href="https://github.com/seleniumbase/SeleniumBase/blob/master/help_docs/virtualenv_instructions.md">Python virtual env</a> is recommended.
@@ -261,9 +362,19 @@ Feature: SeleniumBase scenarios for the RealWorld App
261
362
  <a id="install_seleniumbase"></a>
262
363
  <h2><img src="https://seleniumbase.github.io/img/logo7.png" title="SeleniumBase" width="32" /> Install SeleniumBase:</h2>
263
364
 
264
- **You can install ``seleniumbase`` from [GitHub](https://github.com/seleniumbase/SeleniumBase) or [PyPI](https://pypi.org/project/seleniumbase/):**
365
+ **You can install ``seleniumbase`` from [PyPI](https://pypi.org/project/seleniumbase/) or [GitHub](https://github.com/seleniumbase/SeleniumBase):**
265
366
 
266
- 🔵 **Installing ``seleniumbase`` from a GitHub clone:**
367
+ 🔵 **How to install ``seleniumbase`` from PyPI:**
368
+
369
+ ```bash
370
+ pip install seleniumbase
371
+ ```
372
+
373
+ * (Add ``--upgrade`` OR ``-U`` to upgrade SeleniumBase.)
374
+ * (Add ``--force-reinstall`` to upgrade indirect packages.)
375
+ * (Use ``pip3`` if multiple versions of Python are present.)
376
+
377
+ 🔵 **How to install ``seleniumbase`` from a GitHub clone:**
267
378
 
268
379
  ```bash
269
380
  git clone https://github.com/seleniumbase/SeleniumBase.git
@@ -271,86 +382,92 @@ cd SeleniumBase/
271
382
  pip install -e .
272
383
  ```
273
384
 
274
- **To upgrade an existing install from a GitHub clone:**
385
+ 🔵 **How to upgrade an existing install from a GitHub clone:**
275
386
 
276
387
  ```bash
277
388
  git pull
278
389
  pip install -e .
279
390
  ```
280
391
 
281
- 🔵 **Installing ``seleniumbase`` from PyPI:**
392
+ 🔵 **Type ``seleniumbase`` or ``sbase`` to verify that SeleniumBase was installed successfully:**
282
393
 
283
394
  ```bash
284
- pip install seleniumbase
285
- ```
286
-
287
- * (Add ``--upgrade`` OR ``-U`` to upgrade SeleniumBase.)
288
- * (Add ``--force-reinstall`` to upgrade indirect libraries.)
289
- * (Use ``pip3`` if multiple versions of Python are present.)
395
+ ___ _ _ ___
396
+ / __| ___| |___ _ _ (_)_ _ _ __ | _ ) __ _ ______
397
+ \__ \/ -_) / -_) ' \| | \| | ' \ | _ \/ _` (_-< -_)
398
+ |___/\___|_\___|_||_|_|\_,_|_|_|_\|___/\__,_/__|___|
399
+ ----------------------------------------------------
400
+
401
+ ╭──────────────────────────────────────────────────╮
402
+ │ * USAGE: "seleniumbase [COMMAND] [PARAMETERS]" │
403
+ │ * OR: "sbase [COMMAND] [PARAMETERS]" │
404
+ │ │
405
+ │ COMMANDS: PARAMETERS / DESCRIPTIONS: │
406
+ │ get / install [DRIVER_NAME] [OPTIONS] │
407
+ │ methods (List common Python methods) │
408
+ │ options (List common pytest options) │
409
+ │ behave-options (List common behave options) │
410
+ │ gui / commander [OPTIONAL PATH or TEST FILE] │
411
+ │ behave-gui (SBase Commander for Behave) │
412
+ │ caseplans [OPTIONAL PATH or TEST FILE] │
413
+ │ mkdir [DIRECTORY] [OPTIONS] │
414
+ │ mkfile [FILE.py] [OPTIONS] │
415
+ │ mkrec / codegen [FILE.py] [OPTIONS] │
416
+ │ recorder (Open Recorder Desktop App.) │
417
+ │ record (If args: mkrec. Else: App.) │
418
+ │ mkpres [FILE.py] [LANG] │
419
+ │ mkchart [FILE.py] [LANG] │
420
+ │ print [FILE] [OPTIONS] │
421
+ │ translate [SB_FILE.py] [LANG] [ACTION] │
422
+ │ convert [WEBDRIVER_UNITTEST_FILE.py] │
423
+ │ extract-objects [SB_FILE.py] │
424
+ │ inject-objects [SB_FILE.py] [OPTIONS] │
425
+ │ objectify [SB_FILE.py] [OPTIONS] │
426
+ │ revert-objects [SB_FILE.py] [OPTIONS] │
427
+ │ encrypt / obfuscate │
428
+ │ decrypt / unobfuscate │
429
+ │ proxy (Start a basic proxy server) │
430
+ │ download server (Get Selenium Grid JAR file) │
431
+ │ grid-hub [start|stop] [OPTIONS] │
432
+ │ grid-node [start|stop] --hub=[HOST/IP] │
433
+ │ │
434
+ │ * EXAMPLE => "sbase get chromedriver stable" │
435
+ │ * For command info => "sbase help [COMMAND]" │
436
+ │ * For info on all commands => "sbase --help" │
437
+ ╰──────────────────────────────────────────────────╯
438
+ ```
439
+
440
+ <h3>🔵 Downloading webdrivers:</h3>
441
+
442
+ ✅ SeleniumBase automatically downloads webdrivers as needed, such as ``chromedriver``.
290
443
 
291
- **To upgrade an existing install from PyPI:**
444
+ <div></div>
445
+ <details>
446
+ <summary> ▶️ Here's sample output from a chromedriver download. (<b>click to expand</b>)</summary>
292
447
 
293
448
  ```bash
294
- pip install -U seleniumbase
295
- ```
449
+ *** chromedriver to download = 131.0.6778.108 (Latest Stable)
296
450
 
297
- 🔵 Type ``seleniumbase`` or ``sbase`` to verify that SeleniumBase was installed successfully:
451
+ Downloading chromedriver-mac-arm64.zip from:
452
+ https://storage.googleapis.com/chrome-for-testing-public/131.0.6778.108/mac-arm64/chromedriver-mac-arm64.zip ...
453
+ Download Complete!
298
454
 
299
- ```bash
300
- ______ __ _ ____
301
- / ____/__ / /__ ____ (_)_ ______ ___ / _ \____ ________
302
- \__ \/ _ \/ / _ \/ __ \/ / / / / __ `__ \ / /_) / __ \/ ___/ _ \
303
- ___/ / __/ / __/ / / / / /_/ / / / / / // /_) / (_/ /__ / __/
304
- /____/\___/_/\___/_/ /_/_/\__,_/_/ /_/ /_//_____/\__,_/____/\___/
305
- ------------------------------------------------------------------
306
-
307
- * USAGE: "seleniumbase [COMMAND] [PARAMETERS]"
308
- * OR: "sbase [COMMAND] [PARAMETERS]"
309
-
310
- COMMANDS:
311
- get / install [DRIVER] [OPTIONS]
312
- methods (List common Python methods)
313
- options (List common pytest options)
314
- behave-options (List common behave options)
315
- gui / commander [OPTIONAL PATH or TEST FILE]
316
- behave-gui (SBase Commander for Behave)
317
- caseplans [OPTIONAL PATH or TEST FILE]
318
- mkdir [DIRECTORY] [OPTIONS]
319
- mkfile [FILE.py] [OPTIONS]
320
- mkrec / codegen [FILE.py] [OPTIONS]
321
- recorder (Open Recorder Desktop App.)
322
- record (If args: mkrec. Else: App.)
323
- mkpres [FILE.py] [LANG]
324
- mkchart [FILE.py] [LANG]
325
- print [FILE] [OPTIONS]
326
- translate [SB_FILE.py] [LANG] [ACTION]
327
- convert [WEBDRIVER_UNITTEST_FILE.py]
328
- extract-objects [SB_FILE.py]
329
- inject-objects [SB_FILE.py] [OPTIONS]
330
- objectify [SB_FILE.py] [OPTIONS]
331
- revert-objects [SB_FILE.py] [OPTIONS]
332
- encrypt / obfuscate
333
- decrypt / unobfuscate
334
- download server (Get Selenium Grid JAR file)
335
- grid-hub [start|stop] [OPTIONS]
336
- grid-node [start|stop] --hub=[HOST/IP]
337
- * (EXAMPLE: "sbase get chromedriver latest") *
338
-
339
- Type "sbase help [COMMAND]" for specific command info.
340
- For info on all commands, type: "seleniumbase --help".
341
- Use "pytest" for running tests.
342
- ```
343
-
344
-
345
- <h3><img src="https://seleniumbase.github.io/img/logo7.png" title="SeleniumBase" width="32" /> Downloading web drivers:</h3>
346
-
347
- ✅ SeleniumBase automatically downloads web drivers as needed, such as ``chromedriver``, ``edgedriver``, and ``geckodriver``.
348
-
349
- ✅ To manually download a webdriver, see [Console Scripts](https://seleniumbase.io/seleniumbase/console_scripts/ReadMe/) OR [Webdriver Installation](https://seleniumbase.io/help_docs/webdriver_installation/).
455
+ Extracting ['chromedriver'] from chromedriver-mac-arm64.zip ...
456
+ Unzip Complete!
457
+
458
+ The file [chromedriver] was saved to:
459
+ ~/github/SeleniumBase/seleniumbase/drivers/
460
+ chromedriver
461
+
462
+ Making [chromedriver 131.0.6778.108] executable ...
463
+ [chromedriver 131.0.6778.108] is now ready for use!
464
+ ```
465
+
466
+ </details>
350
467
 
351
468
 
352
469
  <a id="basic_example_and_usage"></a>
353
- <h3><img src="https://seleniumbase.github.io/img/logo7.png" title="SeleniumBase" width="32" /> Basic Example & Usage:</h3>
470
+ <h2><img src="https://seleniumbase.github.io/img/logo7.png" title="SeleniumBase" width="32" /> Basic Example / Usage:</h2>
354
471
 
355
472
  🔵 If you've cloned SeleniumBase, you can run tests from the [examples/](https://github.com/seleniumbase/SeleniumBase/tree/master/examples) folder.
356
473
 
@@ -361,14 +478,13 @@ cd examples/
361
478
  pytest my_first_test.py
362
479
  ```
363
480
 
364
- > (Uses ``--chrome`` by default.)
365
-
366
- <a href="https://github.com/seleniumbase/SeleniumBase/blob/master/examples/my_first_test.py"><img src="https://seleniumbase.github.io/cdn/gif/swag_labs_4.gif" alt="SeleniumBase Test" title="SeleniumBase Test" width="480" /></a>
481
+ <a href="https://github.com/seleniumbase/SeleniumBase/blob/master/examples/my_first_test.py"><img src="https://seleniumbase.github.io/cdn/gif/fast_swag_2.gif" alt="SeleniumBase Test" title="SeleniumBase Test" width="480" /></a>
367
482
 
368
- <p align="left"><b>Here's the code for <a href="https://github.com/seleniumbase/SeleniumBase/blob/master/examples/my_first_test.py">my_first_test.py</a>:</b></p>
483
+ <p align="left"><b>Here's the full code for <a href="https://github.com/seleniumbase/SeleniumBase/blob/master/examples/my_first_test.py">my_first_test.py</a>:</b></p>
369
484
 
370
485
  ```python
371
486
  from seleniumbase import BaseCase
487
+ BaseCase.main(__name__, __file__)
372
488
 
373
489
  class MyTestClass(BaseCase):
374
490
  def test_swag_labs(self):
@@ -376,20 +492,21 @@ class MyTestClass(BaseCase):
376
492
  self.type("#user-name", "standard_user")
377
493
  self.type("#password", "secret_sauce\n")
378
494
  self.assert_element("div.inventory_list")
379
- self.assert_text("PRODUCTS", "span.title")
495
+ self.assert_exact_text("Products", "span.title")
380
496
  self.click('button[name*="backpack"]')
381
497
  self.click("#shopping_cart_container a")
382
- self.assert_text("YOUR CART", "span.title")
498
+ self.assert_exact_text("Your Cart", "span.title")
383
499
  self.assert_text("Backpack", "div.cart_item")
384
500
  self.click("button#checkout")
385
501
  self.type("#first-name", "SeleniumBase")
386
502
  self.type("#last-name", "Automation")
387
503
  self.type("#postal-code", "77123")
388
504
  self.click("input#continue")
389
- self.assert_text("CHECKOUT: OVERVIEW")
505
+ self.assert_text("Checkout: Overview")
390
506
  self.assert_text("Backpack", "div.cart_item")
507
+ self.assert_text("29.99", "div.inventory_item_price")
391
508
  self.click("button#finish")
392
- self.assert_exact_text("THANK YOU FOR YOUR ORDER", "h2")
509
+ self.assert_exact_text("Thank you for your order!", "h2")
393
510
  self.assert_element('img[alt="Pony Express"]')
394
511
  self.js_click("a#logout_sidebar_link")
395
512
  self.assert_element("div#login_button_container")
@@ -401,7 +518,7 @@ class MyTestClass(BaseCase):
401
518
 
402
519
 
403
520
  <a id="common_methods"></a>
404
- <h3><img src="https://seleniumbase.github.io/img/logo7.png" title="SeleniumBase" width="32" /> Here are some common SeleniumBase methods that you might find in tests:</h3>
521
+ <h3><img src="https://seleniumbase.github.io/img/logo7.png" title="SeleniumBase" width="32" /> Here are some common SeleniumBase methods:</h3>
405
522
 
406
523
  ```python
407
524
  self.open(url) # Navigate the browser window to the URL.
@@ -432,6 +549,7 @@ self.sleep(seconds) # Do nothing for the given amount of time.
432
549
  self.save_screenshot(name) # Save a screenshot in .png format.
433
550
  self.assert_element(selector) # Verify the element is visible.
434
551
  self.assert_text(text, selector) # Verify text in the element.
552
+ self.assert_exact_text(text, selector) # Verify text is exact.
435
553
  self.assert_title(title) # Verify the title of the web page.
436
554
  self.assert_downloaded_file(file) # Verify file was downloaded.
437
555
  self.assert_no_404_errors() # Verify there are no broken links.
@@ -446,93 +564,122 @@ self.assert_no_js_errors() # Verify there are no JS errors.
446
564
 
447
565
  <p>✅ SeleniumBase automatically handles common <a href="https://www.selenium.dev/documentation/webdriver/" target="_blank">WebDriver</a> actions such as launching web browsers before tests, saving screenshots during failures, and closing web browsers after tests.</p>
448
566
 
449
- <p>✅ SeleniumBase lets you <a href="https://github.com/seleniumbase/SeleniumBase/blob/master/help_docs/customizing_test_runs.md">customize test runs from the command-line</a>.</p>
567
+ <p>✅ SeleniumBase lets you customize tests via <a href="https://github.com/seleniumbase/SeleniumBase/blob/master/help_docs/customizing_test_runs.md">command-line options</a>.</p>
450
568
 
451
569
  <p>✅ SeleniumBase uses simple syntax for commands. Example:</p>
452
570
 
453
571
  ```python
454
- self.type("input", "dogs\n")
572
+ self.type("input", "dogs\n") # (The "\n" presses ENTER)
455
573
  ```
456
574
 
457
- SeleniumBase tests can be run with <code>pytest</code> or <code>nosetests</code>. (There's also a <a href="https://github.com/seleniumbase/SeleniumBase/blob/master/examples/behave_bdd/ReadMe.md">behave BDD</a> format.)
575
+ 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>.
458
576
 
459
577
  ```bash
460
- pytest my_first_test.py --chrome
578
+ pytest coffee_cart_tests.py --rs
579
+ pytest test_sb_fixture.py --demo
580
+ pytest test_suite.py --rs --html=report.html --dashboard
581
+
582
+ pynose basic_test.py --mobile
583
+ pynose test_suite.py --headless --report --show-report
584
+
585
+ python raw_sb.py
586
+ python raw_test_scripts.py
461
587
 
462
- nosetests test_suite.py --firefox
588
+ behave realworld.feature
589
+ behave calculator.feature -D rs -D dashboard
463
590
  ```
464
591
 
465
- <p>✅ <code>pytest</code> includes automatic test discovery. If you don't specify a specific file or folder to run, <code>pytest</code> will automatically search through all subdirectories for tests to run based on the following criteria:</p>
592
+ <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>
466
593
 
467
594
  * Python files that start with ``test_`` or end with ``_test.py``.
468
595
  * Python methods that start with ``test_``.
469
596
 
470
- 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``, which triggers autodiscovery.
597
+ 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.
471
598
 
472
- <p>✅ You can do a pre-flight check to see which tests would get discovered by <code>pytest</code> before the real flight:</p>
599
+ <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>
473
600
 
474
601
  ```bash
475
- pytest --collect-only -q
602
+ pytest --co -q
476
603
  ```
477
604
 
478
- <p>✅ You can be more specific when calling <code>pytest</code> on a file:</p>
605
+ <p>✅ You can be more specific when calling <code translate="no">pytest</code> or <code translate="no">pynose</code> on a file:</p>
479
606
 
480
607
  ```bash
481
608
  pytest [FILE_NAME.py]::[CLASS_NAME]::[METHOD_NAME]
482
609
 
483
- nosetests [FILE_NAME.py]:[CLASS_NAME].[METHOD_NAME]
610
+ pynose [FILE_NAME.py]:[CLASS_NAME].[METHOD_NAME]
484
611
  ```
485
612
 
486
- <p>✅ No More Flaky Tests! SeleniumBase methods automatically wait for page elements to finish loading before interacting with them (<i>up to a timeout limit</i>). This means <b>you no longer need random <span><code>time.sleep()</code></span> statements</b> in your scripts.</p>
613
+ <p>✅ No More Flaky Tests! SeleniumBase methods automatically wait for page elements to finish loading before interacting with them (<i>up to a timeout limit</i>). This means <b>you no longer need random <span><code translate="no">time.sleep()</code></span> statements</b> in your scripts.</p>
487
614
  <img src="https://img.shields.io/badge/Flaky%20Tests%3F-%20NO%21-11BBDD.svg" alt="NO MORE FLAKY TESTS!" />
488
615
 
489
616
  ✅ SeleniumBase supports all major browsers and operating systems:
490
617
  <p><b>Browsers:</b> Chrome, Edge, Firefox, and Safari.</p>
491
- <p><b>Systems: </b>Linux/Ubuntu, macOS, and Windows.</p>
618
+ <p><b>Systems:</b> Linux/Ubuntu, macOS, and Windows.</p>
492
619
 
493
620
  ✅ SeleniumBase works on all popular CI/CD platforms:
494
621
  <p><a href="https://github.com/seleniumbase/SeleniumBase/blob/master/integrations/github/workflows/ReadMe.md"><img alt="GitHub Actions integration" src="https://img.shields.io/badge/GitHub_Actions-12B2C2.svg?logo=GitHubActions&logoColor=CFFFC2" /></a> <a href="https://github.com/seleniumbase/SeleniumBase/blob/master/integrations/azure/jenkins/ReadMe.md"><img alt="Jenkins integration" src="https://img.shields.io/badge/Jenkins-32B242.svg?logo=jenkins&logoColor=white" /></a> <a href="https://github.com/seleniumbase/SeleniumBase/blob/master/integrations/azure/azure_pipelines/ReadMe.md"><img alt="Azure integration" src="https://img.shields.io/badge/Azure-2288EE.svg?logo=AzurePipelines&logoColor=white" /></a> <a href="https://github.com/seleniumbase/SeleniumBase/blob/master/integrations/google_cloud/ReadMe.md"><img alt="Google Cloud integration" src="https://img.shields.io/badge/Google_Cloud-11CAE8.svg?logo=GoogleCloud&logoColor=EE0066" /></a> <a href="#utilizing_advanced_features"><img alt="AWS integration" src="https://img.shields.io/badge/AWS-4488DD.svg?logo=AmazonAWS&logoColor=FFFF44" /></a> <a href="https://en.wikipedia.org/wiki/Personal_computer" target="_blank"><img alt="Your Computer" src="https://img.shields.io/badge/💻_Your_Computer-44E6E6.svg" /></a></p>
495
622
 
496
- <p>✅ SeleniumBase includes an automated/manual hybrid solution called <b><a href="https://github.com/seleniumbase/SeleniumBase/blob/master/examples/master_qa/ReadMe.md">MasterQA</a></b>, which speeds up manual testing by having automation perform all the browser actions while the manual tester handles validation.</p>
623
+ <p>✅ SeleniumBase includes an automated/manual hybrid solution called <b><a href="https://github.com/seleniumbase/SeleniumBase/blob/master/examples/master_qa/ReadMe.md">MasterQA</a></b> to speed up manual testing with automation while manual testers handle validation.</p>
624
+
625
+ <p>✅ SeleniumBase supports <a href="https://github.com/seleniumbase/SeleniumBase/tree/master/examples/offline_examples">running tests while offline</a> (<i>assuming webdrivers have previously been downloaded when online</i>).</p>
497
626
 
498
627
  <p>✅ For a full list of SeleniumBase features, <a href="https://github.com/seleniumbase/SeleniumBase/blob/master/help_docs/features_list.md">Click Here</a>.</p>
499
628
 
500
629
 
501
- <a id="detailed_instructions"></a>
502
- <h2><img src="https://seleniumbase.github.io/img/logo7.png" title="SeleniumBase" width="32" /> Detailed Instructions:</h2>
630
+ <a id="demo_mode_and_debugging"></a>
631
+ <h2><img src="https://seleniumbase.github.io/img/logo7.png" title="SeleniumBase" width="32" /> Demo Mode / Debugging:</h2>
503
632
 
504
- <a id="seleniumbase_demo_mode"></a>
505
- 🔵 <b>Demo Mode</b> helps you see what a test is doing. If a test is moving too fast for your eyes, run it in <b>Demo Mode</b>, which pauses the browser briefly between actions, highlights page elements being acted on, and displays assertions:
633
+ 🔵 <b>Demo Mode</b> helps you see what a test is doing. If a test is moving too fast for your eyes, run it in <b>Demo Mode</b> to pause the browser briefly between actions, highlight page elements being acted on, and display assertions:
506
634
 
507
635
  ```bash
508
636
  pytest my_first_test.py --demo
509
637
  ```
510
638
 
511
- 🔵 You can use the following calls in your scripts to help you debug issues:
639
+ 🔵 ``time.sleep(seconds)`` can be used to make a test wait at a specific spot:
640
+
641
+ ```python
642
+ import time; time.sleep(3) # Do nothing for 3 seconds.
643
+ ```
644
+
645
+ 🔵 **Debug Mode** with Python's built-in **[pdb](https://docs.python.org/3/library/pdb.html)** library helps you debug tests:
512
646
 
513
647
  ```python
514
- import time; time.sleep(5) # Makes the test wait and do nothing for 5 seconds.
515
- import pdb; pdb.set_trace() # Enter debugging mode. n = next, c = continue, s = step.
516
- import pytest; pytest.set_trace() # Enter debugging mode. n = next, c = continue, s = step.
648
+ import pdb; pdb.set_trace()
649
+ import pytest; pytest.set_trace()
650
+ breakpoint() # Shortcut for "import pdb; pdb.set_trace()"
517
651
  ```
518
652
 
653
+ > (**``pdb``** commands: ``n``, ``c``, ``s``, ``u``, ``d`` => ``next``, ``continue``, ``step``, ``up``, ``down``)
654
+
519
655
  🔵 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:
520
656
 
521
657
  ```bash
522
- pytest my_first_test.py --pdb
658
+ pytest test_fail.py --pdb
659
+ ```
660
+
661
+ 🔵 To start tests in Debug Mode, add **``--trace``** as a ``pytest`` option:
662
+
663
+ ```bash
664
+ pytest test_coffee_cart.py --trace
523
665
  ```
524
666
 
525
- (**``pdb``** console commands: ``n``, ``c``, ``s`` => ``next``, ``continue``, ``step``).
667
+ <a href="https://github.com/mdmintz/pdbp"><img src="https://seleniumbase.github.io/cdn/gif/coffee_pdbp.gif" alt="SeleniumBase test with the pdbp (Pdb+) debugger" title="SeleniumBase test with the pdbp (Pdb+) debugger" /></a>
668
+
669
+
670
+ <a id="command_line_options"></a>
671
+ <h2>🔵 Command-line Options:</h2>
526
672
 
527
673
  <a id="pytest_options"></a>
528
- 🔵 Here are some useful command-line options that come with <code>pytest</code>:
674
+ Here are some useful command-line options that come with <code translate="no">pytest</code>:
529
675
 
530
676
  ```bash
531
677
  -v # Verbose mode. Prints the full name of each test and shows more details.
532
678
  -q # Quiet mode. Print fewer details in the console output when running tests.
533
679
  -x # Stop running the tests after the first failure is reached.
534
680
  --html=report.html # Creates a detailed pytest-html report after tests finish.
535
- --collect-only | --co # Show what tests would get run. (Without running them)
681
+ --co | --collect-only # Show what tests would get run. (Without running them)
682
+ --co -q # (Both options together!) - Do a dry run with full test names shown.
536
683
  -n=NUM # Multithread the tests using that many threads. (Speed up test runs!)
537
684
  -s # See print statements. (Should be on by default with pytest.ini present.)
538
685
  --junit-xml=report.xml # Creates a junit-xml report after tests finish.
@@ -542,7 +689,7 @@ pytest my_first_test.py --pdb
542
689
  ```
543
690
 
544
691
  <a id="new_pytest_options"></a>
545
- 🔵 SeleniumBase provides additional <code>pytest</code> command-line options for tests:
692
+ SeleniumBase provides additional <code translate="no">pytest</code> command-line options for tests:
546
693
 
547
694
  ```bash
548
695
  --browser=BROWSER # (The web browser to use. Default: "chrome".)
@@ -550,8 +697,6 @@ pytest my_first_test.py --pdb
550
697
  --edge # (Shortcut for "--browser=edge".)
551
698
  --firefox # (Shortcut for "--browser=firefox".)
552
699
  --safari # (Shortcut for "--browser=safari".)
553
- --cap-file=FILE # (The web browser's desired capabilities to use.)
554
- --cap-string=STRING # (The web browser's desired capabilities to use.)
555
700
  --settings-file=FILE # (Override default SeleniumBase settings.)
556
701
  --env=ENV # (Set the test env. Access with "self.env" in tests.)
557
702
  --account=STR # (Set account. Access with "self.account" in tests.)
@@ -564,11 +709,15 @@ pytest my_first_test.py --pdb
564
709
  --protocol=PROTOCOL # (The Selenium Grid protocol: http|https.)
565
710
  --server=SERVER # (The Selenium Grid server/IP used for tests.)
566
711
  --port=PORT # (The Selenium Grid port used by the test server.)
567
- --proxy=SERVER:PORT # (Connect to a proxy server:port for tests.)
568
- --proxy=USERNAME:PASSWORD@SERVER:PORT # (Use authenticated proxy server.)
569
- --proxy-bypass-list=STRING # (";"-separated hosts to bypass, Eg "*.foo.com")
712
+ --cap-file=FILE # (The web browser's desired capabilities to use.)
713
+ --cap-string=STRING # (The web browser's desired capabilities to use.)
714
+ --proxy=SERVER:PORT # (Connect to a proxy server:port as tests are running)
715
+ --proxy=USERNAME:PASSWORD@SERVER:PORT # (Use an authenticated proxy server)
716
+ --proxy-bypass-list=STRING # (";"-separated hosts to bypass, Eg "*.foo.com")
570
717
  --proxy-pac-url=URL # (Connect to a proxy server using a PAC_URL.pac file.)
571
718
  --proxy-pac-url=USERNAME:PASSWORD@URL # (Authenticated proxy with PAC URL.)
719
+ --proxy-driver # (If a driver download is needed, will use: --proxy=PROXY.)
720
+ --multi-proxy # (Allow multiple authenticated proxies when multi-threaded.)
572
721
  --agent=STRING # (Modify the web browser's User-Agent string.)
573
722
  --mobile # (Use the mobile device emulator while running tests.)
574
723
  --metrics=STRING # (Set mobile metrics: "CSSWidth,CSSHeight,PixelRatio".)
@@ -577,13 +726,18 @@ pytest my_first_test.py --pdb
577
726
  --firefox-pref=SET # (Set a Firefox preference:value set, comma-separated.)
578
727
  --extension-zip=ZIP # (Load a Chrome Extension .zip|.crx, comma-separated.)
579
728
  --extension-dir=DIR # (Load a Chrome Extension directory, comma-separated.)
729
+ --disable-features="F1,F2" # (Disable features, comma-separated, no spaces.)
580
730
  --binary-location=PATH # (Set path of the Chromium browser binary to use.)
731
+ --driver-version=VER # (Set the chromedriver or uc_driver version to use.)
581
732
  --sjw # (Skip JS Waits for readyState to be "complete" or Angular to load.)
733
+ --wfa # (Wait for AngularJS to be done loading after specific web actions.)
582
734
  --pls=PLS # (Set pageLoadStrategy on Chrome: "normal", "eager", or "none".)
583
- --headless # (Run tests in headless mode. The default arg on Linux OS.)
584
- --headless2 # (Use the new headless mode, which supports extensions.)
735
+ --headless # (The default headless mode. Linux uses this mode by default.)
736
+ --headless1 # (Use Chrome's old headless mode. Fast, but has limitations.)
737
+ --headless2 # (Use Chrome's new headless mode, which supports extensions.)
585
738
  --headed # (Run tests in headed/GUI mode on Linux OS, where not default.)
586
739
  --xvfb # (Run tests using the Xvfb virtual display server on Linux OS.)
740
+ --xvfb-metrics=STRING # (Set Xvfb display size on Linux: "Width,Height".)
587
741
  --locale=LOCALE_CODE # (Set the Language Locale Code for the web browser.)
588
742
  --interval=SECONDS # (The autoplay interval for presentations & tour steps)
589
743
  --start-page=URL # (The starting URL for the web browser when tests begin.)
@@ -597,13 +751,16 @@ pytest my_first_test.py --pdb
597
751
  --message-duration=SECONDS # (The time length for Messenger alerts.)
598
752
  --check-js # (Check for JavaScript errors after page loads.)
599
753
  --ad-block # (Block some types of display ads from loading.)
754
+ --host-resolver-rules=RULES # (Set host-resolver-rules, comma-separated.)
600
755
  --block-images # (Block images from loading during tests.)
601
756
  --do-not-track # (Indicate to websites that you don't want to be tracked.)
602
757
  --verify-delay=SECONDS # (The delay before MasterQA verification checks.)
758
+ --ee | --esc-end # (Lets the user end the current test via the ESC key.)
603
759
  --recorder # (Enables the Recorder for turning browser actions into code.)
604
760
  --rec-behave # (Same as Recorder Mode, but also generates behave-gherkin.)
605
761
  --rec-sleep # (If the Recorder is enabled, also records self.sleep calls.)
606
762
  --rec-print # (If the Recorder is enabled, prints output after tests end.)
763
+ --disable-cookies # (Disable Cookies on websites. Pages might break!)
607
764
  --disable-js # (Disable JavaScript on websites. Pages might break!)
608
765
  --disable-csp # (Disable the Content Security Policy of websites.)
609
766
  --disable-ws # (Disable Web Security on Chromium-based browsers.)
@@ -611,18 +768,22 @@ pytest my_first_test.py --pdb
611
768
  --enable-sync # (Enable "Chrome Sync" on websites.)
612
769
  --uc | --undetected # (Use undetected-chromedriver to evade bot-detection.)
613
770
  --uc-cdp-events # (Capture CDP events when running in "--undetected" mode.)
771
+ --log-cdp # ("goog:loggingPrefs", {"performance": "ALL", "browser": "ALL"})
614
772
  --remote-debug # (Sync to Chrome Remote Debugger chrome://inspect/#devices)
615
- --final-debug # (Enter Debug Mode after each test ends. Don't use with CI!)
773
+ --ftrace | --final-trace # (Debug Mode after each test. Don't use with CI!)
616
774
  --dashboard # (Enable the SeleniumBase Dashboard. Saved at: dashboard.html)
617
775
  --dash-title=STRING # (Set the title shown for the generated dashboard.)
618
- --swiftshader # (Use Chrome's "--use-gl=swiftshader" feature.)
776
+ --enable-3d-apis # (Enables WebGL and 3D APIs.)
777
+ --swiftshader # (Chrome "--use-gl=angle" / "--use-angle=swiftshader-webgl")
619
778
  --incognito # (Enable Chrome's Incognito mode.)
620
779
  --guest # (Enable Chrome's Guest mode.)
780
+ --dark # (Enable Chrome's Dark mode.)
621
781
  --devtools # (Open Chrome's DevTools when the browser opens.)
622
- --reuse-session | --rs # (Reuse browser session for all tests.)
623
- --reuse-class-session | --rcs # (Reuse session for tests in class.)
782
+ --rs | --reuse-session # (Reuse browser session for all tests.)
783
+ --rcs | --reuse-class-session # (Reuse session for tests in class.)
624
784
  --crumbs # (Delete all cookies between tests reusing a session.)
625
785
  --disable-beforeunload # (Disable the "beforeunload" event on Chrome.)
786
+ --window-position=X,Y # (Set the browser's starting window position.)
626
787
  --window-size=WIDTH,HEIGHT # (Set the browser's starting window size.)
627
788
  --maximize # (Start tests with the browser window maximized.)
628
789
  --screenshot # (Save a screenshot at the end of each test.)
@@ -636,14 +797,16 @@ pytest my_first_test.py --pdb
636
797
 
637
798
  (See the full list of command-line option definitions **[here](https://github.com/seleniumbase/SeleniumBase/blob/master/seleniumbase/plugins/pytest_plugin.py)**. For detailed examples of command-line options, see **[customizing_test_runs.md](https://github.com/seleniumbase/SeleniumBase/blob/master/help_docs/customizing_test_runs.md)**)
638
799
 
639
- 🔵 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.
800
+ --------
801
+
802
+ 🔵 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.
640
803
 
641
804
  ```bash
642
805
  cd examples/
643
806
 
644
- pytest test_suite.py --browser=chrome
807
+ pytest test_suite.py --chrome
645
808
 
646
- pytest test_suite.py --browser=firefox
809
+ pytest test_suite.py --firefox
647
810
  ```
648
811
 
649
812
  An easy way to override seleniumbase/config/settings.py is by using a custom settings file.
@@ -654,10 +817,10 @@ Here's the command-line option to add to tests: (See [examples/custom_settings.p
654
817
  🔵 To pass additional data from the command-line to tests, add ``--data="ANY STRING"``.
655
818
  Inside your tests, you can use ``self.data`` to access that.
656
819
 
820
+ <a id="directory_configuration"></a>
821
+ <h2><img src="https://seleniumbase.github.io/img/logo7.png" title="SeleniumBase" width="32" /> Directory Configuration:</h2>
657
822
 
658
- <h3><img src="https://seleniumbase.github.io/img/logo7.png" title="SeleniumBase" width="32" /> Test Directory Configuration:</h3>
659
-
660
- 🔵 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 **nosetests**, 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. Folders should also include a blank ``__init__.py`` file, which allows your tests to import files from that folder.
823
+ 🔵 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.
661
824
 
662
825
  🔵 ``sbase mkdir DIR`` creates a folder with config files and sample tests:
663
826
 
@@ -707,7 +870,7 @@ ui_tests/
707
870
  └── setup.cfg
708
871
  ```
709
872
 
710
- 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 (only needed for nosetests). Finally, the ``requirements.txt`` file can be used to help you install seleniumbase into your environments (if it's not already installed).
873
+ 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).
711
874
 
712
875
  --------
713
876
 
@@ -718,6 +881,7 @@ Let's try an example of a test that fails:
718
881
  ```python
719
882
  """ test_fail.py """
720
883
  from seleniumbase import BaseCase
884
+ BaseCase.main(__name__, __file__)
721
885
 
722
886
  class MyTestClass(BaseCase):
723
887
 
@@ -732,11 +896,12 @@ You can run it from the ``examples/`` folder like this:
732
896
  pytest test_fail.py
733
897
  ```
734
898
 
735
- 🔵 You'll notice that a logs folder, "latest_logs", was created to hold information about the failing test, and screenshots. 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.
899
+ 🔵 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.
736
900
 
737
901
  --------
738
902
 
739
- <h3><img src="https://seleniumbase.github.io/img/logo7.png" title="SeleniumBase" width="32" /> The SeleniumBase Dashboard:</h3>
903
+ <a id="seleniumbase_dashboard"></a>
904
+ <h2><img src="https://seleniumbase.github.io/img/logo7.png" title="SeleniumBase" width="32" /> SeleniumBase Dashboard:</h2>
740
905
 
741
906
  🔵 The ``--dashboard`` option for pytest generates a SeleniumBase Dashboard located at ``dashboard.html``, which updates automatically as tests run and produce results. Example:
742
907
 
@@ -746,30 +911,30 @@ pytest --dashboard --rs --headless
746
911
 
747
912
  <img src="https://seleniumbase.github.io/cdn/img/dashboard_1.png" alt="The SeleniumBase Dashboard" title="The SeleniumBase Dashboard" width="380" />
748
913
 
749
- 🔵 Additionally, you can host your own SeleniumBase Dashboard Server on a port of your choice. Here's an example of that using Python 3's ``http.server``:
914
+ 🔵 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``:
750
915
 
751
916
  ```bash
752
917
  python -m http.server 1948
753
918
  ```
754
919
 
755
- 🔵 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 ``CTRL+C`` to stop the http server.)
920
+ 🔵 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.)
756
921
 
757
922
  🔵 Here's a full example of what the SeleniumBase Dashboard may look like:
758
923
 
759
924
  ```bash
760
- pytest test_suite.py --dashboard --rs --headless
925
+ pytest test_suite.py test_image_saving.py --dashboard --rs --headless
761
926
  ```
762
927
 
763
- <img src="https://seleniumbase.github.io/cdn/img/dashboard_2.png" alt="The SeleniumBase Dashboard" title="The SeleniumBase Dashboard" width="480" />
928
+ <img src="https://seleniumbase.github.io/cdn/img/dashboard_2.png" alt="The SeleniumBase Dashboard" title="The SeleniumBase Dashboard" width="520" />
764
929
 
765
930
  --------
766
931
 
767
932
  <a id="creating_visual_reports"></a>
768
- <h3><img src="https://seleniumbase.github.io/img/logo7.png" title="SeleniumBase" width="32" /> Generating Test Reports:</h3>
933
+ <h2><img src="https://seleniumbase.github.io/img/logo7.png" title="SeleniumBase" width="32" /> Generating Test Reports:</h2>
769
934
 
770
- <h4><b>Pytest Reports:</b></h4>
935
+ <h3>🔵 <code>pytest</code> HTML Reports:</h3>
771
936
 
772
- 🔵 Using ``--html=report.html`` gives you a fancy report of the name specified after your test suite completes.
937
+ Using ``--html=report.html`` gives you a fancy report of the name specified after your test suite completes.
773
938
 
774
939
  ```bash
775
940
  pytest test_suite.py --html=report.html
@@ -777,9 +942,9 @@ pytest test_suite.py --html=report.html
777
942
 
778
943
  <img src="https://seleniumbase.github.io/cdn/img/html_report.png" alt="Example Pytest Report" title="Example Pytest Report" width="520" />
779
944
 
780
- 🔵 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.
945
+ 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.
781
946
 
782
- 🔵 Here's an example of an upgraded html report:
947
+ Here's an example of an upgraded html report:
783
948
 
784
949
  ```bash
785
950
  pytest test_suite.py --dashboard --html=report.html
@@ -787,7 +952,7 @@ pytest test_suite.py --dashboard --html=report.html
787
952
 
788
953
  <img src="https://seleniumbase.github.io/cdn/img/dash_report.jpg" alt="Dashboard Pytest HTML Report" title="Dashboard Pytest HTML Report" width="520" />
789
954
 
790
- If viewing pytest html reports in [Jenkins](https://www.jenkins.io/), you may need to [configure Jenkins settings](https://stackoverflow.com/a/46197356) 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/).
955
+ 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/).
791
956
 
792
957
  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.
793
958
 
@@ -795,19 +960,19 @@ You can also use ``--junit-xml=report.xml`` to get an xml report instead. Jenkin
795
960
  pytest test_suite.py --junit-xml=report.xml
796
961
  ```
797
962
 
798
- <h4><b>Nosetest Reports:</b></h4>
963
+ <h3>🔵 <code>pynose</code> Reports:</h3>
799
964
 
800
965
  The ``--report`` option gives you a fancy report after your test suite completes.
801
966
 
802
967
  ```bash
803
- nosetests test_suite.py --report
968
+ pynose test_suite.py --report
804
969
  ```
805
970
 
806
- <img src="https://seleniumbase.github.io/cdn/img/nose_report.png" alt="Example Nosetest Report" title="Example Nosetest Report" width="320" />
971
+ <img src="https://seleniumbase.github.io/cdn/img/nose_report.png" alt="Example pynose Report" title="Example pynose Report" width="320" />
807
972
 
808
- (NOTE: You can add ``--show-report`` to immediately display Nosetest reports after the test suite completes. Only use ``--show-report`` when running tests locally because it pauses the test run.)
973
+ (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.)
809
974
 
810
- <h4><b>Behave Dashboard & Reports:</b></h4>
975
+ <h3>🔵 <code>behave</code> Dashboard & Reports:</h3>
811
976
 
812
977
  (The [behave_bdd/](https://github.com/seleniumbase/SeleniumBase/tree/master/examples/behave_bdd) folder can be found in the [examples/](https://github.com/seleniumbase/SeleniumBase/tree/master/examples) folder.)
813
978
 
@@ -815,17 +980,17 @@ nosetests test_suite.py --report
815
980
  behave behave_bdd/features/ -D dashboard -D headless
816
981
  ```
817
982
 
818
- <img src="https://seleniumbase.github.io/cdn/img/sb_behave_dashboard.png" title="SeleniumBase" width="500">
983
+ <img src="https://seleniumbase.github.io/cdn/img/sb_behave_dashboard.png" title="SeleniumBase" width="520">
819
984
 
820
- You can also use ``--junit`` to get ``.xml`` reports for each Behave feature. Jenkins can use these files to display better reporting for your tests.
985
+ 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.
821
986
 
822
987
  ```bash
823
988
  behave behave_bdd/features/ --junit -D rs -D headless
824
989
  ```
825
990
 
826
- <h4><b>Allure Reports:</b></h4>
991
+ <h3>🔵 Allure Reports:</h3>
827
992
 
828
- See: [https://docs.qameta.io/allure/](https://docs.qameta.io/allure/#_pytest)
993
+ See: [https://allurereport.org/docs/pytest/](https://allurereport.org/docs/pytest/)
829
994
 
830
995
  SeleniumBase no longer includes ``allure-pytest`` as part of installed dependencies. If you want to use it, install it first:
831
996
 
@@ -839,6 +1004,7 @@ Now your tests can create Allure results files, which can be processed by Allure
839
1004
  pytest test_suite.py --alluredir=allure_results
840
1005
  ```
841
1006
 
1007
+ --------
842
1008
 
843
1009
  <h3><img src="https://seleniumbase.github.io/img/logo7.png" title="SeleniumBase" width="32" /> Using a Proxy Server:</h3>
844
1010
 
@@ -878,9 +1044,9 @@ pytest user_agent_test.py --agent="Mozilla/5.0 (Nintendo 3DS; U; ; en) Version/1
878
1044
  ```
879
1045
 
880
1046
 
881
- <h3><img src="https://seleniumbase.github.io/img/logo7.png" title="SeleniumBase" width="32" /> Handling Pop-Up / Pop Up Alerts:</h3>
1047
+ <h3><img src="https://seleniumbase.github.io/img/logo7.png" title="SeleniumBase" width="32" /> Handling Pop-Up Alerts:</h3>
882
1048
 
883
- 🔵 <code>self.accept_alert()</code> automatically waits for and accepts alert pop-ups. <code>self.dismiss_alert()</code> automatically waits for and dismisses alert pop-ups. On occasion, some methods like <code>self.click(SELECTOR)</code> might dismiss a pop-up on its own because they call JavaScript to make sure that the <code>readyState</code> of the page is <code>complete</code> before advancing. If you're trying to accept a pop-up that got dismissed this way, use this workaround: Call <code>self.find_element(SELECTOR).click()</code> instead, (which will let the pop-up remain on the screen), and then use <code>self.accept_alert()</code> to accept the pop-up (<a href="https://github.com/seleniumbase/SeleniumBase/issues/600#issuecomment-647270426">more on that here</a>). If pop-ups are intermittent, wrap code in a try/except block.
1049
+ 🔵 <code translate="no">self.accept_alert()</code> automatically waits for and accepts alert pop-ups. <code translate="no">self.dismiss_alert()</code> automatically waits for and dismisses alert pop-ups. On occasion, some methods like <code translate="no">self.click(SELECTOR)</code> might dismiss a pop-up on its own because they call JavaScript to make sure that the <code translate="no">readyState</code> of the page is <code translate="no">complete</code> before advancing. If you're trying to accept a pop-up that got dismissed this way, use this workaround: Call <code translate="no">self.find_element(SELECTOR).click()</code> instead, (which will let the pop-up remain on the screen), and then use <code translate="no">self.accept_alert()</code> to accept the pop-up (<a href="https://github.com/seleniumbase/SeleniumBase/issues/600#issuecomment-647270426">more on that here</a>). If pop-ups are intermittent, wrap code in a try/except block.
884
1050
 
885
1051
 
886
1052
  <h3><img src="https://seleniumbase.github.io/img/logo7.png" title="SeleniumBase" width="32" /> Building Guided Tours for Websites:</h3>
@@ -902,11 +1068,11 @@ pytest user_agent_test.py --agent="Mozilla/5.0 (Nintendo 3DS; U; ; en) Version/1
902
1068
  <ul>
903
1069
  <li>You can set up a <a href="https://jenkins.io/" target="_blank">Jenkins</a> build server for running tests at regular intervals. For a real-world Jenkins example of headless browser automation in action, check out the <a href="https://github.com/seleniumbase/SeleniumBase/blob/master/integrations/azure/jenkins/ReadMe.md">SeleniumBase Jenkins example on Azure</a> or the <a href="https://github.com/seleniumbase/SeleniumBase/blob/master/integrations/google_cloud/ReadMe.md">SeleniumBase Jenkins example on Google Cloud</a>.</li>
904
1070
 
905
- <li>You can use <a href="https://selenium.dev/documentation/en/grid/" target="_blank">the Selenium Grid</a> to scale your testing by distributing tests on several machines with parallel execution. To do this, check out the <a href="https://github.com/seleniumbase/SeleniumBase/tree/master/seleniumbase/utilities/selenium_grid">SeleniumBase selenium_grid folder</a>, which should have everything you need, including the <a href="https://github.com/seleniumbase/SeleniumBase/blob/master/seleniumbase/utilities/selenium_grid/ReadMe.md">Selenium Grid ReadMe</a>, which will help you get started.</li>
1071
+ <li>You can use <a href="https://selenium.dev/documentation/en/grid/" target="_blank">the Selenium Grid</a> to scale your testing by distributing tests on several machines with parallel execution. To do this, check out the <a href="https://github.com/seleniumbase/SeleniumBase/tree/master/seleniumbase/utilities/selenium_grid">SeleniumBase selenium_grid folder</a>, which should have everything you need, including the <a href="https://github.com/seleniumbase/SeleniumBase/blob/master/seleniumbase/utilities/selenium_grid/ReadMe.md">Selenium Grid ReadMe</a> to help you get started.</li>
906
1072
 
907
1073
  <li>If you're using the <a href="https://github.com/seleniumbase/SeleniumBase/blob/master/help_docs/mysql_installation.md">SeleniumBase MySQL feature</a> to save results from tests running on a server machine, you can install <a href="https://dev.mysql.com/downloads/tools/workbench/">MySQL Workbench</a> to help you read & write from your DB more easily.</li>
908
1074
 
909
- <li>If you're using AWS, you can set up an <a href="https://aws.amazon.com/s3/" target="_blank">Amazon S3</a> account for saving log files and screenshots from your tests. To activate this feature, modify <a href="https://github.com/seleniumbase/SeleniumBase/blob/master/seleniumbase/config/settings.py">settings.py</a> with connection details in the S3 section, and add <code>--with-s3-logging</code> on the command-line when running your tests.</li>
1075
+ <li>If you're using AWS, you can set up an <a href="https://aws.amazon.com/s3/" target="_blank">Amazon S3</a> account for saving log files and screenshots from your tests. To activate this feature, modify <a href="https://github.com/seleniumbase/SeleniumBase/blob/master/seleniumbase/config/settings.py">settings.py</a> with connection details in the S3 section, and add <code translate="no">--with-s3-logging</code> on the command-line when running your tests.</li>
910
1076
  </ul>
911
1077
 
912
1078
  Here's an example of running tests with some additional features enabled:
@@ -921,7 +1087,7 @@ pytest [YOUR_TEST_FILE.py] --with-db-reporting --with-s3-logging
921
1087
  <a id="detailed_method_specifications"></a>
922
1088
  <h3><img src="https://seleniumbase.github.io/img/logo7.png" title="SeleniumBase" width="32" /> Detailed Method Specifications and Examples:</h3>
923
1089
 
924
- 🔵 Navigating to a web page: (and related commands)
1090
+ 🔵 **Navigating to a web page: (and related commands)**
925
1091
 
926
1092
  ```python
927
1093
  self.open("https://xkcd.com/378/") # This method opens the specified page.
@@ -937,7 +1103,7 @@ self.get_current_url() # This method returns the current page URL.
937
1103
  self.get_page_source() # This method returns the current page source.
938
1104
  ```
939
1105
 
940
- <b>ProTip™:</b> You can use the <code>self.get_page_source()</code> method with Python's <code>find()</code> command to parse through HTML to find something specific. (For more advanced parsing, see the <a href="https://github.com/seleniumbase/SeleniumBase/blob/master/examples/test_parse_soup.py">BeautifulSoup example</a>.)
1106
+ <b>ProTip™:</b> You can use the <code translate="no">self.get_page_source()</code> method with Python's <code translate="no">find()</code> command to parse through HTML to find something specific. (For more advanced parsing, see the <a href="https://github.com/seleniumbase/SeleniumBase/blob/master/examples/test_parse_soup.py">BeautifulSoup example</a>.)
941
1107
 
942
1108
  ```python
943
1109
  source = self.get_page_source()
@@ -946,7 +1112,7 @@ head_close_tag = source.find('</head>', head_open_tag)
946
1112
  everything_inside_head = source[head_open_tag+len('<head>'):head_close_tag]
947
1113
  ```
948
1114
 
949
- 🔵 Clicking:
1115
+ 🔵 **Clicking:**
950
1116
 
951
1117
  To click an element on the page:
952
1118
 
@@ -956,29 +1122,29 @@ self.click("div#my_id")
956
1122
 
957
1123
  **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.
958
1124
 
959
- 🔵 Typing Text:
1125
+ 🔵 **Typing Text:**
960
1126
 
961
- <code>self.type(selector, text)</code> # updates the text from the specified element with the specified value. An exception is raised if the element is missing or if the text field is not editable. Example:
1127
+ <code translate="no">self.type(selector, text)</code> # updates the text from the specified element with the specified value. An exception is raised if the element is missing or if the text field is not editable. Example:
962
1128
 
963
1129
  ```python
964
1130
  self.type("input#id_value", "2012")
965
1131
  ```
966
1132
 
967
- You can also use <code>self.add_text()</code> or the <a href="https://www.selenium.dev/documentation/webdriver/" target="_blank">WebDriver</a> <code>.send_keys()</code> command, but those won't clear the text box first if there's already text inside.
1133
+ You can also use <code translate="no">self.add_text()</code> or the <a href="https://www.selenium.dev/documentation/webdriver/" target="_blank">WebDriver</a> <code translate="no">.send_keys()</code> command, but those won't clear the text box first if there's already text inside.
968
1134
 
969
- 🔵 Getting the text from an element on a page:
1135
+ 🔵 **Getting the text from an element on a page:**
970
1136
 
971
1137
  ```python
972
1138
  text = self.get_text("header h2")
973
1139
  ```
974
1140
 
975
- 🔵 Getting the attribute value from an element on a page:
1141
+ 🔵 **Getting the attribute value from an element on a page:**
976
1142
 
977
1143
  ```python
978
1144
  attribute = self.get_attribute("#comic img", "title")
979
1145
  ```
980
1146
 
981
- 🔵 Asserting existence of an element on a page within some number of seconds:
1147
+ 🔵 **Asserting existence of an element on a page within some number of seconds:**
982
1148
 
983
1149
  ```python
984
1150
  self.wait_for_element_present("div.my_class", timeout=10)
@@ -986,7 +1152,7 @@ self.wait_for_element_present("div.my_class", timeout=10)
986
1152
 
987
1153
  (NOTE: You can also use: ``self.assert_element_present(ELEMENT)``)
988
1154
 
989
- 🔵 Asserting visibility of an element on a page within some number of seconds:
1155
+ 🔵 **Asserting visibility of an element on a page within some number of seconds:**
990
1156
 
991
1157
  ```python
992
1158
  self.wait_for_element_visible("a.my_class", timeout=5)
@@ -1012,7 +1178,7 @@ You can also use ``*=`` to search for any partial value in a CSS selector as sho
1012
1178
  self.click('a[name*="partial_name"]')
1013
1179
  ```
1014
1180
 
1015
- 🔵 Asserting visibility of text inside an element on a page within some number of seconds:
1181
+ 🔵 **Asserting visibility of text inside an element on a page within some number of seconds:**
1016
1182
 
1017
1183
  ```python
1018
1184
  self.assert_text("Make it so!", "div#trek div.picard div.quotes")
@@ -1021,7 +1187,7 @@ self.assert_text("Tea. Earl Grey. Hot.", "div#trek div.picard div.quotes", timeo
1021
1187
 
1022
1188
  (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.)
1023
1189
 
1024
- 🔵 Asserting Anything:
1190
+ 🔵 **Asserting Anything:**
1025
1191
 
1026
1192
  ```python
1027
1193
  self.assert_true(var1 == var2)
@@ -1031,7 +1197,7 @@ self.assert_false(var1 == var2)
1031
1197
  self.assert_equal(var1, var2)
1032
1198
  ```
1033
1199
 
1034
- 🔵 Useful Conditional Statements: (with creative examples)
1200
+ 🔵 **Useful Conditional Statements: (with creative examples)**
1035
1201
 
1036
1202
  ❓ ``is_element_visible(selector):`` (visible on the page)
1037
1203
 
@@ -1066,7 +1232,7 @@ if self.is_text_visible("You Shall Not Pass!", "h1"):
1066
1232
 
1067
1233
  <div></div>
1068
1234
  <details>
1069
- <summary> ▶️ Click for a longer example of <code>is_text_visible():</code></summary>
1235
+ <summary> ▶️ Click for a longer example of <code translate="no">is_text_visible():</code></summary>
1070
1236
 
1071
1237
  ```python
1072
1238
  def get_mirror_universe_captain_picard_superbowl_ad(superbowl_year):
@@ -1104,24 +1270,52 @@ if self.is_link_text_visible("Stop! Hammer time!"):
1104
1270
  self.click_link("Stop! Hammer time!")
1105
1271
  ```
1106
1272
 
1107
- 🔵 Switching Tabs:
1273
+ <h3>🔵 Switching Tabs:</h3>
1108
1274
 
1109
- <p>If your test opens up a new tab/window, you can switch to it. (SeleniumBase automatically switches to new tabs that don't open to <code>about:blank</code> URLs.)</p>
1275
+ <p>If your test opens up a new tab/window, you can switch to it. (SeleniumBase automatically switches to new tabs that don't open to <code translate="no">about:blank</code> URLs.)</p>
1110
1276
 
1111
1277
  ```python
1112
1278
  self.switch_to_window(1) # This switches to the new tab (0 is the first one)
1113
1279
  ```
1114
1280
 
1115
- 🔵 <b>ProTip™:</b> iframes follow the same principle as new windows - you need to specify the iframe if you want to take action on something in there
1281
+ <h3>🔵 How to handle iframes:</h3>
1282
+
1283
+ 🔵 <b>iframes</b> follow the same principle as new windows: You must first switch to the iframe if you want to perform actions in there:
1116
1284
 
1117
1285
  ```python
1118
- self.switch_to_frame('ContentManagerTextBody_ifr')
1119
- # Now you can act inside the iframe
1120
- # .... Do something cool (here)
1121
- self.switch_to_default_content() # Exit the iframe when you're done
1286
+ self.switch_to_frame("iframe")
1287
+ # ... Now perform actions inside the iframe
1288
+ self.switch_to_parent_frame() # Exit the current iframe
1122
1289
  ```
1123
1290
 
1124
- 🔵 Executing Custom jQuery Scripts:
1291
+ 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()``.)
1292
+
1293
+ ```python
1294
+ self.switch_to_frame('iframe[name="frame1"]')
1295
+ self.switch_to_frame('iframe[name="frame2"]')
1296
+ # ... Now perform actions inside the inner iframe
1297
+ self.switch_to_default_content() # Back to the main page
1298
+ ```
1299
+
1300
+ 🔵 You can also use a context manager to act inside iframes:
1301
+
1302
+ ```python
1303
+ with self.frame_switch("iframe"):
1304
+ # ... Now perform actions while inside the code block
1305
+ # You have left the iframe
1306
+ ```
1307
+
1308
+ This also works with nested iframes:
1309
+
1310
+ ```python
1311
+ with self.frame_switch('iframe[name="frame1"]'):
1312
+ with self.frame_switch('iframe[name="frame2"]'):
1313
+ # ... Now perform actions while inside the code block
1314
+ # You are now back inside the first iframe
1315
+ # You have left all the iframes
1316
+ ```
1317
+
1318
+ <h3>🔵 How to execute custom jQuery scripts:</h3>
1125
1319
 
1126
1320
  <p>jQuery is a powerful JavaScript library that allows you to perform advanced actions in a web browser.
1127
1321
  If the web page you're on already has jQuery loaded, you can start executing jQuery scripts immediately.
@@ -1165,7 +1359,11 @@ self.execute_script("return jQuery('textarea')[2].value") # Returns the css "va
1165
1359
 
1166
1360
  </details>
1167
1361
 
1168
- 🔵 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 such a website, add ``--disable-csp`` on the command-line.
1362
+ <h3>🔵 How to handle a restrictive CSP:</h3>
1363
+
1364
+ ❗ 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.
1365
+
1366
+ <h3>🔵 More JavaScript fun:</h3>
1169
1367
 
1170
1368
  <div></div>
1171
1369
  <details>
@@ -1180,35 +1378,37 @@ self.execute_script('''document.body.innerHTML = \"%s\"''' % referral_link)
1180
1378
  self.click("a.analytics") # Clicks the generated button
1181
1379
  ```
1182
1380
 
1183
- (Due to popular demand, this traffic generation example has been included in SeleniumBase with the <code>self.generate_referral(start_page, end_page)</code> and the <code>self.generate_traffic(start_page, end_page, loops)</code> methods.)
1381
+ (Due to popular demand, this traffic generation example has been included in SeleniumBase with the <code translate="no">self.generate_referral(start_page, end_page)</code> and the <code translate="no">self.generate_traffic(start_page, end_page, loops)</code> methods.)
1184
1382
 
1185
1383
  </details>
1186
1384
 
1187
- 🔵 Using deferred asserts:
1385
+ <h3>🔵 How to use deferred asserts:</h3>
1188
1386
 
1189
- <p>Let's say you want to verify multiple different elements on a web page in a single test, but you don't want the test to fail until you verified several elements at once so that you don't have to rerun the test to find more missing elements on the same page. That's where deferred asserts come in. Here's the example:</p>
1387
+ <p>Let's say you want to verify multiple different elements on a web page in a single test, but you don't want the test to fail until you verified several elements at once so that you don't have to rerun the test to find more missing elements on the same page. That's where deferred asserts come in. Here's an example:</p>
1190
1388
 
1191
1389
  ```python
1192
1390
  from seleniumbase import BaseCase
1391
+ BaseCase.main(__name__, __file__)
1193
1392
 
1194
- class MyTestClass(BaseCase):
1195
-
1393
+ class DeferredAssertTests(BaseCase):
1196
1394
  def test_deferred_asserts(self):
1197
- self.open('https://xkcd.com/993/')
1198
- self.wait_for_element('#comic')
1395
+ self.open("https://xkcd.com/993/")
1396
+ self.wait_for_element("#comic")
1199
1397
  self.deferred_assert_element('img[alt="Brand Identity"]')
1200
1398
  self.deferred_assert_element('img[alt="Rocket Ship"]') # Will Fail
1201
- self.deferred_assert_element('#comicmap')
1202
- self.deferred_assert_text('Fake Item', '#middleContainer') # Will Fail
1203
- self.deferred_assert_text('Random', '#middleContainer')
1399
+ self.deferred_assert_element("#comicmap")
1400
+ self.deferred_assert_text("Fake Item", "ul.comicNav") # Will Fail
1401
+ self.deferred_assert_text("Random", "ul.comicNav")
1204
1402
  self.deferred_assert_element('a[name="Super Fake !!!"]') # Will Fail
1403
+ self.deferred_assert_exact_text("Brand Identity", "#ctitle")
1404
+ self.deferred_assert_exact_text("Fake Food", "#comic") # Will Fail
1205
1405
  self.process_deferred_asserts()
1206
1406
  ```
1207
1407
 
1208
- <code>deferred_assert_element()</code> and <code>deferred_assert_text()</code> will save any exceptions that would be raised.
1209
- To flush out all the failed deferred asserts into a single exception, make sure to call <code>self.process_deferred_asserts()</code> at the end of your test method. If your test hits multiple pages, you can call <code>self.process_deferred_asserts()</code> before navigating to a new page so that the screenshot from your log files matches the URL where the deferred asserts were made.
1408
+ <code translate="no">deferred_assert_element()</code> and <code translate="no">deferred_assert_text()</code> will save any exceptions that would be raised.
1409
+ To flush out all the failed deferred asserts into a single exception, make sure to call <code translate="no">self.process_deferred_asserts()</code> at the end of your test method. If your test hits multiple pages, you can call <code translate="no">self.process_deferred_asserts()</code> before navigating to a new page so that the screenshot from your log files matches the URL where the deferred asserts were made.
1210
1410
 
1211
- 🔵 Accessing Raw <a href="https://www.selenium.dev/documentation/webdriver/" target="_blank">WebDriver</a>:
1411
+ <h3>🔵 How to access raw <a href="https://www.selenium.dev/documentation/webdriver/" target="_blank">WebDriver</a>:</h3>
1212
1412
 
1213
1413
  <p>If you need access to any commands that come with standard <a href="https://www.selenium.dev/documentation/webdriver/" target="_blank">WebDriver</a>, you can call them directly like this:</p>
1214
1414
 
@@ -1220,42 +1420,47 @@ self.driver.find_elements("partial link text", "GitHub")
1220
1420
 
1221
1421
  (In general, you'll want to use the SeleniumBase versions of methods when available.)
1222
1422
 
1223
- 🔵 Retrying failing tests automatically:
1423
+ <h3>🔵 How to retry failing tests automatically:</h3>
1224
1424
 
1225
- <p>You can use <code>--reruns=NUM</code> to retry failing tests that many times. Use <code>--reruns-delay=SECONDS</code> to wait that many seconds between retries. Example:</p>
1425
+ <p>You can use <code translate="no">pytest --reruns=NUM</code> to retry failing tests that many times. Add <code translate="no">--reruns-delay=SECONDS</code> to wait that many seconds between retries. Example:</p>
1226
1426
 
1227
1427
  ```bash
1228
1428
  pytest --reruns=1 --reruns-delay=1
1229
1429
  ```
1230
1430
 
1231
- <p>You can use the <code>@retry_on_exception()</code> decorator to retry failing methods. (First import: <code>from seleniumbase import decorators</code>). To learn more about SeleniumBase decorators, <a href="https://github.com/seleniumbase/SeleniumBase/tree/master/seleniumbase/common">click here</a>.</p>
1431
+ <p>You can use the <code translate="no">@retry_on_exception()</code> decorator to retry failing methods. (First import: <code translate="no">from seleniumbase import decorators</code>). To learn more about SeleniumBase decorators, <a href="https://github.com/seleniumbase/SeleniumBase/tree/master/seleniumbase/common">click here</a>.</p>
1232
1432
 
1433
+ --------
1233
1434
 
1234
- <h3><img src="https://seleniumbase.github.io/img/logo7.png" title="SeleniumBase" width="32" /> Wrap-Up</h3>
1435
+ > "Catch bugs in QA before deploying code to Production!"
1436
+
1437
+ <p align="left"><a href="https://seleniumbase.io/error_page" target="_blank"><img src="https://seleniumbase.github.io/cdn/gif/error_page.gif" alt="Catch bugs in QA before deploying code to Production!" title="Catch bugs in QA before deploying code to Production!" /></a></p>
1438
+
1439
+ --------
1235
1440
 
1236
- <b>Congratulations on getting started with SeleniumBase!</b>
1441
+ <h3><img src="https://seleniumbase.github.io/img/logo7.png" title="SeleniumBase" width="32" /> Wrap-Up</h3>
1237
1442
 
1238
1443
  <p>
1239
1444
  <div><b>If you see something, say something!</b></div>
1240
- <div><a href="https://github.com/seleniumbase/SeleniumBase/issues?q=is%3Aissue+is%3Aclosed"><img src="https://img.shields.io/github/issues-closed-raw/seleniumbase/SeleniumBase.svg?color=22BB88" title="Closed Issues" /></a> <a href="https://github.com/seleniumbase/SeleniumBase/pulls?q=is%3Apr+is%3Aclosed"><img src="https://img.shields.io/github/issues-pr-closed/seleniumbase/SeleniumBase.svg?logo=github&logoColor=white&color=22BB99" title="Closed Pull Requests" /></a></div>
1445
+ <div><a href="https://github.com/seleniumbase/SeleniumBase/issues?q=is%3Aissue+is%3Aclosed"><img src="https://img.shields.io/github/issues-closed-raw/seleniumbase/SeleniumBase.svg?color=22BB88" title="Closed Issues" /></a> <a href="https://github.com/seleniumbase/SeleniumBase/pulls?q=is%3Apr+is%3Aclosed"><img src="https://img.shields.io/github/issues-pr-closed/seleniumbase/SeleniumBase.svg?logo=github&logoColor=white&color=22BB99" title="Closed Pull Requests" /></a></div>
1241
1446
  </p>
1242
1447
 
1243
- <p>
1244
- <div><b>If you like SeleniumBase, star us! ⭐</b></div>
1245
- <div><a href="https://github.com/seleniumbase/SeleniumBase/stargazers"><img src="https://img.shields.io/github/stars/seleniumbase/seleniumbase.svg?color=19A57B" title="Stargazers" /></a></div>
1246
- </p>
1247
- <p><div><a href="https://github.com/mdmintz">https://github.com/mdmintz</a></div></p>
1448
+ <p align="left"><a href="https://github.com/seleniumbase/SeleniumBase/"><img src="https://seleniumbase.github.io/cdn/img/sb_logo_10t.png" alt="SeleniumBase" title="SeleniumBase" width="274" /></a></p>
1248
1449
 
1249
- <div><a href="https://github.com/seleniumbase/SeleniumBase/"><img src="https://seleniumbase.github.io/cdn/img/fancy_logo_14.png" title="SeleniumBase" width="220" /></a></div> <div><a href="https://github.com/seleniumbase/SeleniumBase/blob/master/LICENSE"><img src="https://img.shields.io/badge/license-MIT-22BBCC.svg" title="SeleniumBase" /></a> <a href="https://gitter.im/seleniumbase/SeleniumBase" target="_blank"><img src="https://badges.gitter.im/seleniumbase/SeleniumBase.svg" title="SeleniumBase" alt="Join the chat!" /></a></div> <div><a href="https://github.com/seleniumbase/SeleniumBase"><img src="https://img.shields.io/badge/tested%20with-SeleniumBase-04C38E.svg" alt="Tested with SeleniumBase" /></a></div> <div><a href="https://seleniumbase.io"><img src="https://img.shields.io/badge/docs-seleniumbase.io-11BBAA.svg" alt="SeleniumBase Docs" /></a></div>
1450
+ <a href="https://pypi.org/project/seleniumbase/" target="_blank"><img src="https://img.shields.io/pypi/pyversions/seleniumbase.svg?color=22AAEE&logo=python&logoColor=FEDC54" title="Supported Python Versions" /></a>
1250
1451
 
1251
1452
  <p><div>
1252
- <span><a href="https://www.youtube.com/playlist?list=PLp9uKicxkBc5UIlGi2BuE3aWC7JyXpD3m"><img src="https://seleniumbase.github.io/cdn/img/youtube.png" title="SeleniumBase Playlist on YouTube" alt="SeleniumBase Playlist on YouTube" width="54" /></a></span>
1253
- <span><a href="https://github.com/seleniumbase/SeleniumBase"><img src="https://seleniumbase.github.io/img/social/share_github.svg" title="SeleniumBase on GitHub" alt="SeleniumBase on GitHub" width="50" /></a></span>
1254
- <span><a href="https://gitter.im/seleniumbase/SeleniumBase" target="_blank"><img src="https://seleniumbase.github.io/img/social/share_gitter.svg" title="SeleniumBase on Gitter" alt="SeleniumBase on Gitter" width="38" /></a></span>
1453
+ <span><a href="https://www.youtube.com/playlist?list=PLp9uKicxkBc5UIlGi2BuE3aWC7JyXpD3m"><img src="https://seleniumbase.github.io/cdn/img/youtube.png" title="SeleniumBase Playlist on YouTube" alt="SeleniumBase Playlist on YouTube" width="70" /></a></span>
1454
+ <span><a href="https://github.com/seleniumbase/SeleniumBase"><img src="https://seleniumbase.github.io/img/social/share_github.svg" title="SeleniumBase on GitHub" alt="SeleniumBase on GitHub" width="64" /></a></span>
1455
+ <span><a href="https://discord.gg/EdhQTn3EyE"><img src="https://seleniumbase.github.io/other/discord_icon.png" title="SeleniumBase on Discord" alt="SeleniumBase on Discord" width="66" /></a></span>
1456
+ <span><a href="https://www.facebook.com/SeleniumBase"><img src="https://seleniumbase.io/img/social/share_facebook.svg" title="SeleniumBase on Facebook" alt="SeleniumBase on Facebook" width="62" /></a></span>
1255
1457
  </div></p>
1256
1458
 
1257
- --------
1459
+ <p><div><b><a href="https://github.com/mdmintz">https://github.com/mdmintz</a></b></div></p>
1258
1460
 
1259
- <p><a href="https://github.com/seleniumbase/SeleniumBase/"><img src="https://seleniumbase.github.io/cdn/img/sb_logo_b.png" alt="SeleniumBase" title="SeleniumBase" width="240" /></a></p>
1260
- <p><a href="https://pepy.tech/project/seleniumbase" target="_blank"><img src="https://pepy.tech/badge/seleniumbase" alt="SeleniumBase PyPI downloads" /></a></p>
1261
- <p><a href="https://www.python.org/downloads/" target="_blank"><img src="https://img.shields.io/pypi/pyversions/seleniumbase.svg?color=22AAEE&logo=python&logoColor=FEDC54" title="Supported Python Versions" /></a></p>
1461
+ <div><a href="https://github.com/seleniumbase/SeleniumBase/"><img src="https://seleniumbase.github.io/cdn/img/super_logo_sb3.png" title="SeleniumBase" width="274" /></a></div>
1462
+ <div><a href="https://seleniumbase.io"><img src="https://img.shields.io/badge/docs-seleniumbase.io-11BBAA.svg" alt="SeleniumBase Docs" /></a> <a href="https://github.com/seleniumbase/SeleniumBase/blob/master/LICENSE"><img src="https://img.shields.io/badge/license-MIT-22BBCC.svg" title="SeleniumBase" /></a></div>
1463
+ <div><a href="https://github.com/seleniumbase/SeleniumBase"><img src="https://img.shields.io/badge/tested%20with-SeleniumBase-04C38E.svg" alt="Tested with SeleniumBase" /></a> <a href="https://github.com/seleniumbase/SeleniumBase/stargazers"><img src="https://img.shields.io/github/stars/seleniumbase/seleniumbase.svg?color=19A57B" title="Stargazers" /></a></div>
1464
+ <div><a href="https://hellogithub.com/repository/c6be2d0f1969448697683d11a4ff915e" target="_blank"><img src="https://abroad.hellogithub.com/v1/widgets/recommend.svg?rid=c6be2d0f1969448697683d11a4ff915e&claim_uid=xcrm4p9j3d6JCO5&theme=small" alt="Featured|HelloGitHub" /></a> <a href="https://discord.gg/EdhQTn3EyE" target="_blank"><img src="https://img.shields.io/badge/join-discord-infomational" alt="Join the SeleniumBase chat on Discord"/></a> <a href="https://gitter.im/seleniumbase/SeleniumBase" target="_blank"><img src="https://img.shields.io/gitter/room/seleniumbase/SeleniumBase.svg" alt="Gitter chat"/></a></div>
1465
+ <div><a href="https://pepy.tech/project/seleniumbase" target="_blank"><img src="https://static.pepy.tech/badge/seleniumbase" alt="SeleniumBase PyPI downloads" /></a> <img src="https://views.whatilearened.today/views/github/seleniumbase/SeleniumBase.svg" width="98px" height="20px" alt="Views" /></div>
1466
+ <div align="left"></div>