From 9f57451364ba6ba3f97ae4f5a9d60f0c2ab60efe Mon Sep 17 00:00:00 2001 From: Michael Mintz Date: Tue, 8 Aug 2023 22:52:40 -0400 Subject: [PATCH] Update the docs --- help_docs/syntax_formats/index.html | 2 ++ help_docs/translations/index.html | 4 ++++ search/search_index.json | 2 +- 3 files changed, 7 insertions(+), 1 deletion(-) diff --git a/help_docs/syntax_formats/index.html b/help_docs/syntax_formats/index.html index 959e33bb0..13c6a9391 100644 --- a/help_docs/syntax_formats/index.html +++ b/help_docs/syntax_formats/index.html @@ -2106,10 +2106,12 @@

self.单击('button:contains("搜索")') self.断言文本("舞龍", "#firstHeading") self.断言元素('img[src*="Chinese_draak.jpg"]') + self.回去() self.输入文本('input[name="search"]', "麻婆豆腐") self.单击('button:contains("搜索")') self.断言文本("麻婆豆腐", "#firstHeading") self.断言元素('figure:contains("一家中餐館的麻婆豆腐")') + self.回去() self.输入文本('input[name="search"]', "精武英雄") self.单击('button:contains("搜索")') self.断言元素('img[src*="Fist_of_legend.jpg"]') diff --git a/help_docs/translations/index.html b/help_docs/translations/index.html index 45e92ee37..dd7855a33 100644 --- a/help_docs/translations/index.html +++ b/help_docs/translations/index.html @@ -1764,6 +1764,7 @@

self.输入文本('input[name="search"]', "舞龍") self.单击('button:contains("搜索")') self.断言文本("舞龍", "#firstHeading") + self.断言元素('img[src*="Chinese_draak.jpg"]')

Here's another example:

Translation API 🈺

diff --git a/search/search_index.json b/search/search_index.json index f76f320a7..4f00a7237 100644 --- a/search/search_index.json +++ b/search/search_index.json @@ -1 +1 @@ -{"config": {"lang": ["en"], "separator": "[\\s]+", "pipeline": ["stopWordFilter"]}, "docs": [{"location": "", "title": "\u2705 SeleniumBase README", "text": "SeleniumBase All-in-one Test Automation Framework For Python enthusiasts and enterprise developers

\ud83d\ude80 Start | \ud83c\udff0 Features | \ud83d\udcda Examples | \ud83c\udf9b\ufe0f Options | \ud83c\udf20 Scripts | \ud83d\udcf1 Mobile \ud83d\udcd8 APIs | \ud83d\udd21 Formats | \ud83d\udcca Dashboard | \ud83d\udd34 Recorder | \ud83d\uddfe Locales | \ud83c\udf10 Grid \ud83c\udf96\ufe0f GUI | \ud83d\udcf0 TestPage | \ud83d\uddc2\ufe0f CasePlans | \ud83d\udd75\ufe0f Inspector | \ud83e\uddec Hybrid | \ud83d\udcbb Farm \ud83d\udc41\ufe0f How | \ud83d\ude9d Migrate | \u267b\ufe0f Templates | \ud83d\ude89 NodeGUI | \ud83d\udcf6 Charts | \ud83d\ude8e Tours \ud83e\udd16 CI/CD | \ud83d\udd79\ufe0f JSMgr | \ud83c\udf0f Translator | \ud83c\udf9e\ufe0f Presenter | \ud83d\udec2 Dialog | \ud83d\uddbc\ufe0f Visual

Explore the README:

Example: test_demo_site.py from ./examples/ (Uses --chrome by default)

cd examples/\npytest test_demo_site.py\n

Easy to type, click, select, toggle, drag-and-drop, etc.

Example: test_coffee_cart.py from ./examples/

cd examples/\npytest test_coffee_cart.py --demo\n

(--demo mode slows down tests and highlights actions)

from seleniumbase import BaseCase\nBaseCase.main(__name__, __file__)\n\nclass CoffeeCartTest(BaseCase):\n    def test_coffee_cart(self):\n        self.open(\"https://seleniumbase.io/coffee/\")\n        self.assert_title(\"Coffee Cart\")\n        self.click('div[data-sb=\"Cappuccino\"]')\n        self.click('div[data-sb=\"Flat-White\"]')\n        self.click('div[data-sb=\"Cafe-Latte\"]')\n        self.click('a[aria-label=\"Cart page\"]')\n        self.assert_exact_text(\"Total: $53.00\", \"button.pay\")\n        self.click(\"button.pay\")\n        self.type(\"input#name\", \"Selenium Coffee\")\n        self.type(\"input#email\", \"test@test.test\")\n        self.click(\"button#submit-payment\")\n        self.assert_text(\"Thanks for your purchase.\", \"#app .success\")\n

(For more examples, see the SeleniumBase/examples/ folder.)

\u25b6\ufe0f How is SeleniumBase different from raw Selenium? (click to expand)

\ud83d\udca1 SeleniumBase is a Python framework for browser automation and testing. SeleniumBase uses Selenium/WebDriver APIs, and incorporates test-runners such as pytest, pynose, and behave to provide organized structure, test discovery, test execution, test state (eg. passed, failed, or skipped), and command-line options for changing default settings (such as choosing the browser to use). With raw Selenium, you would need to set up your own options-parser for configuring tests from the command-line.

\ud83d\udca1 With raw Selenium, commands that use selectors need to specify the type of selector (eg. \"css selector\", \"button#myButton\"). 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 (but optionally you could).

\ud83d\udca1 SeleniumBase methods often perform multiple actions in a single method call. For example, self.type(selector,text) does the following:1. Waits for the element to be visible.2. Waits for the element to be interactive.3. Clears the text field.4. Types in the new text.5. Presses Enter/Submit if the text ends in \"\\n\".With raw Selenium, those actions require multiple method calls.

\ud83d\udca1 SeleniumBase uses default timeout values when not set: \u2705self.click(\"button\") With raw Selenium, methods would fail instantly (by default) if an element needed more time to load: \u274cself.driver.find_element(by=\"css selector\", value=\"button\").click() (Reliable code is better than unreliable code.)

\ud83d\udca1 SeleniumBase lets you change the explicit timeout values of methods: \u2705self.click(\"button\",timeout=10) With raw Selenium, that requires more code: \u274cWebDriverWait(driver,10).until(EC.element_to_be_clickable(\"css selector\", \"button\")).click() (Simple code is better than complex code.)

\ud83d\udca1 SeleniumBase gives you clean error output when a test fails. With raw Selenium, error messages can get very messy.

\ud83d\udca1 SeleniumBase gives you the option to generate a dashboard and reports for tests. It also saves screenshots from failing tests to the ./latest_logs/ folder. Raw Selenium does not have these options out-of-the-box.

\ud83d\udca1 SeleniumBase includes desktop GUI apps for running tests, such as SeleniumBase Commander for pytest and SeleniumBase Behave GUI for behave.

\ud83d\udca1 SeleniumBase has its own Recorder / Test Generator that can create tests from manual browser actions. SeleniumBase also includes other useful tools and console scripts for getting things done quickly. (See the documentation for more details!)

\u25b6\ufe0f Learn about different ways of writing tests (click to expand)

\ud83d\udcd8\ud83d\udcdd An example test with the BaseCase class. Runs with pytest or pynose. (Learn more)

from seleniumbase import BaseCase\nBaseCase.main(__name__, __file__)\n\nclass TestMFALogin(BaseCase):\n    def test_mfa_login(self):\n        self.open(\"https://seleniumbase.io/realworld/login\")\n        self.type(\"#username\", \"demo_user\")\n        self.type(\"#password\", \"secret_pass\")\n        self.enter_mfa_code(\"#totpcode\", \"GAXG2MTEOR3DMMDG\")  # 6-digit\n        self.assert_exact_text(\"Welcome!\", \"h1\")\n        self.assert_element(\"img#image1\")\n        self.click('a:contains(\"This Page\")')\n        self.save_screenshot_to_logs()\n

\ud83d\udcd7\ud83d\udcdd An example test with the sb pytest fixture. Runs with pytest.

def test_mfa_login(sb):\n    sb.open(\"https://seleniumbase.io/realworld/login\")\n    sb.type(\"#username\", \"demo_user\")\n    sb.type(\"#password\", \"secret_pass\")\n    sb.enter_mfa_code(\"#totpcode\", \"GAXG2MTEOR3DMMDG\")  # 6-digit\n    sb.assert_exact_text(\"Welcome!\", \"h1\")\n    sb.assert_element(\"img#image1\")\n    sb.click('a:contains(\"This Page\")')\n    sb.save_screenshot_to_logs()\n

\ud83d\udcd9\ud83d\udcdd An example test with the SB Context Manager. Runs with pure python.

from seleniumbase import SB\n\nwith SB() as sb:  # By default, browser=\"chrome\" if not set.\n    sb.open(\"https://seleniumbase.io/realworld/login\")\n    sb.type(\"#username\", \"demo_user\")\n    sb.type(\"#password\", \"secret_pass\")\n    sb.enter_mfa_code(\"#totpcode\", \"GAXG2MTEOR3DMMDG\")  # 6-digit\n    sb.assert_text(\"Welcome!\", \"h1\")\n    sb.highlight(\"img#image1\")  # A fancier assert_element() call\n    sb.click('a:contains(\"This Page\")')  # Use :contains() on any tag\n    sb.click_link(\"Sign out\")  # Link must be \"a\" tag. Not \"button\".\n    sb.assert_element('a:contains(\"Sign in\")')\n    sb.assert_exact_text(\"You have been signed out!\", \"#top_message\")\n

\ud83d\udcd5\ud83d\udcdd An example test with behave-BDD Gherkin structure. Runs with behave. (Learn more)

Feature: SeleniumBase scenarios for the RealWorld App\n\nScenario: Verify RealWorld App\n    Given Open \"seleniumbase.io/realworld/login\"\nWhen Type \"demo_user\" into \"#username\"\nAnd Type \"secret_pass\" into \"#password\"\nAnd Do MFA \"GAXG2MTEOR3DMMDG\" into \"#totpcode\"\nThen Assert exact text \"Welcome!\" in \"h1\"\nAnd Assert element \"img#image1\"\nAnd Click 'a:contains(\"This Page\")'\nAnd Save screenshot to logs\n

Set up Python & Git:

\ud83d\udd35 Add Python and Git to your System PATH.

\ud83d\udd35 Using a Python virtual env is recommended.

Install SeleniumBase:

You can install seleniumbase from PyPI or GitHub:

\ud83d\udd35 How to install seleniumbase from PyPI:

pip install seleniumbase\n

\ud83d\udd35 How to install seleniumbase from a GitHub clone:

git clone https://github.com/seleniumbase/SeleniumBase.git\ncd SeleniumBase/\npip install -e .\n

\ud83d\udd35 How to upgrade an existing install from a GitHub clone:

git pull\npip install -e .\n

\ud83d\udd35 Type seleniumbase or sbase to verify that SeleniumBase was installed successfully:

   ______     __           _                  ____                / ____/__  / /__  ____  (_)_  ______ ___   / _  \\____  ________ \\__ \\/ _ \\/ / _ \\/ __ \\/ / / / / __ `__ \\ / /_) / __ \\/ ___/ _ \\\n___/ /  __/ /  __/ / / / / /_/ / / / / / // /_) / (_/ /__  /  __/\n/____/\\___/_/\\___/_/ /_/_/\\__,_/_/ /_/ /_//_____/\\__,_/____/\\___/ \n------------------------------------------------------------------\n\n * USAGE: \"seleniumbase [COMMAND] [PARAMETERS]\"\n*    OR:        \"sbase [COMMAND] [PARAMETERS]\"\n\nCOMMANDS:\n      get / install    [DRIVER] [OPTIONS]\nmethods          (List common Python methods)\noptions          (List common pytest options)\nbehave-options   (List common behave options)\ngui / commander  [OPTIONAL PATH or TEST FILE]\nbehave-gui       (SBase Commander for Behave)\ncaseplans        [OPTIONAL PATH or TEST FILE]\nmkdir            [DIRECTORY] [OPTIONS]\nmkfile           [FILE.py] [OPTIONS]\nmkrec / codegen  [FILE.py] [OPTIONS]\nrecorder         (Open Recorder Desktop App.)\nrecord           (If args: mkrec. Else: App.)\nmkpres           [FILE.py] [LANG]\nmkchart          [FILE.py] [LANG]\nprint            [FILE] [OPTIONS]\ntranslate        [SB_FILE.py] [LANG] [ACTION]\nconvert          [WEBDRIVER_UNITTEST_FILE.py]\nextract-objects  [SB_FILE.py]\ninject-objects   [SB_FILE.py] [OPTIONS]\nobjectify        [SB_FILE.py] [OPTIONS]\nrevert-objects   [SB_FILE.py] [OPTIONS]\nencrypt / obfuscate\n      decrypt / unobfuscate\n      download server  (Get Selenium Grid JAR file)\ngrid-hub         [start|stop] [OPTIONS]\ngrid-node        [start|stop] --hub=[HOST/IP]\n* (EXAMPLE: \"sbase get chromedriver latest\") *\n\n    Type \"sbase help [COMMAND]\" for specific command info.\n    For info on all commands, type: \"seleniumbase --help\".\n    Use \"pytest\" for running tests.\n
\ud83d\udd35 Downloading webdrivers:

\u2705 SeleniumBase automatically downloads webdrivers as needed, such as chromedriver.

\u25b6\ufe0f Here's output from a chromedriver download. (click to expand)
*** chromedriver version for download = 114.0.5735.90 (Latest)\n\nDownloading chromedriver_mac_arm64.zip from:\nhttps://chromedriver.storage.googleapis.com/114.0.5735.90/chromedriver_mac_arm64.zip ...\nDownload Complete!\n\nExtracting ['chromedriver'] from chromedriver_mac_arm64.zip ...\nUnzip Complete!\n\nThe file [chromedriver] was saved to:\n/Users/michael/github/SeleniumBase/seleniumbase/drivers/chromedriver\n\nMaking [chromedriver 114.0.5735.90] executable ...\n[chromedriver 114.0.5735.90] is now ready for use!\n

Basic Example / Usage:

\ud83d\udd35 If you've cloned SeleniumBase, you can run tests from the examples/ folder.

Here's my_first_test.py:

cd examples/\npytest my_first_test.py\n

(Uses --chrome by default.)

SeleniumBase easily handles login, shopping, and checkout.

Here's the code for my_first_test.py:

from seleniumbase import BaseCase\nBaseCase.main(__name__, __file__)\n\nclass MyTestClass(BaseCase):\n    def test_swag_labs(self):\n        self.open(\"https://www.saucedemo.com\")\n        self.type(\"#user-name\", \"standard_user\")\n        self.type(\"#password\", \"secret_sauce\\n\")\n        self.assert_element(\"div.inventory_list\")\n        self.assert_exact_text(\"Products\", \"span.title\")\n        self.click('button[name*=\"backpack\"]')\n        self.click(\"#shopping_cart_container a\")\n        self.assert_exact_text(\"Your Cart\", \"span.title\")\n        self.assert_text(\"Backpack\", \"div.cart_item\")\n        self.click(\"button#checkout\")\n        self.type(\"#first-name\", \"SeleniumBase\")\n        self.type(\"#last-name\", \"Automation\")\n        self.type(\"#postal-code\", \"77123\")\n        self.click(\"input#continue\")\n        self.assert_text(\"Checkout: Overview\")\n        self.assert_text(\"Backpack\", \"div.cart_item\")\n        self.assert_text(\"29.99\", \"div.inventory_item_price\")\n        self.click(\"button#finish\")\n        self.assert_exact_text(\"Thank you for your order!\", \"h2\")\n        self.assert_element('img[alt=\"Pony Express\"]')\n        self.js_click(\"a#logout_sidebar_link\")\n        self.assert_element(\"div#login_button_container\")\n

Here are some common SeleniumBase methods:
self.open(url)  # Navigate the browser window to the URL.\nself.type(selector, text)  # Update the field with the text.\nself.click(selector)  # Click the element with the selector.\nself.click_link(link_text)  # Click the link containing text.\nself.go_back()  # Navigate back to the previous URL.\nself.select_option_by_text(dropdown_selector, option)\nself.hover_and_click(hover_selector, click_selector)\nself.drag_and_drop(drag_selector, drop_selector)\nself.get_text(selector)  # Get the text from the element.\nself.get_current_url()  # Get the URL of the current page.\nself.get_page_source()  # Get the HTML of the current page.\nself.get_attribute(selector, attribute)  # Get element attribute.\nself.get_title()  # Get the title of the current page.\nself.switch_to_frame(frame)  # Switch into the iframe container.\nself.switch_to_default_content()  # Leave the iframe container.\nself.open_new_window()  # Open a new window in the same browser.\nself.switch_to_window(window)  # Switch to the browser window.\nself.switch_to_default_window()  # Switch to the original window.\nself.get_new_driver(OPTIONS)  # Open a new driver with OPTIONS.\nself.switch_to_driver(driver)  # Switch to the browser driver.\nself.switch_to_default_driver()  # Switch to the original driver.\nself.wait_for_element(selector)  # Wait until element is visible.\nself.is_element_visible(selector)  # Return element visibility.\nself.is_text_visible(text, selector)  # Return text visibility.\nself.sleep(seconds)  # Do nothing for the given amount of time.\nself.save_screenshot(name)  # Save a screenshot in .png format.\nself.assert_element(selector)  # Verify the element is visible.\nself.assert_text(text, selector)  # Verify text in the element.\nself.assert_exact_text(text, selector)  # Verify text is exact.\nself.assert_title(title)  # Verify the title of the web page.\nself.assert_downloaded_file(file)  # Verify file was downloaded.\nself.assert_no_404_errors()  # Verify there are no broken links.\nself.assert_no_js_errors()  # Verify there are no JS errors.\n

\ud83d\udd35 For the complete list of SeleniumBase methods, see: Method Summary

Fun Facts / Learn More:

\u2705 SeleniumBase automatically handles common WebDriver actions such as launching web browsers before tests, saving screenshots during failures, and closing web browsers after tests.

\u2705 SeleniumBase lets you customize test runs from the command-line.

\u2705 SeleniumBase uses simple syntax for commands. Example:

self.type(\"input\", \"dogs\\n\")  # (The \"\\n\" presses ENTER)\n

Most SeleniumBase scripts can be run with pytest, pynose, or pure python. 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 Syntax Formats) There's also a Gherkin test format that runs with behave.

pytest coffee_cart_tests.py --rs\npytest test_sb_fixture.py --demo\npytest test_suite.py --rs --html=report.html --dashboard\n\npynose basic_test.py --mobile\npynose test_suite.py --headless --report --show-report\n\npython raw_sb.py\npython raw_test_scripts.py\n\nbehave realworld.feature\nbehave calculator.feature -D rs -D dashboard\n

\u2705 pytest includes automatic test discovery. If you don't specify a specific file or folder to run, pytest will automatically search through all subdirectories for tests to run based on the following criteria:

With a SeleniumBase 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.

\u2705 You can do a pre-flight check to see which tests would get discovered by pytest before the actual run:

pytest --co -q\n

\u2705 You can be more specific when calling pytest or pynose on a file:

pytest [FILE_NAME.py]::[CLASS_NAME]::[METHOD_NAME]\n\npynose [FILE_NAME.py]:[CLASS_NAME].[METHOD_NAME]\n

\u2705 No More Flaky Tests! SeleniumBase methods automatically wait for page elements to finish loading before interacting with them (up to a timeout limit). This means you no longer need random time.sleep() statements in your scripts.

\u2705 SeleniumBase supports all major browsers and operating systems:

Browsers: Chrome, Edge, Firefox, and Safari.

Systems: Linux/Ubuntu, macOS, and Windows.

\u2705 SeleniumBase works on all popular CI/CD platforms:

\u2705 SeleniumBase includes an automated/manual hybrid solution called MasterQA to speed up manual testing with automation while manual testers handle validation.

\u2705 SeleniumBase supports running tests while offline (assuming webdrivers have previously been downloaded when online).

\u2705 For a full list of SeleniumBase features, Click Here.

Demo Mode / Debugging:

\ud83d\udd35 Demo Mode helps you see what a test is doing. If a test is moving too fast for your eyes, run it in Demo Mode to pause the browser briefly between actions, highlight page elements being acted on, and display assertions:

pytest my_first_test.py --demo\n

\ud83d\udd35 time.sleep(seconds) can be used to make a test wait at a specific spot:

import time; time.sleep(3)  # Do nothing for 3 seconds.\n

\ud83d\udd35 Debug Mode with Python's built-in pdb library helps you debug tests:

import pdb; pdb.set_trace()\nimport pytest; pytest.set_trace()\nbreakpoint()  # Shortcut for \"import pdb; pdb.set_trace()\"\n

(pdb commands: n, c, s, u, d => next, continue, step, up, down)

\ud83d\udd35 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:

pytest test_fail.py --pdb\n

\ud83d\udd35 To start tests in Debug Mode, add --trace as a pytest option:

pytest test_coffee_cart.py --trace\n

\ud83d\udd35 Command-line Options:

\u2705 Here are some useful command-line options that come with pytest:

-v  # Verbose mode. Prints the full name of each test and shows more details.\n-q  # Quiet mode. Print fewer details in the console output when running tests.\n-x  # Stop running the tests after the first failure is reached.\n--html=report.html  # Creates a detailed pytest-html report after tests finish.\n--co | --collect-only  # Show what tests would get run. (Without running them)\n--co -q  # (Both options together!) - Do a dry run with full test names shown.\n-n=NUM  # Multithread the tests using that many threads. (Speed up test runs!)\n-s  # See print statements. (Should be on by default with pytest.ini present.)\n--junit-xml=report.xml  # Creates a junit-xml report after tests finish.\n--pdb  # If a test fails, enter Post Mortem Debug Mode. (Don't use with CI!)\n--trace  # Enter Debug Mode at the beginning of each test. (Don't use with CI!)\n-m=MARKER  # Run tests with the specified pytest marker.\n

\u2705 SeleniumBase provides additional pytest command-line options for tests:

--browser=BROWSER  # (The web browser to use. Default: \"chrome\".)\n--chrome  # (Shortcut for \"--browser=chrome\". On by default.)\n--edge  # (Shortcut for \"--browser=edge\".)\n--firefox  # (Shortcut for \"--browser=firefox\".)\n--safari  # (Shortcut for \"--browser=safari\".)\n--settings-file=FILE  # (Override default SeleniumBase settings.)\n--env=ENV  # (Set the test env. Access with \"self.env\" in tests.)\n--account=STR  # (Set account. Access with \"self.account\" in tests.)\n--data=STRING  # (Extra test data. Access with \"self.data\" in tests.)\n--var1=STRING  # (Extra test data. Access with \"self.var1\" in tests.)\n--var2=STRING  # (Extra test data. Access with \"self.var2\" in tests.)\n--var3=STRING  # (Extra test data. Access with \"self.var3\" in tests.)\n--variables=DICT  # (Extra test data. Access with \"self.variables\".)\n--user-data-dir=DIR  # (Set the Chrome user data directory to use.)\n--protocol=PROTOCOL  # (The Selenium Grid protocol: http|https.)\n--server=SERVER  # (The Selenium Grid server/IP used for tests.)\n--port=PORT  # (The Selenium Grid port used by the test server.)\n--cap-file=FILE  # (The web browser's desired capabilities to use.)\n--cap-string=STRING  # (The web browser's desired capabilities to use.)\n--proxy=SERVER:PORT  # (Connect to a proxy server:port as tests are running)\n--proxy=USERNAME:PASSWORD@SERVER:PORT  # (Use an authenticated proxy server)\n--proxy-bypass-list=STRING # (\";\"-separated hosts to bypass, Eg \"*.foo.com\")\n--proxy-pac-url=URL  # (Connect to a proxy server using a PAC_URL.pac file.)\n--proxy-pac-url=USERNAME:PASSWORD@URL  # (Authenticated proxy with PAC URL.)\n--proxy-driver  # (If a driver download is needed, will use: --proxy=PROXY.)\n--multi-proxy  # (Allow multiple authenticated proxies when multi-threaded.)\n--agent=STRING  # (Modify the web browser's User-Agent string.)\n--mobile  # (Use the mobile device emulator while running tests.)\n--metrics=STRING  # (Set mobile metrics: \"CSSWidth,CSSHeight,PixelRatio\".)\n--chromium-arg=\"ARG=N,ARG2\"  # (Set Chromium args, \",\"-separated, no spaces.)\n--firefox-arg=\"ARG=N,ARG2\"  # (Set Firefox args, comma-separated, no spaces.)\n--firefox-pref=SET  # (Set a Firefox preference:value set, comma-separated.)\n--extension-zip=ZIP  # (Load a Chrome Extension .zip|.crx, comma-separated.)\n--extension-dir=DIR  # (Load a Chrome Extension directory, comma-separated.)\n--binary-location=PATH  # (Set path of the Chromium browser binary to use.)\n--driver-version=VER  # (Set the chromedriver or uc_driver version to use.)\n--sjw  # (Skip JS Waits for readyState to be \"complete\" or Angular to load.)\n--pls=PLS  # (Set pageLoadStrategy on Chrome: \"normal\", \"eager\", or \"none\".)\n--headless  # (Run tests in headless mode. The default arg on Linux OS.)\n--headless2  # (Use the new headless mode, which supports extensions.)\n--headed  # (Run tests in headed/GUI mode on Linux OS, where not default.)\n--xvfb  # (Run tests using the Xvfb virtual display server on Linux OS.)\n--locale=LOCALE_CODE  # (Set the Language Locale Code for the web browser.)\n--interval=SECONDS  # (The autoplay interval for presentations & tour steps)\n--start-page=URL  # (The starting URL for the web browser when tests begin.)\n--archive-logs  # (Archive existing log files instead of deleting them.)\n--archive-downloads  # (Archive old downloads instead of deleting them.)\n--time-limit=SECONDS  # (Safely fail any test that exceeds the time limit.)\n--slow  # (Slow down the automation. Faster than using Demo Mode.)\n--demo  # (Slow down and visually see test actions as they occur.)\n--demo-sleep=SECONDS  # (Set the wait time after Slow & Demo Mode actions.)\n--highlights=NUM  # (Number of highlight animations for Demo Mode actions.)\n--message-duration=SECONDS  # (The time length for Messenger alerts.)\n--check-js  # (Check for JavaScript errors after page loads.)\n--ad-block  # (Block some types of display ads from loading.)\n--block-images  # (Block images from loading during tests.)\n--do-not-track  # (Indicate to websites that you don't want to be tracked.)\n--verify-delay=SECONDS  # (The delay before MasterQA verification checks.)\n--recorder  # (Enables the Recorder for turning browser actions into code.)\n--rec-behave  # (Same as Recorder Mode, but also generates behave-gherkin.)\n--rec-sleep  # (If the Recorder is enabled, also records self.sleep calls.)\n--rec-print  # (If the Recorder is enabled, prints output after tests end.)\n--disable-js  # (Disable JavaScript on websites. Pages might break!)\n--disable-csp  # (Disable the Content Security Policy of websites.)\n--disable-ws  # (Disable Web Security on Chromium-based browsers.)\n--enable-ws  # (Enable Web Security on Chromium-based browsers.)\n--enable-sync  # (Enable \"Chrome Sync\" on websites.)\n--uc | --undetected  # (Use undetected-chromedriver to evade bot-detection.)\n--uc-cdp-events  # (Capture CDP events when running in \"--undetected\" mode.)\n--remote-debug  # (Sync to Chrome Remote Debugger chrome://inspect/#devices)\n--final-debug  # (Enter Debug Mode after each test ends. Don't use with CI!)\n--dashboard  # (Enable the SeleniumBase Dashboard. Saved at: dashboard.html)\n--dash-title=STRING  # (Set the title shown for the generated dashboard.)\n--enable-3d-apis  # (Enables WebGL and 3D APIs.)\n--swiftshader  # (Use Chrome's \"--use-gl=swiftshader\" feature.)\n--incognito  # (Enable Chrome's Incognito mode.)\n--guest  # (Enable Chrome's Guest mode.)\n--dark  # (Enable Chrome's Dark mode.)\n--devtools  # (Open Chrome's DevTools when the browser opens.)\n--rs | --reuse-session  # (Reuse browser session for all tests.)\n--rcs | --reuse-class-session  # (Reuse session for tests in class.)\n--crumbs  # (Delete all cookies between tests reusing a session.)\n--disable-beforeunload  # (Disable the \"beforeunload\" event on Chrome.)\n--window-size=WIDTH,HEIGHT  # (Set the browser's starting window size.)\n--maximize  # (Start tests with the browser window maximized.)\n--screenshot  # (Save a screenshot at the end of each test.)\n--no-screenshot  # (No screenshots saved unless tests directly ask it.)\n--visual-baseline  # (Set the visual baseline for Visual/Layout tests.)\n--wire  # (Use selenium-wire's webdriver for replacing selenium webdriver.)\n--external-pdf  # (Set Chromium \"plugins.always_open_pdf_externally\":True.)\n--timeout-multiplier=MULTIPLIER  # (Multiplies the default timeout values.)\n--list-fail-page  # (After each failing test, list the URL of the failure.)\n

(See the full list of command-line option definitions here. For detailed examples of command-line options, see customizing_test_runs.md)

\ud83d\udd35 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, 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.

cd examples/\n\npytest test_suite.py --chrome\n\npytest test_suite.py --firefox\n

An easy way to override seleniumbase/config/settings.py is by using a custom settings file. Here's the command-line option to add to tests: (See examples/custom_settings.py) --settings_file=custom_settings.py (Settings include default timeout values, a two-factor auth key, DB credentials, S3 credentials, and other important settings used by tests.)

\ud83d\udd35 To pass additional data from the command-line to tests, add --data=\"ANY STRING\". Inside your tests, you can use self.data to access that.

Directory Configuration:

\ud83d\udd35 When running tests with pytest, you'll want a copy of pytest.ini in your root folders. When running tests with pynose, you'll want a copy of setup.cfg in your root folders. These files specify default configuration details for tests. Test folders should also include a blank init.py file to allow your test files to import other files from that folder.

\ud83d\udd35 sbase mkdir DIR creates a folder with config files and sample tests:

sbase mkdir ui_tests\n

That new folder will have these files:

ui_tests/\n\u251c\u2500\u2500 __init__.py\n\u251c\u2500\u2500 my_first_test.py\n\u251c\u2500\u2500 parameterized_test.py\n\u251c\u2500\u2500 pytest.ini\n\u251c\u2500\u2500 requirements.txt\n\u251c\u2500\u2500 setup.cfg\n\u251c\u2500\u2500 test_demo_site.py\n\u2514\u2500\u2500 boilerplates/\n    \u251c\u2500\u2500 __init__.py\n    \u251c\u2500\u2500 base_test_case.py\n    \u251c\u2500\u2500 boilerplate_test.py\n    \u251c\u2500\u2500 classic_obj_test.py\n    \u251c\u2500\u2500 page_objects.py\n    \u251c\u2500\u2500 sb_fixture_test.py\n    \u2514\u2500\u2500 samples/\n        \u251c\u2500\u2500 __init__.py\n        \u251c\u2500\u2500 google_objects.py\n        \u251c\u2500\u2500 google_test.py\n        \u251c\u2500\u2500 sb_swag_test.py\n        \u2514\u2500\u2500 swag_labs_test.py\n

ProTip\u2122: You can also create a boilerplate folder without any sample tests in it by adding -b or --basic to the sbase mkdir command:

sbase mkdir ui_tests --basic\n

That new folder will have these files:

ui_tests/\n\u251c\u2500\u2500 __init__.py\n\u251c\u2500\u2500 pytest.ini\n\u251c\u2500\u2500 requirements.txt\n\u2514\u2500\u2500 setup.cfg\n

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).

Log files from failed tests:

Let's try an example of a test that fails:

\"\"\" test_fail.py \"\"\"\nfrom seleniumbase import BaseCase\nBaseCase.main(__name__, __file__)\n\nclass MyTestClass(BaseCase):\n\n    def test_find_army_of_robots_on_xkcd_desert_island(self):\n        self.open(\"https://xkcd.com/731/\")\n        self.assert_element(\"div#ARMY_OF_ROBOTS\", timeout=1)  # This should fail\n

You can run it from the examples/ folder like this:

pytest test_fail.py\n

\ud83d\udd35 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, 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.

SeleniumBase Dashboard:

\ud83d\udd35 The --dashboard option for pytest generates a SeleniumBase Dashboard located at dashboard.html, which updates automatically as tests run and produce results. Example:

pytest --dashboard --rs --headless\n

\ud83d\udd35 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:

python -m http.server 1948\n

\ud83d\udd35 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.)

\ud83d\udd35 Here's a full example of what the SeleniumBase Dashboard may look like:

pytest test_suite.py --dashboard --rs --headless\n

Generating Test Reports: \ud83d\udd35 Pytest Reports:

\u2705 Using --html=report.html gives you a fancy report of the name specified after your test suite completes.

pytest test_suite.py --html=report.html\n

\u2705 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.

\u2705 Here's an example of an upgraded html report:

pytest test_suite.py --dashboard --html=report.html\n

If viewing pytest html reports in Jenkins, you may need to configure Jenkins settings for the html to render correctly. This is due to Jenkins CSP changes.

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.

pytest test_suite.py --junit-xml=report.xml\n
\ud83d\udd35 pynose Reports:

The --report option gives you a fancy report after your test suite completes.

pynose test_suite.py --report\n

(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.)

\ud83d\udd35 Behave Dashboard & Reports: (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.)
behave behave_bdd/features/ -D dashboard -D headless\n
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.
behave behave_bdd/features/ --junit -D rs -D headless\n
\ud83d\udd35 Allure Reports: See: [https://docs.qameta.io/allure/](https://docs.qameta.io/allure/#_pytest) SeleniumBase no longer includes ``allure-pytest`` as part of installed dependencies. If you want to use it, install it first:
pip install allure-pytest\n
Now your tests can create Allure results files, which can be processed by Allure Reports.
pytest test_suite.py --alluredir=allure_results\n
-------- Using a Proxy Server: If you wish to use a proxy server for your browser tests (Chromium or Firefox), you can add ``--proxy=IP_ADDRESS:PORT`` as an argument on the command line.
pytest proxy_test.py --proxy=IP_ADDRESS:PORT\n
If the proxy server that you wish to use requires authentication, you can do the following (Chromium only):
pytest proxy_test.py --proxy=USERNAME:PASSWORD@IP_ADDRESS:PORT\n
SeleniumBase also supports SOCKS4 and SOCKS5 proxies:
pytest proxy_test.py --proxy=\"socks4://IP_ADDRESS:PORT\"\n\npytest proxy_test.py --proxy=\"socks5://IP_ADDRESS:PORT\"\n
To make things easier, you can add your frequently-used proxies to PROXY_LIST in [proxy_list.py](https://github.com/seleniumbase/SeleniumBase/blob/master/seleniumbase/config/proxy_list.py), and then use ``--proxy=KEY_FROM_PROXY_LIST`` to use the IP_ADDRESS:PORT of that key.
pytest proxy_test.py --proxy=proxy1\n
Changing the User-Agent: \ud83d\udd35 If you wish to change the User-Agent for your browser tests (Chromium and Firefox only), you can add ``--agent=\"USER AGENT STRING\"`` as an argument on the command-line.
pytest user_agent_test.py --agent=\"Mozilla/5.0 (Nintendo 3DS; U; ; en) Version/1.7412.EU\"\n
Handling Pop-Up / Pop Up Alerts: \ud83d\udd35 self.accept_alert() automatically waits for and accepts alert pop-ups. self.dismiss_alert() automatically waits for and dismisses alert pop-ups. On occasion, some methods like self.click(SELECTOR) might dismiss a pop-up on its own because they call JavaScript to make sure that the readyState of the page is complete before advancing. If you're trying to accept a pop-up that got dismissed this way, use this workaround: Call self.find_element(SELECTOR).click() instead, (which will let the pop-up remain on the screen), and then use self.accept_alert() to accept the pop-up (more on that here). If pop-ups are intermittent, wrap code in a try/except block. Building Guided Tours for Websites: \ud83d\udd35 Learn about SeleniumBase Interactive Walkthroughs (in the ``examples/tour_examples/`` folder). It's great for prototyping a website onboarding experience. -------- Production Environments & Integrations: \u25b6\ufe0f Here are some things you can do to set up a production environment for your testing. (click to expand) Here's an example of running tests with some additional features enabled:
pytest [YOUR_TEST_FILE.py] --with-db-reporting --with-s3-logging\n
Detailed Method Specifications and Examples: \ud83d\udd35 **Navigating to a web page: (and related commands)**
self.open(\"https://xkcd.com/378/\")  # This method opens the specified page.\n\nself.go_back()  # This method navigates the browser to the previous page.\n\nself.go_forward()  # This method navigates the browser forward in history.\n\nself.refresh_page()  # This method reloads the current page.\n\nself.get_current_url()  # This method returns the current page URL.\n\nself.get_page_source()  # This method returns the current page source.\n
ProTip\u2122: You can use the self.get_page_source() method with Python's find() command to parse through HTML to find something specific. (For more advanced parsing, see the BeautifulSoup example.)
source = self.get_page_source()\nhead_open_tag = source.find('<head>')\nhead_close_tag = source.find('</head>', head_open_tag)\neverything_inside_head = source[head_open_tag+len('<head>'):head_close_tag]\n
\ud83d\udd35 **Clicking:** To click an element on the page:
self.click(\"div#my_id\")\n
**ProTip\u2122:** 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. \ud83d\udd35 **Typing Text:** self.type(selector, text) # 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:
self.type(\"input#id_value\", \"2012\")\n
You can also use self.add_text() or the WebDriver .send_keys() command, but those won't clear the text box first if there's already text inside. \ud83d\udd35 **Getting the text from an element on a page:**
text = self.get_text(\"header h2\")\n
\ud83d\udd35 **Getting the attribute value from an element on a page:**
attribute = self.get_attribute(\"#comic img\", \"title\")\n
\ud83d\udd35 **Asserting existence of an element on a page within some number of seconds:**
self.wait_for_element_present(\"div.my_class\", timeout=10)\n
(NOTE: You can also use: ``self.assert_element_present(ELEMENT)``) \ud83d\udd35 **Asserting visibility of an element on a page within some number of seconds:**
self.wait_for_element_visible(\"a.my_class\", timeout=5)\n
(NOTE: The short versions of that are ``self.find_element(ELEMENT)`` and ``self.assert_element(ELEMENT)``. The ``find_element()`` version returns the element.) Since the line above returns the element, you can combine that with ``.click()`` as shown below:
self.find_element(\"a.my_class\", timeout=5).click()\n\n# But you're better off using the following statement, which does the same thing\nself.click(\"a.my_class\")  # DO IT THIS WAY!\n
**ProTip\u2122:** You can use dots to signify class names (Ex: ``div.class_name``) as a simplified version of ``div[class=\"class_name\"]`` within a CSS selector. You can also use ``*=`` to search for any partial value in a CSS selector as shown below:
self.click('a[name*=\"partial_name\"]')\n
\ud83d\udd35 **Asserting visibility of text inside an element on a page within some number of seconds:**
self.assert_text(\"Make it so!\", \"div#trek div.picard div.quotes\")\nself.assert_text(\"Tea. Earl Grey. Hot.\", \"div#trek div.picard div.quotes\", timeout=3)\n
(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.) \ud83d\udd35 **Asserting Anything:**
self.assert_true(var1 == var2)\n\nself.assert_false(var1 == var2)\n\nself.assert_equal(var1, var2)\n
\ud83d\udd35 **Useful Conditional Statements: (with creative examples)** \u2753 ``is_element_visible(selector):`` (visible on the page)
if self.is_element_visible('div#warning'):\n    print(\"Red Alert: Something bad might be happening!\")\n
\u2753 ``is_element_present(selector):`` (present in the HTML)
if self.is_element_present('div#top_secret img.tracking_cookie'):\n    self.contact_cookie_monster()  # Not a real SeleniumBase method\nelse:\n    current_url = self.get_current_url()\n    self.contact_the_nsa(url=current_url, message=\"Dark Zone Found\")  # Not a real SeleniumBase method\n
def is_there_a_cloaked_klingon_ship_on_this_page():\n    if self.is_element_present(\"div.ships div.klingon\"):\n        return not self.is_element_visible(\"div.ships div.klingon\")\n    return False\n
\u2753 ``is_text_visible(text, selector):`` (text visible on element)
if self.is_text_visible(\"You Shall Not Pass!\", \"h1\"):\n    self.open(\"https://www.youtube.com/watch?v=3xYXUeSmb-Y\")\n
\u25b6\ufe0f Click for a longer example of is_text_visible():
def get_mirror_universe_captain_picard_superbowl_ad(superbowl_year):\n    selector = \"div.superbowl_%s div.commercials div.transcript div.picard\" % superbowl_year\n    if self.is_text_visible(\"Yes, it was I who summoned you all here.\", selector):\n        return \"Picard Paramount+ Superbowl Ad 2020\"\n    elif self.is_text_visible(\"Commander, signal the following: Our Network is Secure!\"):\n        return \"Picard Mirror Universe iboss Superbowl Ad 2018\"\n    elif self.is_text_visible(\"For the Love of Marketing and Earl Grey Tea!\", selector):\n        return \"Picard Mirror Universe HubSpot Superbowl Ad 2015\"\n    elif self.is_text_visible(\"Delivery Drones... Engage\", selector):\n        return \"Picard Mirror Universe Amazon Superbowl Ad 2015\"\n    elif self.is_text_visible(\"Bing it on Screen!\", selector):\n        return \"Picard Mirror Universe Microsoft Superbowl Ad 2015\"\n    elif self.is_text_visible(\"OK Glass, Make it So!\", selector):\n        return \"Picard Mirror Universe Google Superbowl Ad 2015\"\n    elif self.is_text_visible(\"Number One, I've Never Seen Anything Like It.\", selector):\n        return \"Picard Mirror Universe Tesla Superbowl Ad 2015\"\n    elif self.is_text_visible(\"Let us make sure history never forgets the name ... Facebook\", selector):\n        return \"Picard Mirror Universe Facebook Superbowl Ad 2015\"\n    elif self.is_text_visible(\"\"\"With the first link, the chain is forged.\n                              The first speech censored, the first thought forbidden,\n                              the first freedom denied, chains us all irrevocably.\"\"\", selector):\n        return \"Picard Mirror Universe Wikimedia Superbowl Ad 2015\"\n    else:\n        raise Exception(\"Reports of my assimilation are greatly exaggerated.\")\n
\u2753 ``is_link_text_visible(link_text):``
if self.is_link_text_visible(\"Stop! Hammer time!\"):\n    self.click_link(\"Stop! Hammer time!\")\n
\ud83d\udd35 Switching Tabs:

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 about:blank URLs.)

self.switch_to_window(1)  # This switches to the new tab (0 is the first one)\n
\ud83d\udd35 How to handle iframes: \ud83d\udd35 iframes follow the same principle as new windows: You must first switch to the iframe if you want to perform actions in there:
self.switch_to_frame(\"iframe\")\n# ... Now perform actions inside the iframe\nself.switch_to_parent_frame()  # Exit the current iframe\n
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()``.)
self.switch_to_frame('iframe[name=\"frame1\"]')\nself.switch_to_frame('iframe[name=\"frame2\"]')\n# ... Now perform actions inside the inner iframe\nself.switch_to_default_content()  # Back to the main page\n
\ud83d\udd35 You can also use a context manager to act inside iframes:
with self.frame_switch(\"iframe\"):\n    # ... Now perform actions while inside the code block\n# You have left the iframe\n
This also works with nested iframes:
with self.frame_switch('iframe[name=\"frame1\"]'):\n    with self.frame_switch('iframe[name=\"frame2\"]'):\n        # ... Now perform actions while inside the code block\n    # You are now back inside the first iframe\n# You have left all the iframes\n
\ud83d\udd35 How to execute custom jQuery scripts:

jQuery is a powerful JavaScript library that allows you to perform advanced actions in a web browser. If the web page you're on already has jQuery loaded, you can start executing jQuery scripts immediately. You'd know this because the web page would contain something like the following in the HTML:

<script src=\"https://ajax.googleapis.com/ajax/libs/jquery/3.6.3/jquery.min.js\"></script>\n
\ud83d\udd35 It's OK if you want to use jQuery on a page that doesn't have it loaded yet. To do so, run the following command first:
self.activate_jquery()\n
\u25b6\ufe0f Here are some examples of using jQuery in your scripts. (click to expand)
self.execute_script(\"jQuery, window.scrollTo(0, 600)\")  # Scrolling the page\n\nself.execute_script(\"jQuery('#annoying-widget').hide()\")  # Hiding elements on a page\n\nself.execute_script(\"jQuery('#hidden-widget').show(0)\")  # Showing hidden elements on a page\n\nself.execute_script(\"jQuery('#annoying-button a').remove()\")  # Removing elements on a page\n\nself.execute_script(\"jQuery('%s').mouseover()\" % (mouse_over_item))  # Mouse-over elements on a page\n\nself.execute_script(\"jQuery('input#the_id').val('my_text')\")  # Fast text input on a page\n\nself.execute_script(\"jQuery('div#dropdown a.link').click()\")  # Click elements on a page\n\nself.execute_script(\"return jQuery('div#amazing')[0].text\")  # Returns the css \"text\" of the element given\n\nself.execute_script(\"return jQuery('textarea')[2].value\")  # Returns the css \"value\" of the 3rd textarea element on the page\n
(Most of the above commands can be done directly with built-in SeleniumBase methods.) \ud83d\udd35 How to handle a restrictive CSP: \u2757 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. \ud83d\udd35 More JavaScript fun: \u25b6\ufe0f In this example, JavaScript creates a referral button on a page, which is then clicked. (click to expand)
start_page = \"https://xkcd.com/465/\"\ndestination_page = \"https://github.com/seleniumbase/SeleniumBase\"\nself.open(start_page)\nreferral_link = '''<a class='analytics test' href='%s'>Free-Referral Button!</a>''' % destination_page\nself.execute_script('''document.body.innerHTML = \\\"%s\\\"''' % referral_link)\nself.click(\"a.analytics\")  # Clicks the generated button\n
(Due to popular demand, this traffic generation example has been included in SeleniumBase with the self.generate_referral(start_page, end_page) and the self.generate_traffic(start_page, end_page, loops) methods.) \ud83d\udd35 How to use deferred asserts:

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:

from seleniumbase import BaseCase\nBaseCase.main(__name__, __file__)\n\nclass MyTestClass(BaseCase):\n    def test_deferred_asserts(self):\n        self.open('https://xkcd.com/993/')\n        self.wait_for_element('#comic')\n        self.deferred_assert_element('img[alt=\"Brand Identity\"]')\n        self.deferred_assert_element('img[alt=\"Rocket Ship\"]')  # Will Fail\n        self.deferred_assert_element('#comicmap')\n        self.deferred_assert_text('Fake Item', '#middleContainer')  # Will Fail\n        self.deferred_assert_text('Random', '#middleContainer')\n        self.deferred_assert_element('a[name=\"Super Fake !!!\"]')  # Will Fail\n        self.process_deferred_asserts()\n
deferred_assert_element() and deferred_assert_text() will save any exceptions that would be raised. To flush out all the failed deferred asserts into a single exception, make sure to call self.process_deferred_asserts() at the end of your test method. If your test hits multiple pages, you can call self.process_deferred_asserts() before navigating to a new page so that the screenshot from your log files matches the URL where the deferred asserts were made. \ud83d\udd35 How to access raw WebDriver:

If you need access to any commands that come with standard WebDriver, you can call them directly like this:

self.driver.delete_all_cookies()\ncapabilities = self.driver.capabilities\nself.driver.find_elements(\"partial link text\", \"GitHub\")\n
(In general, you'll want to use the SeleniumBase versions of methods when available.) \ud83d\udd35 How to retry failing tests automatically:

You can use pytest --reruns=NUM to retry failing tests that many times. Add --reruns-delay=SECONDS to wait that many seconds between retries. Example:

pytest --reruns=1 --reruns-delay=1\n

You can use the @retry_on_exception() decorator to retry failing methods. (First import: from seleniumbase import decorators). To learn more about SeleniumBase decorators, click here.

-------- > \"Catch bugs in QA before deploying code to Production!\"

-------- Wrap-Up

If you see something, say something!

https://github.com/mdmintz

--------

"}, {"location": "examples/ReadMe/", "title": "\ud83d\udcda Running Example Tests", "text": ""}, {"location": "examples/ReadMe/#example-tests", "title": "Example Tests", "text": "

(NOTE: Some example tests fail on purpose to demonstrate logging features.)

Example tests with run commands to help you get started:

Run an example test: (Default option: --chrome)

pytest test_demo_site.py\n

Run an example test in Firefox:

pytest my_first_test.py --browser=firefox\n

Run an example test in --demo mode: (highlight assertions)

pytest test_swag_labs.py --demo\n

Run test_coffee_cart.py to test the Coffee Cart app:

pytest test_coffee_cart.py --demo\n

Run a Wordle-solver example:

pytest wordle_test.py\n

Run an example test in --headless mode: (invisible browser)

pytest my_first_test.py --headless\n

Run an example test using Chrome's mobile device emulator: (default settings)

pytest test_swag_labs.py --mobile\n

Run an example test in --demo mode: (highlight assertions)

pytest test_xkcd.py --demo\n

Run a test suite with verbose output: (see more details)

pytest test_suite.py -v\n

Run a test suite using multiple parallel processes (-n=NUM):

pytest test_suite.py -n=8\n

Run a parameterized test: (Generates multiple tests from one)

pytest parameterized_test.py -v\n

Run a test suite and generate a SeleniumBase Dashboard:

pytest test_suite.py --dashboard\n

Run a test suite and generate a pytest report:

pytest test_suite.py --html=report.html\n

Run a failing test: (See the latest_logs/ folder for logs and screenshots)

pytest test_fail.py\n

Run a failing test that activates pdb debug mode on failure:

pytest test_fail.py --pdb -s\n

(pdb commands: n, c, s, u, d => next, continue, step, up, down)

Run a test suite that demonstrates the use of pytest markers:

pytest -m marker_test_suite -v\n

Run a test suite that reuses the browser session between tests:

pytest test_suite.py --rs\n

Run an example test demonstrating the rate_limited Python decorator:

pytest rate_limiting_test.py\n

Run an example test that demonstrates how to upload a file to a website:

pytest upload_file_test.py\n

\ud83c\udf96\ufe0f SeleniumBase Commander is a GUI for pytest:

sbase gui\n

SeleniumBase tests can also be run with pynose:

pynose my_first_test.py\n

Run an example test suite and generate a pynose test report:

pynose test_suite.py --report --show-report\n

Run an example test using a pynose configuration file:

pynose my_first_test.py --config=example_config.cfg\n

For more advanced run commands, such as using a proxy server, see ../help_docs/customizing_test_runs.md

If you just need to perform some quick website verification on various devices, you can use the SeleniumBase Device Farm. Just plug in a website URL, and it will display how the website looks on four different devices:

To make things easier, here's a simple GUI program that allows you to run a few example tests by pressing a button:

python gui_test_runner.py\n

(The newer SeleniumBase Commander improves on that.)

"}, {"location": "examples/behave_bdd/ReadMe/", "title": "\ud83d\udc1d Behave-BDD ReadMe", "text": ""}, {"location": "examples/behave_bdd/ReadMe/#behave-test-runner-for-seleniumbase", "title": "\ud83d\udc1d Behave test runner for SeleniumBase \ud83d\udc1d", "text": "

\ud83d\udc1d (Utilizes the Behave BDD Python library. For more info, see the Behave tutorial and read about Behave's Gherkin model.)

\ud83d\udc1d Behave examples with SeleniumBase: SeleniumBase/examples/behave_bdd

> cd examples/behave_bdd/\n> behave features/realworld.feature -T -D dashboard -k\n\nDashboard: /Users/michael/github/SeleniumBase/examples/behave_bdd/dashboard.html\n********************************************************************************\nFeature: SeleniumBase scenarios for the RealWorld App # features/realworld.feature:1\n\nScenario: Verify RealWorld App (log in / sign out)  # features/realworld.feature:3\nGiven Open \"seleniumbase.io/realworld/login\"      # ../../sbase/steps.py:10\nAnd Clear Session Storage                         # ../../sbase/steps.py:669\nWhen Type \"demo_user\" into \"#username\"            # ../../sbase/steps.py:40\nAnd Type \"secret_pass\" into \"#password\"           # ../../sbase/steps.py:40\nAnd Do MFA \"GAXG2MTEOR3DMMDG\" into \"#totpcode\"    # ../../sbase/steps.py:322\nThen Assert exact text \"Welcome!\" in \"h1\"         # ../../sbase/steps.py:157\nAnd Highlight \"img#image1\"                        # ../../sbase/steps.py:184\nAnd Click 'a:contains(\"This Page\")'               # ../../sbase/steps.py:27\nAnd Save screenshot to logs                       # ../../sbase/steps.py:239\nWhen Click link \"Sign out\"                        # ../../sbase/steps.py:195\nThen Assert element 'a:contains(\"Sign in\")'       # ../../sbase/steps.py:120\nAnd Assert text \"You have been signed out!\"       # ../../sbase/steps.py:145\n\u2705 Scenario Passed!\n\n- Dashboard: /Users/michael/github/SeleniumBase/examples/behave_bdd/dashboard.html\n--- LogPath: /Users/michael/github/SeleniumBase/examples/behave_bdd/latest_logs/\n==================================================================================\n1 feature passed, 0 failed, 0 skipped\n1 scenario passed, 0 failed, 0 skipped\n12 steps passed, 0 failed, 0 skipped, 0 undefined\nTook 0m4.682s\n

\ud83d\udc1d Another example, which uses higher-level Behave steps to simplify the .feature file:

> cd examples/behave_bdd/\n> behave features/calculator.feature:61 -T -D dashboard -k\n\nDashboard: /Users/michael/github/SeleniumBase/examples/behave_bdd/dashboard.html\n********************************************************************************\nFeature: SeleniumBase scenarios for the Calculator App # features/calculator.feature:1\n\nBackground:   # features/calculator.feature:3\n\nScenario: 7.0 \u00d7 (3 + 3) = 42        # features/calculator.feature:49\nGiven Open the Calculator App     # features/steps/calculator.py:4\nWhen Press C                      # features/steps/calculator.py:9\nAnd Press 7                       # features/steps/calculator.py:79\nAnd Press .                       # features/steps/calculator.py:104\nAnd Press 0                       # features/steps/calculator.py:94\nAnd Press \u00d7                       # features/steps/calculator.py:29\nAnd Press (                       # features/steps/calculator.py:14\nAnd Press 3                       # features/steps/calculator.py:59\nAnd Press +                       # features/steps/calculator.py:39\nAnd Press 3                       # features/steps/calculator.py:59\nAnd Press )                       # features/steps/calculator.py:19\nThen Verify output is \"7.0\u00d7(3+3)\" # features/steps/calculator.py:135\nWhen Press =                      # features/steps/calculator.py:44\nThen Verify output is \"42\"        # features/steps/calculator.py:135\n\u2705 Scenario Passed!\n\n- Dashboard: /Users/michael/github/SeleniumBase/examples/behave_bdd/dashboard.html\n--- LogPath: /Users/michael/github/SeleniumBase/examples/behave_bdd/latest_logs/\n==================================================================================\n1 feature passed, 0 failed, 0 skipped\n1 scenario passed, 0 failed, 8 skipped\n14 steps passed, 0 failed, 60 skipped, 0 undefined\nTook 0m1.672s\n

\ud83d\udc1d\u26aa With the Dashboard enabled, you'll get one of these:

"}, {"location": "examples/behave_bdd/ReadMe/#behave-gherkin-files", "title": "\ud83d\udc1d Behave-Gherkin files", "text": "

\ud83d\udc1d The *.feature files can use any step seen from:

behave --steps-catalog\n

\ud83d\udc1d SeleniumBase includes several pre-made Behave steps, which you can use by creating a Python file with the following line in your features/steps/ directory:

from seleniumbase.behave import steps  # noqa\n

\ud83d\udc1d Inside your features/environment.py file, you should have the following:

from seleniumbase import BaseCase\nfrom seleniumbase.behave import behave_sb\nbehave_sb.set_base_class(BaseCase)  # Accepts a BaseCase subclass\nfrom seleniumbase.behave.behave_sb import before_all  # noqa\nfrom seleniumbase.behave.behave_sb import before_feature  # noqa\nfrom seleniumbase.behave.behave_sb import before_scenario  # noqa\nfrom seleniumbase.behave.behave_sb import before_step  # noqa\nfrom seleniumbase.behave.behave_sb import after_step  # noqa\nfrom seleniumbase.behave.behave_sb import after_scenario  # noqa\nfrom seleniumbase.behave.behave_sb import after_feature  # noqa\nfrom seleniumbase.behave.behave_sb import after_all  # noqa\n

\ud83d\udc1d If you've already created a subclass of BaseCase with custom methods, you can swap BaseCase in with your own subclass, which will allow you to easily use your own custom methods in your Behave step definitions.

\ud83d\udc1d Here's an example Python file in the features/steps/ folder:

from behave import step\n\n\n@step(\"Open the Swag Labs Login Page\")\ndef go_to_swag_labs(context):\n    sb = context.sb\n    sb.open(\"https://www.saucedemo.com\")\n    sb.clear_local_storage()\n\n\n@step(\"Login to Swag Labs with {user}\")\ndef login_to_swag_labs(context, user):\n    sb = context.sb\n    sb.type(\"#user-name\", user)\n    sb.type(\"#password\", \"secret_sauce\\n\")\n\n\n@step(\"Verify that the current user is logged in\")\ndef verify_logged_in(context):\n    sb = context.sb\n    sb.assert_element(\"#header_container\")\n    sb.assert_element(\"#react-burger-menu-btn\")\n    sb.assert_element(\"#shopping_cart_container\")\n\n\n@step('Add \"{item}\" to cart')\ndef add_item_to_cart(context, item):\n    sb = context.sb\n    sb.click('div.inventory_item:contains(\"%s\") button[name*=\"add\"]' % item)\n

\ud83d\udc1d A *.feature file could look like this:

Feature: SeleniumBase scenarios for the Swag Labs App\n\nBackground:\n    Given Open the Swag Labs Login Page\n\nScenario: User can order a backpack from the store\n    When Login to Swag Labs with standard_user\nThen Verify that the current user is logged in\nAnd Save price of \"Backpack\" to <item_price>\nWhen Add \"Backpack\" to Cart\nThen Verify shopping cart badge shows 1 item(s)\nWhen Click on shopping cart icon\nAnd Click Checkout\nAnd Enter checkout info: First, Last, 12345\nAnd Click Continue\nThen Verify 1 \"Backpack\"(s) in cart\nAnd Verify cost of \"Backpack\" is <item_price>\nAnd Verify item total is $29.99\nAnd Verify tax amount is $2.40\nAnd Verify total cost is $32.39\nWhen Click Finish\nThen Verify order complete\nWhen Logout from Swag Labs\nThen Verify on Login page\n

\ud83d\udc1d Here's another example of a *.feature file:

Feature: SeleniumBase scenarios for the RealWorld App\n\nScenario: Verify RealWorld App (log in / sign out)\n    Given Open \"seleniumbase.io/realworld/login\"\nAnd Clear Session Storage\nWhen Type \"demo_user\" into \"#username\"\nAnd Type \"secret_pass\" into \"#password\"\nAnd Do MFA \"GAXG2MTEOR3DMMDG\" into \"#totpcode\"\nThen Assert text \"Welcome!\" in \"h1\"\nAnd Highlight element \"img#image1\"\nAnd Click 'a:contains(\"This Page\")'\nAnd Save screenshot to logs\nWhen Click link \"Sign out\"\nThen Assert element 'a:contains(\"Sign in\")'\nAnd Assert text \"You have been signed out!\"\n

\ud83d\udc1d If there's a test failure, that's easy to spot:

Feature: SeleniumBase scenarios for the Fail Page # features/fail_page.feature:1\n\nScenario: Fail test on purpose to see what happens  # features/fail_page.feature:3\nWhen Open the Fail Page                           # features/steps/fail_page.py:4\nThen Fail test on purpose                         # features/steps/fail_page.py:9\nAssertion Failed: This test fails on purpose!\n      Captured stdout:\n      >>> STEP FAILED:  (#2) Fail test on purpose\nClass / Feature:  SeleniumBase scenarios for the Fail Page\n      Test / Scenario:  Fail test on purpose to see what happens\n\n   \u274c Scenario Failed!\n

\ud83d\udc1d\ud83c\udf96\ufe0f For convenience, the SeleniumBase Behave GUI lets you run behave scripts from a Desktop app.

\ud83d\udc1d\ud83c\udf96\ufe0f To launch it, call sbase behave-gui or sbase gui-behave:

sbase behave-gui\n* Starting the SeleniumBase Behave Commander GUI App...\n

\ud83d\udc1d\ud83c\udf96\ufe0f You can customize the tests that show up there:

sbase behave-gui  # all tests\nsbase behave-gui -i=calculator  # tests with \"calculator\" in the name\nsbase behave-gui features/  # tests located in the \"features/\" folder\nsbase behave-gui features/calculator.feature  # tests in that feature\n
To learn more about SeleniumBase, check out the Docs Site:

All the code is on GitHub:

"}, {"location": "examples/chart_maker/ReadMe/", "title": "\ud83d\udcf6 Chart Maker", "text": ""}, {"location": "examples/chart_maker/ReadMe/#chartmaker", "title": "\ud83d\udcca ChartMaker \ud83d\udcf6 ChartMaker API", "text": "

SeleniumBase ChartMaker lets you use Python to generate HTML charts.

(Click to see a presentation with multiple charts)

Here's how to run a simple pie chart presentation from GitHub => seleniumbase/SeleniumBase/examples/chart_maker:

cd examples/chart_maker\npytest my_chart.py\n

Here's the code for that pie chart presentation (GitHub => seleniumbase/SeleniumBase/examples/chart_maker/my_chart.py):

from seleniumbase import BaseCase\nBaseCase.main(__name__, __file__)\n\nclass MyChartMakerClass(BaseCase):\n    def test_chart_maker(self):\n        self.create_presentation()\n        self.create_pie_chart(title=\"Automated Tests\")\n        self.add_data_point(\"Passed\", 7, color=\"#95d96f\")\n        self.add_data_point(\"Untested\", 2, color=\"#eaeaea\")\n        self.add_data_point(\"Failed\", 1, color=\"#f1888f\")\n        self.add_slide(\"<p>Pie Chart</p>\" + self.extract_chart())\n        self.begin_presentation(filename=\"my_chart.html\")\n

Here's how to run an example presentation with multiple charts:

cd examples/chart_maker\npytest chart_presentation.py\n

Here are screenshots from the examples:

Here's a line chart example:
from seleniumbase import BaseCase\nBaseCase.main(__name__, __file__)\n\nclass MyChartMakerClass(BaseCase):\n    def test_chart_maker(self):\n        self.create_presentation()\n        self.create_line_chart(\n            title=\"Time Outside\", subtitle=\"Last Week\", unit=\"Minutes\")\n        self.add_data_point(\"Sun\", 5)\n        self.add_data_point(\"Mon\", 10)\n        self.add_data_point(\"Tue\", 20)\n        self.add_data_point(\"Wed\", 40)\n        self.add_data_point(\"Thu\", 80)\n        self.add_data_point(\"Fri\", 65)\n        self.add_data_point(\"Sat\", 50)\n        self.add_slide(\"<p>Line Chart</p>\" + self.extract_chart())\n        self.begin_presentation(filename=\"line_chart.html\", interval=8)\n

This example is from test_line_chart.py, which you can run from the examples/chart_maker folder with the following command:

pytest test_line_chart.py\n

Because that presentation above has an interval set to 8, it will automatically advance to the next slide after 8 seconds. (Or exit if there are no more slides.)

For a more advanced example (multiple charts in a presentation):
from seleniumbase import BaseCase\nBaseCase.main(__name__, __file__)\n\nclass MyChartMakerClass(BaseCase):\n    def test_chart_maker_presentation(self):\n        self.create_presentation(theme=\"sky\")\n\n        self.create_pie_chart(title=\"Automated Tests\")\n        self.add_data_point(\"Passed\", 7, color=\"#95d96f\")\n        self.add_data_point(\"Untested\", 2, color=\"#eaeaea\")\n        self.add_data_point(\"Failed\", 1, color=\"#f1888f\")\n        self.add_slide(\"<p>Pie Chart</p>\" + self.extract_chart())\n\n        self.create_bar_chart(title=\"Language\")\n        self.add_data_point(\"Python\", 33, color=\"Orange\")\n        self.add_data_point(\"JavaScript\", 27, color=\"Teal\")\n        self.add_data_point(\"HTML + CSS\", 21, color=\"Purple\")\n        self.add_slide(\"<p>Bar Chart</p>\" + self.extract_chart())\n\n        self.create_column_chart(title=\"Colors\")\n        self.add_data_point(\"Red\", 10, color=\"Red\")\n        self.add_data_point(\"Green\", 25, color=\"Green\")\n        self.add_data_point(\"Blue\", 15, color=\"Blue\")\n        self.add_slide(\"<p>Column Chart</p>\" + self.extract_chart())\n\n        self.create_line_chart(title=\"Last Week's Data\")\n        self.add_data_point(\"Sun\", 5)\n        self.add_data_point(\"Mon\", 10)\n        self.add_data_point(\"Tue\", 20)\n        self.add_data_point(\"Wed\", 40)\n        self.add_data_point(\"Thu\", 80)\n        self.add_data_point(\"Fri\", 65)\n        self.add_data_point(\"Sat\", 50)\n        self.add_slide(\"<p>Line Chart</p>\" + self.extract_chart())\n\n        self.begin_presentation(filename=\"chart_presentation.html\")\n

Here's how to run that example:

cd examples/chart_maker\npytest chart_presentation.py\n

(Press the Right Arrow to advance to the next slide in that chart presentation)

(Click to see a live example of that presentation)

Multi-Series charts can also be created. Try the available examples to learn more.

self.create_pie_chart(\n    chart_name=None, title=None, subtitle=None,\n    data_name=None, unit=None, libs=True):\n\"\"\" Creates a JavaScript pie chart using \"HighCharts\".\n    @Params\n    chart_name - If creating multiple charts,\n                 use this to select which one.\n    title - The title displayed for the chart.\n    subtitle - The subtitle displayed for the chart.\n    data_name - The series name. Useful for multi-series charts.\n                If no data_name, will default to using \"Series 1\".\n    unit - The description label given to the chart's y-axis values.\n    libs - The option to include Chart libraries (JS and CSS files).\n           Should be set to True (default) for the first time creating\n           a chart on a web page. If creating multiple charts on the\n           same web page, you won't need to re-import the libraries\n           when creating additional charts.\n    labels - If True, displays labels on the chart for data points.\n    legend - If True, displays the data point legend on the chart.\n\"\"\"\n
self.create_bar_chart(\n    chart_name=None, title=None, subtitle=None,\n    data_name=None, unit=None, libs=True):\n\"\"\" Creates a JavaScript bar chart using \"HighCharts\".\n    @Params\n    chart_name - If creating multiple charts,\n                 use this to select which one.\n    title - The title displayed for the chart.\n    subtitle - The subtitle displayed for the chart.\n    data_name - The series name. Useful for multi-series charts.\n                If no data_name, will default to using \"Series 1\".\n    unit - The description label given to the chart's y-axis values.\n    libs - The option to include Chart libraries (JS and CSS files).\n           Should be set to True (default) for the first time creating\n           a chart on a web page. If creating multiple charts on the\n           same web page, you won't need to re-import the libraries\n           when creating additional charts.\n    labels - If True, displays labels on the chart for data points.\n    legend - If True, displays the data point legend on the chart.\n\"\"\"\n
self.create_column_chart(\n    chart_name=None, title=None, subtitle=None,\n    data_name=None, unit=None, libs=True):\n\"\"\" Creates a JavaScript column chart using \"HighCharts\".\n    @Params\n    chart_name - If creating multiple charts,\n                 use this to select which one.\n    title - The title displayed for the chart.\n    subtitle - The subtitle displayed for the chart.\n    data_name - The series name. Useful for multi-series charts.\n                If no data_name, will default to using \"Series 1\".\n    unit - The description label given to the chart's y-axis values.\n    libs - The option to include Chart libraries (JS and CSS files).\n           Should be set to True (default) for the first time creating\n           a chart on a web page. If creating multiple charts on the\n           same web page, you won't need to re-import the libraries\n           when creating additional charts.\n    labels - If True, displays labels on the chart for data points.\n    legend - If True, displays the data point legend on the chart.\n\"\"\"\n
self.create_line_chart(\n    chart_name=None, title=None, subtitle=None,\n    data_name=None, unit=None, zero=False, libs=True):\n\"\"\" Creates a JavaScript line chart using \"HighCharts\".\n    @Params\n    chart_name - If creating multiple charts,\n                 use this to select which one.\n    title - The title displayed for the chart.\n    subtitle - The subtitle displayed for the chart.\n    data_name - The series name. Useful for multi-series charts.\n                If no data_name, will default to using \"Series 1\".\n    unit - The description label given to the chart's y-axis values.\n    zero - If True, the y-axis always starts at 0. (Default: False).\n    libs - The option to include Chart libraries (JS and CSS files).\n           Should be set to True (default) for the first time creating\n           a chart on a web page. If creating multiple charts on the\n           same web page, you won't need to re-import the libraries\n           when creating additional charts.\n    labels - If True, displays labels on the chart for data points.\n    legend - If True, displays the data point legend on the chart.\n\"\"\"\n
self.create_area_chart(\n    chart_name=None, title=None, subtitle=None,\n    data_name=None, unit=None, zero=False, libs=True):\n\"\"\" Creates a JavaScript area chart using \"HighCharts\".\n    @Params\n    chart_name - If creating multiple charts,\n                 use this to select which one.\n    title - The title displayed for the chart.\n    subtitle - The subtitle displayed for the chart.\n    data_name - The series name. Useful for multi-series charts.\n                If no data_name, will default to using \"Series 1\".\n    unit - The description label given to the chart's y-axis values.\n    zero - If True, the y-axis always starts at 0. (Default: False).\n    libs - The option to include Chart libraries (JS and CSS files).\n           Should be set to True (default) for the first time creating\n           a chart on a web page. If creating multiple charts on the\n           same web page, you won't need to re-import the libraries\n           when creating additional charts.\n    labels - If True, displays labels on the chart for data points.\n    legend - If True, displays the data point legend on the chart.\n\"\"\"\n

If creating multiple charts at the same time, you can pass the chart_name parameter to distinguish between different charts.

Adding a data point to a chart:
self.add_data_point(label, value, color=None, chart_name=None):\n\"\"\" Add a data point to a SeleniumBase-generated chart.\n    @Params\n    label - The label name for the data point.\n    value - The numeric value of the data point.\n    color - The HTML color of the data point.\n            Can be an RGB color. Eg: \"#55ACDC\".\n            Can also be a named color. Eg: \"Teal\".\n    chart_name - If creating multiple charts,\n                 use this to select which one.\n\"\"\"\n
Adding a new data series to an existing chart:
self.add_series_to_chart(self, data_name=None, chart_name=None):\n\"\"\" Add a new data series to an existing chart.\n    This allows charts to have multiple data sets.\n    @Params\n    data_name - Set the series name. Useful for multi-series charts.\n    chart_name - If creating multiple charts,\n                 use this to select which one.\n\"\"\"\n
Saving a chart to a file:
self.save_chart(chart_name=None, filename=None):\n\"\"\" Saves a SeleniumBase-generated chart to a file for later use.\n    @Params\n    chart_name - If creating multiple charts at the same time,\n                 use this to select the one you wish to use.\n    filename - The name of the HTML file that you wish to\n               save the chart to. (filename must end in \".html\")\n\"\"\"\n

The full HTML of the chart is saved to the saved_charts/ folder.

Extracting the HTML of a chart:
self.extract_chart(chart_name=None):\n\"\"\" Extracts the HTML from a SeleniumBase-generated chart.\n    @Params\n    chart_name - If creating multiple charts at the same time,\n                 use this to select the one you wish to use.\n\"\"\"\n
Displaying a chart in the browser window:
self.display_chart(chart_name=None, filename=None):\n\"\"\" Displays a SeleniumBase-generated chart in the browser window.\n    @Params\n    chart_name - If creating multiple charts at the same time,\n                 use this to select the one you wish to use.\n    filename - The name of the HTML file that you wish to\n               save the chart to. (filename must end in \".html\")\n    interval - The delay time for auto-advancing charts. (in seconds)\n               If set to 0 (default), auto-advancing is disabled.\n\"\"\"\n

All methods have the optional chart_name argument, which is only needed when storing multiple charts at the same time.

"}, {"location": "examples/dialog_boxes/ReadMe/", "title": "\ud83d\udec2 Dialog Boxes", "text": "Dialog Boxes \ud83d\udec2

SeleniumBase Dialog Boxes let your users provide input in the middle of automation scripts.

\u2195\ufe0f (Example: dialog_box_tour.py) \u2195\ufe0f

Here's how to run that example:
cd examples/dialog_boxes\npytest test_dialog_boxes.py\n
Here's a code snippet from that:
self.open(\"https://xkcd.com/1920/\")\nskip_button = [\"SKIP\", \"red\"]  # Can be a [text, color] list or tuple.\nbuttons = [\"Fencing\", \"Football\", \"Metaball\", \"Go/Chess\", skip_button]\nmessage = \"Choose a sport:\"\nchoice = self.get_jqc_button_input(message, buttons)\nif choice == \"Fencing\":\n    self.open(\"https://xkcd.com/1424/\")\n
Here's a simple form with only buttons as input:
choice = self.get_jqc_button_input(\"Ready?\", [\"YES\", \"NO\"])\nprint(choice)  # This prints \"YES\" or \"NO\"\n\n# You may want to customize the color of buttons\nbuttons = [(\"YES\", \"green\"), (\"NO\", \"red\")]\nchoice = self.get_jqc_button_input(\"Ready?\", buttons)\n
Here's a simple form with an input field:
text = self.get_jqc_text_input(\"Enter text:\", [\"Search\"])\nprint(text)  # This prints the text entered\n
This form has an input field and buttons:
message = \"Type your name and choose a language:\"\nbuttons = [\"Python\", \"JavaScript\"]\ntext, choice = self.get_jqc_form_inputs(message, buttons)\nprint(\"Your name is: %s\" % text)\nprint(\"You picked %s!\" % choice)\n
You can customize options if you want:
# Themes: bootstrap, modern, material, supervan, light, dark, seamless\noptions = [(\"theme\", \"modern\"), (\"width\", \"50%\")]\nself.get_jqc_text_input(\"You Won!\", [\"OK\"], options)\n
Default options can be set with set_jqc_theme():
self.set_jqc_theme(\"light\", color=\"green\", width=\"38%\")\n\n# To reset jqc theme settings to factory defaults\nself.reset_jqc_theme()\n
All methods for Dialog Boxes:
self.get_jqc_button_input(message, buttons, options=None)\n\nself.get_jqc_text_input(message, button=None, options=None)\n\nself.get_jqc_form_inputs(message, buttons, options=None)\n\nself.set_jqc_theme(theme, color=None, width=None)\n\nself.reset_jqc_theme()\n\nself.activate_jquery_confirm()  # Automatic for jqc methods\n
Detailed method summaries for Dialog Boxes:
self.get_jqc_button_input(message, buttons, options=None)\n\"\"\"\nPop up a jquery-confirm box and return the text of the button clicked.\nIf running in headless mode, the last button text is returned.\n@Params\nmessage: The message to display in the jquery-confirm dialog.\nbuttons: A list of tuples for text and color.\n    Example: [(\"Yes!\", \"green\"), (\"No!\", \"red\")]\n    Available colors: blue, green, red, orange, purple, default, dark.\n    A simple text string also works: \"My Button\". (Uses default color.)\noptions: A list of tuples for options to set.\n    Example: [(\"theme\", \"bootstrap\"), (\"width\", \"450px\")]\n    Available theme options: bootstrap, modern, material, supervan,\n                             light, dark, and seamless.\n    Available colors: (For the BORDER color, NOT the button color.)\n        \"blue\", \"default\", \"green\", \"red\", \"purple\", \"orange\", \"dark\".\n    Example option for changing the border color: (\"color\", \"default\")\n    Width can be set using percent or pixels. Eg: \"36.0%\", \"450px\".\n\"\"\"\n\nself.get_jqc_text_input(message, button=None, options=None)\n\"\"\"\nPop up a jquery-confirm box and return the text submitted by the input.\nIf running in headless mode, the text returned is \"\" by default.\n@Params\nmessage: The message to display in the jquery-confirm dialog.\nbutton: A 2-item list or tuple for text and color. Or just the text.\n    Example: [\"Submit\", \"blue\"] -> (default button if not specified)\n    Available colors: blue, green, red, orange, purple, default, dark.\n    A simple text string also works: \"My Button\". (Uses default color.)\noptions: A list of tuples for options to set.\n    Example: [(\"theme\", \"bootstrap\"), (\"width\", \"450px\")]\n    Available theme options: bootstrap, modern, material, supervan,\n                             light, dark, and seamless.\n    Available colors: (For the BORDER color, NOT the button color.)\n        \"blue\", \"default\", \"green\", \"red\", \"purple\", \"orange\", \"dark\".\n    Example option for changing the border color: (\"color\", \"default\")\n    Width can be set using percent or pixels. Eg: \"36.0%\", \"450px\".\n\"\"\"\n\nself.get_jqc_form_inputs(message, buttons, options=None)\n\"\"\"\nPop up a jquery-confirm box and return the input/button texts as tuple.\nIf running in headless mode, returns the (\"\", buttons[-1][0]) tuple.\n@Params\nmessage: The message to display in the jquery-confirm dialog.\nbuttons: A list of tuples for text and color.\n    Example: [(\"Yes!\", \"green\"), (\"No!\", \"red\")]\n    Available colors: blue, green, red, orange, purple, default, dark.\n    A simple text string also works: \"My Button\". (Uses default color.)\noptions: A list of tuples for options to set.\n    Example: [(\"theme\", \"bootstrap\"), (\"width\", \"450px\")]\n    Available theme options: bootstrap, modern, material, supervan,\n                             light, dark, and seamless.\n    Available colors: (For the BORDER color, NOT the button color.)\n        \"blue\", \"default\", \"green\", \"red\", \"purple\", \"orange\", \"dark\".\n    Example option for changing the border color: (\"color\", \"default\")\n    Width can be set using percent or pixels. Eg: \"36.0%\", \"450px\".\n\"\"\"\n\nself.set_jqc_theme(theme, color=None, width=None)\n\"\"\" Sets the default jquery-confirm theme and width (optional).\nAvailable themes: \"bootstrap\", \"modern\", \"material\", \"supervan\",\n                  \"light\", \"dark\", and \"seamless\".\nAvailable colors: (This sets the BORDER color, NOT the button color.)\n    \"blue\", \"default\", \"green\", \"red\", \"purple\", \"orange\", \"dark\".\nWidth can be set using percent or pixels. Eg: \"36.0%\", \"450px\".\n\"\"\"\n\nself.reset_jqc_theme()\n\"\"\" Resets the jqc theme settings to factory defaults. \"\"\"\n\nself.activate_jquery_confirm()  # Automatic for jqc methods\n\"\"\" See https://craftpip.github.io/jquery-confirm/ for usage. \"\"\"\n
\u2705 \ud83d\udec2 Automated/Manual Hybrid Mode (MasterQA)

MasterQA uses SeleniumBase Dialog Boxes to speed up manual testing by having automation perform all the browser actions while the manual tester handles validation. See the MasterQA GitHub page for examples.

"}, {"location": "examples/example_logs/ReadMe/", "title": "\ud83d\udcca Dashboard / Reports", "text": ""}, {"location": "examples/example_logs/ReadMe/#logs-the-dashboard-and-reports", "title": "Logs, The Dashboard, and Reports", "text": "

\ud83d\udd35 During test failures, logs and screenshots from the most recent test run will get saved to the latest_logs/ folder. If --archive-logs is specified (or if ARCHIVE_EXISTING_LOGS is set to True in settings.py), test logs will also get archived to the archived_logs/ folder. Otherwise, the log files will be cleaned out when the next test run begins (by default).

pytest test_fail.py\n

(Log files in SeleniumBase/examples/example_logs were generated when test_fail.py ran and failed.)

Examples of expected log files generated during failures:

In addition to log files, you can also generate dashboards and test reports.

The SeleniumBase Dashboard:

\ud83d\udd35 The --dashboard option for pytest generates a SeleniumBase Dashboard located at dashboard.html, which updates automatically as tests run and produce results. Example:

pytest --dashboard --rs --headless\n

\ud83d\udd35 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:

python -m http.server 1948\n

\ud83d\udd35 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.)

\ud83d\udd35 Here's a full example of what the SeleniumBase Dashboard may look like:

pytest test_suite.py --dashboard --rs --headless\n

Pytest Reports:

\ud83d\udd35 Using --html=report.html gives you a fancy report of the name specified after your test suite completes.

pytest test_suite.py --html=report.html\n

\ud83d\udd35 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.

\ud83d\udd35 Here's an example of an upgraded html report:

pytest test_suite.py --dashboard --html=report.html\n

If viewing pytest-html reports in Jenkins, you may need to configure Jenkins settings for the HTML to render correctly. This is due to Jenkins CSP changes. That setting can be changed from Manage Jenkins > Script Console by running:

System.setProperty(\"hudson.model.DirectoryBrowserSupport.CSP\", \"\")\n

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.

pytest test_suite.py --junit-xml=report.xml\n
pynose Test Reports:

The pynose --report option gives you a fancy report after your tests complete.

pynose test_suite.py --report\n

(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.)

\ud83d\udc1d\u26aa Behave Dashboard & Reports:

(The behave_bdd/ folder can be found in the examples/ folder.)

behave behave_bdd/features/ -D dashboard -D headless\n

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.

behave behave_bdd/features/ --junit -D rs -D headless\n
"}, {"location": "examples/master_qa/ReadMe/", "title": "\ud83d\udec2 MasterQA Mode", "text": "MasterQA combines automation with manual verification steps.

Here's code from basic_masterqa_test_0.py:

from seleniumbase import MasterQA\n\nclass MasterQATests(MasterQA):\n    def test_masterqa(self):\n        self.open(\"https://xkcd.com/1700/\")\n        self.verify(\"Do you see a webcomic?\")\n        self.open(\"https://seleniumbase.io/demo_page\")\n        self.highlight('table')\n        self.verify(\"Do you see elements in a table?\")\n        self.open(\"https://seleniumbase.io/devices/\")\n        self.highlight(\"div.mockup-wrapper\")\n        self.verify(\"Do you see 4 computer devices?\")\n

After each automation checkpoint, a pop-up window will ask the user questions for each verification command.

When the test run completes, as seen from this longer example, you'll reach the results page that appears after answering all the verification questions. (Failed verifications generate links to screenshots and log files.)

You may have noticed the Incomplete Test Runs row on the results page. If the value for that is not zero, it means that one of the automated steps failed. This could happen if you tell your script to perform an action on an element that doesn't exist. Now that we're mixing automation with manual QA, it's good to tell apart the failures from each. The results_table CSV file contains a spreadsheet with the details of each failure (if any) for both manual and automated steps.

How to run the example tests from scratch:

git clone https://github.com/seleniumbase/SeleniumBase.git\ncd SeleniumBase\npip install .\ncd examples/master_qa\npytest basic_masterqa_test_0.py\npytest masterqa_test_1.py\n

At the end of your test run, you'll receive a report with results, screenshots, and log files. Close the Results Page window when you're done.

Check out masterqa_test_1.py to learn how to write your own MasterQA tests:

You'll notice that tests are written the same way as regular SeleniumBase tests, with the key difference being a different import: from seleniumbase import MasterQA rather than from seleniumbase import BaseCase. Now your Python test class will import MasterQA instead of BaseCase.

To add a manual verification step, use self.verify() in the code after each part of your test that needs a manual verification step. If you want to include a custom question, add text inside that call (in quotes). Example:

self.verify()\n\nself.verify(\"Can you find the moon?\")\n

MasterQA is powered by SeleniumBase, the most advanced open-source automation framework on the Planet.

"}, {"location": "examples/presenter/ReadMe/", "title": "\ud83c\udf9e\ufe0f Presentation Maker", "text": ""}, {"location": "examples/presenter/ReadMe/#presenter", "title": "\ud83d\udcd1 Presenter \ud83c\udf9e\ufe0f", "text": "

SeleniumBase Presenter (slide-maker) lets you use Python to generate HTML presentations.

Here's a sample presentation:

(Click on the image/GIF for the actual presentation)

(Here's the code for that presentation)

Slides can include HTML, code, images, and iframes.

Here's how to run the example presentation:

cd examples/presenter\npytest my_presentation.py\n

Here's a presentation with a chart:

(Click on the image/GIF for the actual presentation)

(Here's the code for that presentation)

Here's how to run that example:

cd examples/presenter\npytest core_presentation.py\n
Creating a new presentation:
self.create_presentation(name=None, theme=\"serif\", transition=\"default\")\n\"\"\" Creates a Reveal-JS presentation that you can add slides to.\n    @Params\n    name - If creating multiple presentations at the same time,\n           use this to specify the name of the current presentation.\n    theme - Set a theme with a unique style for the presentation.\n            Valid themes: \"serif\" (default), \"sky\", \"white\", \"black\",\n                          \"simple\", \"league\", \"moon\", \"night\",\n                          \"beige\", \"blood\", and \"solarized\".\n    transition - Set a transition between slides.\n                 Valid transitions: \"none\" (default), \"slide\", \"fade\",\n                                    \"zoom\", \"convex\", and \"concave\".\n\"\"\"\n

If creating multiple presentations at the same time, you can pass the name parameter to distinguish between different presentations. Notes are disabled by default. You can enable notes by specifying: show_notes=True

Adding a slide to a presentation:
self.add_slide(content=None, image=None, code=None, iframe=None,\n               content2=None, notes=None, transition=None, name=None)\n\"\"\" Allows the user to add slides to a presentation.\n    @Params\n    content - The HTML content to display on the presentation slide.\n    image - Attach an image (from a URL link) to the slide.\n    code - Attach code of any programming language to the slide.\n           Language-detection will be used to add syntax formatting.\n    iframe - Attach an iFrame (from a URL link) to the slide.\n    content2 - HTML content to display after adding an image or code.\n    notes - Additional notes to include with the slide.\n            ONLY SEEN if show_notes is set for the presentation.\n    transition - Set a transition between slides. (overrides previous)\n                 Valid transitions: \"none\" (default), \"slide\", \"fade\",\n                                    \"zoom\", \"convex\", and \"concave\".\n    name - If creating multiple presentations at the same time,\n           use this to select the presentation to add slides to.\n\"\"\"\n
Running a presentation:
self.begin_presentation(\n    filename=\"my_presentation.html\", show_notes=False, interval=0)\n\"\"\" Begin a Reveal-JS Presentation in the web browser.\n    @Params\n    name - If creating multiple presentations at the same time,\n           use this to select the one you wish to add slides to.\n    filename - The name of the HTML file that you wish to\n               save the presentation to. (filename must end in \".html\")\n    show_notes - When set to True, the Notes feature becomes enabled,\n                 which allows presenters to see notes next to slides.\n    interval - The delay time between autoplaying slides. (in seconds)\n               If set to 0 (default), autoplay is disabled.\n\"\"\"\n

Before the presentation is run, the full HTML is saved to the saved_presentations/ folder.

All methods have the optional name argument, which is only needed if you're creating multiple presentations at once.

Here's an example of using SeleniumBase Presenter:
from seleniumbase import BaseCase\nBaseCase.main(__name__, __file__)\n\nclass MyPresenterClass(BaseCase):\n    def test_presenter(self):\n        self.create_presentation(theme=\"serif\")\n        self.add_slide(\n            '<h1>Welcome</h1><br />\\n'\n            '<h3>Press the <b>Right Arrow</b></h3>')\n        self.add_slide(\n            '<h3>SeleniumBase Presenter</h3><br />\\n'\n            '<img width=\"240\" src=\"https://seleniumbase.io/img/logo3a.png\" />'\n            '<span style=\"margin:144px;\" />'\n            '<img src=\"https://seleniumbase.io/other/python_3d_logo.png\" />'\n            '<br /><br />\\n<h4>Create presentations with <b>Python</b></h4>')\n        self.add_slide(\n            '<h3>Make slides using <b>HTML</b>:</h3><br />\\n'\n            '<table style=\"padding:10px;border:4px solid black;font-size:50;\">'\n            '\\n<tr style=\"background-color:CDFFFF;\">\\n'\n            '<th>Row ABC</th><th>Row XYZ</th></tr>\\n'\n            '<tr style=\"background-color:DCFDDC;\">'\n            '<td>Value ONE</td><td>Value TWO</td></tr>\\n'\n            '<tr style=\"background-color:DFDFFB;\">\\n'\n            '<td>Value THREE</td><td>Value FOUR</td></tr>\\n'\n            '</table><br />\\n<h4>(HTML <b>table</b> example)</h4>')\n        self.add_slide(\n            '<h3>Keyboard Shortcuts:</h3>\\n'\n            '<table style=\"padding:10px;border:4px solid black;font-size:30;'\n            'background-color:FFFFDD;\">\\n'\n            '<tr><th>Key</th><th>Action</th></tr>\\n'\n            '<tr><td><b>=></b></td><td>Next Slide (N also works)</td></tr>\\n'\n            '<tr><td><b><=</b></td><td>Previous Slide (P also works)</td></tr>'\n            '\\n<tr><td>F</td><td>Full Screen Mode</td></tr>\\n'\n            '<tr><td>O</td><td>Overview Mode Toggle</td></tr>\\n'\n            '<tr><td>esc</td><td>Exit Full Screen / Overview Mode</td></tr>\\n'\n            '<tr><td><b>.</b></td><td>Pause/Resume Toggle</td></tr>\\n'\n            '<tr><td>space</td><td>Next Slide (alternative)</td></tr></table>')\n        self.add_slide(\n            '<h3>Add <b>images</b> to slides:</h3>',\n            image=\"https://seleniumbase.github.io/other/seagulls.jpg\")\n        self.add_slide(\n            '<h3>Add <b>code</b> to slides:</h3>',\n            code=(\n                'from seleniumbase import BaseCase\\n\\n'\n                'class MyTestClass(BaseCase):\\n\\n'\n                '    def test_basics(self):\\n'\n                '        self.open(\"https://store.xkcd.com/search\")\\n'\n                '        self.type(\\'input[name=\"q\"]\\', \"xkcd book\\\\n\")\\n'\n                '        self.assert_text(\"xkcd: volume 0\", \"h3\")\\n'\n                '        self.open(\"https://xkcd.com/353/\")\\n'\n                '        self.assert_title(\"xkcd: Python\")\\n'\n                '        self.assert_element(\\'img[alt=\"Python\"]\\')\\n'\n                '        self.click(\\'a[rel=\"license\"]\\')\\n'\n                '        self.assert_text(\"free to copy and reuse\")\\n'\n                '        self.go_back()\\n'\n                '        self.click_link(\"About\")\\n'\n                '        self.assert_exact_text(\"xkcd.com\", \"h2\")'))\n        self.add_slide(\n            \"<h3>Highlight <b>code</b> in slides:</h3>\",\n            code=(\n                'from seleniumbase import BaseCase\\n\\n'\n                '<mark>class MyTestClass(BaseCase):</mark>\\n\\n'\n                '    def test_basics(self):\\n'\n                '        self.open(\"https://store.xkcd.com/search\")\\n'\n                '        self.type(\\'input[name=\"q\"]\\', \"xkcd book\\\\n\")\\n'\n                '        self.assert_text(\"xkcd: volume 0\", \"h3\")'))\n        self.add_slide(\n            '<h3>Add <b>iFrames</b> to slides:</h3>',\n            iframe=\"https://seleniumbase.io/demo_page\")\n        self.add_slide(\n            '<h3>Getting started is <b>easy</b>:</h3>',\n            code=(\n                'from seleniumbase import BaseCase\\n\\n'\n                'class MyPresenterClass(BaseCase):\\n\\n'\n                '    def test_presenter(self):\\n'\n                '        self.create_presentation(theme=\"serif\")\\n'\n                '        self.add_slide(\"Welcome to Presenter!\")\\n'\n                '        self.add_slide(\\n'\n                '            \"Add code to slides:\",\\n'\n                '            code=(\\n'\n                '                \"from seleniumbase import BaseCase\\\\n\\\\n\"\\n'\n                '                \"class MyPresenterClass(BaseCase):\\\\n\\\\n\"\\n'\n                '                \"    def test_presenter(self):\\\\n\"\\n'\n                '                \"        self.create_presentation()\\\\n\"))\\n'\n                '        self.begin_presentation(\\n'\n                '            filename=\"demo.html\", show_notes=True)'))\n        self.add_slide(\n            '<h3>Include <b>notes</b> with slides:</h3><br />',\n            code=('self.add_slide(\"[Your HTML goes here]\",\\n'\n                  '               code=\"[Your software code goes here]\",\\n'\n                  '               content2=\"[Additional HTML goes here]\",\\n'\n                  '               notes=\"[Attached speaker notes go here]\"\\n'\n                  '                     \"[Note A! -- Note B! -- Note C! ]\")'),\n            notes='<h2><ul><li>Note A!<li>Note B!<li>Note C!<li>Note D!</h2>',\n            content2=\"<h4>(Notes can include HTML tags)</h4>\")\n        self.add_slide(\n            '<h3>Multiple <b>themes</b> available:</h3>',\n            code=(\n                'self.create_presentation(theme=\"serif\")\\n\\n'\n                'self.create_presentation(theme=\"sky\")\\n\\n'\n                'self.create_presentation(theme=\"simple\")\\n\\n'\n                'self.create_presentation(theme=\"white\")\\n\\n'\n                'self.create_presentation(theme=\"moon\")\\n\\n'\n                'self.create_presentation(theme=\"black\")\\n\\n'\n                'self.create_presentation(theme=\"night\")\\n\\n'\n                'self.create_presentation(theme=\"beige\")\\n\\n'\n                'self.create_presentation(theme=\"league\")'))\n        self.add_slide(\n            '<h2><b>The End</b></h2>',\n            image=\"https://seleniumbase.github.io/img/sb_logo_10.png\")\n        self.begin_presentation(\n            filename=\"presenter.html\", show_notes=True, interval=0)\n

That example is from my_presentation.py, which you can run from the examples/presenter folder with the following command:

pytest my_presentation.py\n
Saving a presentation:

If you want to save the presentation you created as an HTML file, use:

self.save_presentation(filename=\"my_presentation.html\", show_notes=True)\n

Presentations automatically get saved when calling:

self.begin_presentation(show_notes=True)\n
"}, {"location": "examples/tour_examples/ReadMe/", "title": "\ud83d\ude8e Tour Maker", "text": ""}, {"location": "examples/tour_examples/ReadMe/#interactive-product-tours", "title": "Interactive Product Tours \ud83d\ude8e", "text": "

Increase SaaS Product Adoption by 10x or more.

IntroJS, Bootstrap Tour, DriverJS, Shepherd, and Hopscotch.

A tour demo: (with autoplay)

SeleniumBase maps_introjs_tour.py

cd examples/tour_examples\npytest maps_introjs_tour.py --interval=1\n

Here's a longer version:

SeleniumBase google_tour.py

cd examples/tour_examples\npytest google_tour.py\n

(From GitHub => SeleniumBase/examples/tour_examples)

"}, {"location": "examples/tour_examples/ReadMe/#creating-a-new-tour", "title": "Creating a new tour", "text": ""}, {"location": "examples/tour_examples/ReadMe/#to-create-a-tour-utilizing-the-shepherd-library-use-one-of-the-following", "title": "To create a tour utilizing the Shepherd Library, use one of the following", "text": "

self.create_shepherd_tour()

OR

self.create_tour(theme=\"shepherd\")

You can pass a custom theme to change the look & feel of Shepherd tours. Valid themes for Shepherd Tours are dark, light / arrows, default, square, and square-dark.

"}, {"location": "examples/tour_examples/ReadMe/#to-create-a-tour-utilizing-the-bootstrap-tour-library-use-one-of-the-following", "title": "To create a tour utilizing the Bootstrap Tour Library, use one of the following", "text": "

self.create_bootstrap_tour()

OR

self.create_tour(theme=\"bootstrap\")

"}, {"location": "examples/tour_examples/ReadMe/#to-create-a-tour-utilizing-the-introjs-library-use-one-of-the-following", "title": "To create a tour utilizing the IntroJS Library, use one of the following", "text": "

self.create_introjs_tour()

OR

self.create_tour(theme=\"introjs\")

"}, {"location": "examples/tour_examples/ReadMe/#to-create-a-tour-utilizing-the-driverjs-library-use-one-of-the-following", "title": "To create a tour utilizing the DriverJS Library, use one of the following", "text": "

self.create_driverjs_tour()

OR

self.create_tour(theme=\"driverjs\")

"}, {"location": "examples/tour_examples/ReadMe/#to-create-a-tour-utilizing-the-hopscotch-library-use-one-of-the-following", "title": "To create a tour utilizing the Hopscotch Library, use one of the following", "text": "

self.create_hopscotch_tour()

OR

self.create_tour(theme=\"hopscotch\")

"}, {"location": "examples/tour_examples/ReadMe/#adding-a-step-to-a-tour", "title": "Adding a step to a tour", "text": ""}, {"location": "examples/tour_examples/ReadMe/#to-add-a-tour-step-use-the-following", "title": "To add a tour step, use the following", "text": "

self.add_tour_step(message, css_selector, title, alignment, theme)

With the self.add_tour_step() method, you must first pass a message to display. You can then specify a web element to attach to (by using CSS selectors). If no element is specified, the tour step will tether to the top of the screen by default. You can also add an optional title above the message to display with the tour step, as well as change the theme for that step (Shepherd tours only), and even specify the alignment (which is the side of the element that you want the tour message to tether to).

"}, {"location": "examples/tour_examples/ReadMe/#playing-a-tour", "title": "Playing a tour", "text": "

You can play a tour by calling:

self.play_tour(interval)

If you specify an interval (optional), the tour will automatically walk through each step after that many seconds have passed.

All methods have the optional name argument, which is only needed if you're creating multiple tours at once. Then, when you're adding a step or playing a tour, SeleniumBase knows which tour you're referring too. You can avoid using the name arg for multiple tours if you play a tour before creating a new one.

"}, {"location": "examples/tour_examples/ReadMe/#heres-how-the-code-looks", "title": "Here's how the code looks", "text": "
from seleniumbase import BaseCase\nBaseCase.main(__name__, __file__)\n\nclass MyTourClass(BaseCase):\n\n    def test_google_tour(self):\n        self.open('https://google.com/ncr')\n        self.wait_for_element('input[title=\"Search\"]')\n        self.hide_elements(\"iframe\")\n\n        self.create_tour(theme=\"dark\")\n        self.add_tour_step(\"Welcome to Google!\", title=\"SeleniumBase Tours\")\n        self.add_tour_step(\"Type in your query here.\", '[title=\"Search\"]')\n        self.play_tour()\n\n        self.highlight_type('input[title=\"Search\"]', \"Google\")\n        self.wait_for_element('[role=\"listbox\"]')  # Wait for autocomplete\n\n        self.create_tour(theme=\"light\")\n        self.add_tour_step(\"Then click to search.\", '[value=\"Google Search\"]')\n        self.add_tour_step(\"Or press [ENTER] after entry.\", '[title=\"Search\"]')\n        self.play_tour()\n
"}, {"location": "examples/tour_examples/ReadMe/#that-code-is-from-google_tourpy-which-you-can-run-from-the-tour_examples-folder-with-the-following-command", "title": "That code is from google_tour.py, which you can run from the tour_examples/ folder with the following command", "text": "
pytest google_tour.py\n
"}, {"location": "examples/tour_examples/ReadMe/#exporting-a-tour", "title": "Exporting a Tour", "text": "

If you want to save the tour you created as a JavaScript file, use:

self.export_tour()

OR

self.export_tour(name=None, filename=\"my_tour.js\")

(name is optional unless you gave custom names to your tours when you created them. filename is the name of the file to save the JavaScript to.) Once you've exported your tour, you can use it outside of SeleniumBase. You can even copy the tour's JavaScript code to the Console of your web browser to play the tour from there (you need to be on the correct web page for it to work).

"}, {"location": "examples/visual_testing/ReadMe/", "title": "\ud83d\uddbc\ufe0f Visual Testing", "text": ""}, {"location": "examples/visual_testing/ReadMe/#automated-visual-regression-testing", "title": "Automated Visual Regression Testing", "text": "

Automated Visual Regression Testing can help you detect when the layout of a web page has changed. Instead of comparing pixels from screenshots, layout differences can be detected by comparing HTML tags and attributes with a baseline. If a change is detected, it could mean that something broke, the web page was redesigned, or dynamic content changed.

To handle automated visual testing, SeleniumBase uses the self.check_window() method, which can set visual baselines for comparison and then compare the latest versions of web pages to the existing baseline.

The first time a test calls self.check_window() with a unique name parameter, the visual baseline is set, which means a folder is created with the following files:

  • page_url.txt -> The URL of the current window
  • baseline.png -> The baseline screenshot (PNG)
  • tags_level1.txt -> HTML tags from the window
  • tags_level2.txt -> HTML tags + attribute names
  • tags_level3.txt -> HTML tags + attribute names+values
  • After the first time self.check_window() is called, later calls will compare the HTML tags and attributes of the latest window to the ones from the first call (or to the ones from the call when the baseline was last reset). Additionally, a latest.png screenshot is saved in the same folder, which can help you determine if/when the existing baseline needs to be reset.

    Here's an example call:

    self.check_window(name=\"first_test)\", level=3)\n

    On the first run (or if the baseline is being set/reset) the \"level\" doesn't matter because that's only used for comparing the current layout to the existing baseline.

    Here's how the level system works:

  • level=0 -> DRY RUN ONLY - Will perform a comparison to the baseline, and print out any differences that are found, but won't fail the test even if differences exist.
  • level=1 -> HTML tags are compared to tags_level1.txt
  • level=2 -> HTML tags and attribute names are compared to tags_level2.txt
  • level=3 -> HTML tags and attribute names+values are compared to tags_level3.txt
  • As shown, Level-3 is the most strict, Level-1 is the least strict. If the comparisons from the latest window to the existing baseline don't match, the current test will fail, except for Level-0 checks, which print Level-3 results without failing the test.

    You can reset the visual baseline on the command line by adding the following parameter at runtime:

    --visual_baseline\n

    As long as --visual_baseline is used on the command line while running tests, the self.check_window() method cannot fail because it will rebuild the visual baseline rather than comparing the html tags of the latest run to the existing baseline. If there are any expected layout changes to a website that you're testing, you'll need to reset the baseline to prevent unnecessary failures.

    self.check_window() will fail with \"Page Domain Mismatch Failure\" if the domain of the current URL doesn't match the domain of the baseline URL.

    If you want to use self.check_window() to compare a web page to a later version of itself in the same test, add the baseline=True parameter to your first self.check_window() call to use that as the baseline. (This only makes sense if you're calling self.check_window() more than once with the same \"name\" parameter in the same test.)

    Automated Visual Testing with self.check_window() is not very effective for websites that have dynamic content because that changes the layout and structure of web pages. For those pages, you're much better off using regular SeleniumBase functional testing, unless you can remove the dynamic content before performing the comparison, (such as by using self.ad_block() to remove dynamic ad content on a web page).

    Example usage of self.check_window() with different levels:

        self.check_window(name=\"testing\", level=0)\n    self.check_window(name=\"xkcd_home\", level=1)\n    self.check_window(name=\"github_page\", level=2)\n    self.check_window(name=\"wikipedia_page\", level=3)\n\n    self.check_window(name=\"helloworld\", baseline=True)\n    ### Do something that may change the web page\n    self.check_window(name=\"helloworld\", level=3)\n

    Here's an example where clicking a button makes a hidden element visible:

    from seleniumbase import BaseCase\nBaseCase.main(__name__, __file__)\n\nclass VisualLayoutTest(BaseCase):\n    def test_applitools_layout_change_failure(self):\n        self.open('https://applitools.com/helloworld?diff1')\n        print('\\nCreating baseline in \"visual_baseline\" folder.')\n        self.check_window(name=\"helloworld\", baseline=True)\n        # Click a button that changes the text of an element\n        self.click('a[href=\"?diff1\"]')\n        # Click a button that makes a hidden element visible\n        self.click(\"button\")\n        self.check_window(name=\"helloworld\", level=3)\n

    Here's the output of that: (Text changes do not impact visual comparisons)

    AssertionError:\nFirst differing element 39:\n['div', [['class', ['section', 'hidden-section', 'image-section']]]]\n['div', [['class', ['section', 'image-section']]]]\n\n-  ['div', [['class', ['section', 'hidden-section', 'image-section']]]],\n?                                ------------------\n+  ['div', [['class', ['section', 'image-section']]]],\n*\n*** Exception: <Level 3> Visual Diff Failure:\n* HTML tag attribute values don't match the baseline!\n

    Here's an example where a button is removed from a web page:

    from seleniumbase import BaseCase\nBaseCase.main(__name__, __file__)\n\nclass VisualLayoutTest(BaseCase):\n    def test_python_home_layout_change_failure(self):\n        self.open('https://python.org/')\n        print('\\nCreating baseline in \"visual_baseline\" folder.')\n        self.check_window(name=\"python_home\", baseline=True)\n        # Remove the \"Donate\" button\n        self.remove_element('a.donate-button')\n        self.check_window(name=\"python_home\", level=3)\n

    Here's the output of that:

    AssertionError:\nFirst differing element 33:\n['a', [['class', ['donate-button']], ['href', '/psf/donations/']]]\n['div', [['class', ['options-bar']]]]\n\n-  ['a', [['class', ['donate-button']], ['href', '/psf/donations/']]],\n-     'display: list-item; opacity: 0.995722;']]],\n?                         -------------------\n+     'display: list-item;']]],\n*\n*** Exception: <Level 3> Visual Diff Failure:\n* HTML tag attribute values don't match the baseline!\n

    Here's the side_by_side.html file for that, (from the ./latest_logs/ folder), which shows a visual comparison of the two screenshots as a result of the missing \"Donate\" button:

    Here's another example, where a web site logo is resized:

    from seleniumbase import BaseCase\nBaseCase.main(__name__, __file__)\n\nclass VisualLayoutTest(BaseCase):\n    def test_xkcd_layout_change_failure(self):\n        self.open('https://xkcd.com/554/')\n        print('\\nCreating baseline in \"visual_baseline\" folder.')\n        self.check_window(name=\"xkcd_554\", baseline=True)\n        # Change height: (83 -> 130) , Change width: (185 -> 120)\n        self.set_attribute('[alt=\"xkcd.com logo\"]', \"height\", \"130\")\n        self.set_attribute('[alt=\"xkcd.com logo\"]', \"width\", \"120\")\n        self.check_window(name=\"xkcd_554\", level=3)\n

    Here's the output of that:

    AssertionError:\nFirst differing element 22:\n['img[30 chars]['height', '83'], ['src', '/s/0b7742.png'], ['width', '185']]]\n['img[30 chars]['height', '130'], ['src', '/s/0b7742.png'], ['width', '120']]]\n\n-    ['height', '83'],\n?                ^\n+    ['height', '130'],\n?                ^ +\n-    ['width', '185']]],\n?                ^^\n+    ['width', '120']]],\n?                ^^\n*\n*** Exception: <Level 3> Visual Diff Failure:\n* HTML tag attribute values don't match the baseline!\n

    To run the example (from examples/visual_testing/) with a pytest HTML Report, use:

    pytest test_layout_fail.py --html=report.html\n

    Here's what the pytest HTML Report looks like:

    In conclusion, open source automated visual testing tools are being built directly into test frameworks, and this trend is growing. Just like many years ago when free Wi-Fi at coffee shops replaced Internet cafes that charged money for Internet access, open source tools for visual testing will replace their paid counterparts in time. You'll remember this next time you're sipping your Starbucks\u00ae Pumpkin Spice Latte with your free Internet access, instead of paying for Internet at cybercafes.

    "}, {"location": "help_docs/ReadMe/", "title": "\ud83d\udcd1 Table of Contents", "text": ""}, {"location": "help_docs/ReadMe/#help-docs", "title": "Help Docs", "text": "

    \ud83d\ude80 Start | \ud83d\udcca Dashboard \ud83c\udff0 Features | \ud83c\udf9b\ufe0f Options \ud83d\udcda Examples | \ud83d\udcf1 Emulator \ud83c\udf20 Console Scripts | \ud83c\udf10 Grid \ud83d\udcd8 Methods / APIs | \ud83d\ude8e Tours \ud83d\udd21 Syntax Formats | \ud83e\udd16 CI/CD \u267b\ufe0f Boilerplates | \ud83d\uddfe Locale Codes \ud83d\udd79\ufe0f JS Manager | \ud83d\uddbc\ufe0f Visual Testing \ud83c\udf0f Translator | \ud83d\udec2 Dialog Boxes \ud83d\udd34 Recorder | \ud83d\ude9d Migrate \ud83c\udf9e\ufe0f Slides | \ud83d\udcf6 Charts

    Table of Contents (seleniumbase.io) Features List Command Line Tutorial Usage Examples Demo Page for Tests How SeleniumBase Works Installing Python, Pip, & Git Python Virtual Env Tutorial SeleniumBase Installation Webdriver Installation Verify Webdriver Works Console Scripts Tutorial The Dashboard Recorder Mode pytest Commander Syntax Formats Behave BDD Behave Commander Mobile Device Testing Method Summary (API Ref) Case Plans Language Translations Language Locale Codes JS Package Manager Tour Examples Presentation Maker Chart Maker Handling iframes MySQL Installation Overview Using the Selenium Grid Browser Desired Capabilities Safari Driver Detailed Info Seeing Hidden Files on macOS Case Studies Demo Pages / Web Examples Demo Page (Test Page) MFA Login (Test Page) TinyMCE (Test Page) Error Page (Test Page) Drag-&-Drop (Test Page) Device Farm (Virtual) HTML Playground Page SeleniumBase in iframe Page with broken links Shadow DOM/Root W3Schools iframes W3Schools file upload W3Schools doubleclick W3Schools drag & drop W3Schools checkboxes W3Schools radio buttons Presentations Presenter Demo Core Presentation Chart Maker Demo Python Virtual Envs GitHub Pages (seleniumbase.dev) Features List Command Line Tutorial Usage Examples How SeleniumBase Works Installing Python, Pip, & Git Python Virtual Env Tutorial SeleniumBase Installation Webdriver Installation Verify Webdriver Works Console Scripts Tutorial The Dashboard Recorder Mode pytest Commander Syntax Formats Behave BDD Behave Commander Mobile Device Testing Method Summary (API Ref) Case Plans Language Translations Language Locale Codes JS Package Manager Tour Examples Presentation Maker Chart Maker Handling iframes MySQL Installation Overview Using the Selenium Grid Browser Desired Capabilities Safari Driver Detailed Info Seeing Hidden Files on macOS Case Studies

    "}, {"location": "help_docs/behave_gui/", "title": "\ud83d\udc1d Behave-BDD GUI App", "text": ""}, {"location": "help_docs/behave_gui/#seleniumbase-behave-gui-commander", "title": "SeleniumBase Behave GUI / Commander \ud83d\udc1d\ud83c\udf96\ufe0f", "text": "

    \ud83d\udc1d\ud83c\udf96\ufe0f The SeleniumBase Behave GUI lets you run behave scripts from a Desktop GUI.

    \ud83d\udc1d\ud83c\udf96\ufe0f To launch it, call sbase behave-gui or sbase gui-behave:

    > sbase behave-gui\n* Starting the SeleniumBase Behave Commander GUI App...\n

    \ud83d\udc1d\ud83c\udf96\ufe0f SeleniumBase Behave GUI loads the same tests that are found by:

    behave -d\n

    \ud83d\udc1d\ud83c\udf96\ufe0f You can customize which tests are loaded by passing additional args:

    sbase behave-gui [OPTIONAL PATH or TEST FILE]\n

    \ud83d\udc1d\ud83c\udf96\ufe0f Here are examples of customizing test collection:

    sbase behave-gui  # all tests\nsbase behave-gui -i=calculator  # tests with \"calculator\" in the name\nsbase behave-gui features/  # tests located in the \"features/\" folder\nsbase behave-gui features/calculator.feature  # tests in that feature\n

    \ud83d\udc1d\ud83c\udf96\ufe0f Once launched, you can further customize which tests to run and what settings to use. There are various controls for changing settings, modes, and other \"behave\" command line options that are specific to SeleniumBase. You can also set additional options that don't have a visible toggle. When you're ready to run the selected tests with the specified options, click on the Run Selected Tests button.

    \ud83d\udc1d\u26aa With the Dashboard enabled, you'll get one of these:

    To learn more about SeleniumBase, check out the Docs Site:

    All the code is on GitHub:

    "}, {"location": "help_docs/case_plans/", "title": "\ud83d\uddc2\ufe0f Case Plans", "text": ""}, {"location": "help_docs/case_plans/#seleniumbase-case-plans", "title": "SeleniumBase Case Plans \ud83d\uddc2\ufe0fSummary of existing Case Plans", "text": "

    \ud83d\uddc2\ufe0f SeleniumBase Case Plans is Test Case Management Software that uses Markdown tables for displaying test plans directly in GitHub (and other source code management systems that support Markdown format).

    \ud83d\uddc2\ufe0f The case_summary.md file is generated from individual Case Plans that exist in the case_plans/ folders of your repository. (See the example below to learn how the Case Summary file may look.)

    Example of a case_summary.md file:

    \ud83d\udd35 8 Case Plans with customized tables \u2b55 2 Case Plans using boilerplate code \ud83d\udea7 1 Case Plan that is missing a table \ud83d\udd0e (Click rows to expand) \ud83d\udd0d \ud83d\udd35 basic_test.py::MyTestClass::test_basics | # | Step Description | Expected Result | | - | ---------------- | --------------- | | 1 | Log in to https://www.saucedemo.com with ``standard_user``. | Login was successful. | | 2 | Click on the ``Backpack`` ``ADD TO CART`` button. | The button text changed to ``REMOVE``. | | 3 | Click on the cart icon. | The ``Backpack`` is seen in the cart. | | 4 | Remove the ``Backpack`` from the cart. | The ``Backpack`` is no longer in the cart. | | 5 | Log out from the website. | Logout was successful. | \ud83d\udd35 list_assert_test.py::MyTestClass::test_assert_list_of_elements | # | Step Description | Expected Result | | - | ---------------- | --------------- | | 1 | Open https://seleniumbase.io/demo_page. | | | 2 | Use ``self.assert_elements_present(\"head\", \"style\", \"script\")`` to verify that multiple elements are present in the HTML. | The assertion is successful. | | 3 | Use ``self.assert_elements(\"h1\", \"h2\", \"h3\")`` to verify that multiple elements are visible. | The assertion is successful. | | 4 | Use ``self.assert_elements([\"#myDropdown\", \"#myButton\", \"#svgRect\"])`` to verify that multiple elements are visible. | The assertion is successful. | \u2b55 locale_code_test.py::LocaleCodeTests::test_locale_code | # | Step Description | Expected Result | | - | ---------------- | --------------- | | 1 | Perform Action 1 | Verify Action 1 | | 2 | Perform Action 2 | Verify Action 2 | \ud83d\udd35 my_first_test.py::MyTestClass::test_swag_labs | # | Step Description | Expected Result | | - | ---------------- | --------------- | | 1 | Log in to https://www.saucedemo.com with ``standard_user``. | Login was successful. | | 2 | Click on the ``Backpack`` ``ADD TO CART`` button. | The button text changed to ``REMOVE``. | | 3 | Click on the cart icon. | The ``Backpack`` is seen in the cart. | | 4 | Click on the ``CHECKOUT`` button. Enter user details and click ``CONTINUE``. | The ``Backpack`` is seen in the cart on the ``CHECKOUT: OVERVIEW`` page. | | 5 | Click on the ``FINISH`` button. | There is a ``Thank You`` message and a ``Pony Express`` delivery logo. | | 6 | Log out from the website. | Logout was successful. | \u2b55 proxy_test.py::ProxyTests::test_proxy | # | Step Description | Expected Result | | - | ---------------- | --------------- | | 1 | Perform Action 1 | Verify Action 1 | | 2 | Perform Action 2 | Verify Action 2 | \ud83d\udd35 shadow_root_test.py::ShadowRootTest::test_shadow_root | # | Step Description | Expected Result | | - | ---------------- | --------------- | | 1 | Open https://seleniumbase.io/other/shadow_dom. Click each tab and verify the text contained within the Shadow Root sections. | Tab 1 text: ``Content Panel 1`` Tab 2 text: ``Content Panel 2`` Tab 3 text: ``Content Panel 3`` |

    \ud83d\udea7 test_agent.py::UserAgentTests::test_user_agent

    \ud83d\udd35 test_calculator.py::CalculatorTests::test_6_times_7_plus_12_equals_54 | # | Step Description | Expected Result | | - | ---------------- | --------------- | | 1 | Open https://seleniumbase.io/apps/calculator. Perform the following calculation: ``6 \u00d7 7 + 12`` | The output is ``54`` after pressing ``=`` | \ud83d\udd35 test_demo_site.py::DemoSiteTests::test_demo_site | # | Step Description | Expected Result | | - | ---------------- | --------------- | | 1 | Open https://seleniumbase.io/demo_page | | | 2 | Assert the title of the current web page. Assert that a given element is visible on the page. Assert that a text substring appears in an element's text. | The assertions were successful. | | 3 | Type text into various text fields and then verify. | The assertions were successful. | | 4 | Verify that a hover dropdown link changes page text. | The assertion was successful. | | 5 | Verify that a button click changes text on the page. | The assertion was successful. | | 6 | Verify that an SVG element is located on the page. | The assertion was successful. | | 7 | Verify that a slider control updates a progress bar. | The assertion was successful. | | 8 | Verify that a \"select\" option updates a meter bar. | The assertion was successful. | | 9 | Assert an element located inside an iFrame. | The assertion was successful. | | 10 | Assert text located inside an iFrame. | The assertion was successful. | | 11 | Verify that clicking a radio button selects it. | The assertion was successful. | | 12 | Verify that clicking an empty checkbox makes it selected. | The assertion was successful. | | 13 | Verify clicking on multiple elements with one call. | The assertions were successful. | | 14 | Verify that clicking an iFrame checkbox selects it. | The assertions were successful. | | 15 | Verify that Drag and Drop works. | The assertion was successful. | | 16 | Assert link text. | The assertion was successful. | | 17 | Verify clicking on link text. | The action was successful. | | 18 | Assert exact text in an element. | The assertion was successful. | | 19 | Highlight a page element. | The action was successful. | | 20 | Verify that Demo Mode works. | The assertion was successful. | \ud83d\udd35 test_login.py::SwagLabsLoginTests::test_swag_labs_login | # | Step Description | Expected Result | | - | ---------------- | --------------- | | 1 | Log in to https://www.saucedemo.com with ``standard_user``. | Login was successful. | | 2 | Log out from the website. | Logout was successful. | \ud83d\udd35 test_mfa_login.py::TestMFALogin::test_mfa_login | # | Step Description | Expected Result | | - | ---------------- | --------------- | | 1 | Open https://seleniumbase.io/realworld/login Enter credentials and Sign In. | Sign In was successful. | | 2 | Click the ``This Page`` button. Save a screenshot to the logs. | | | 3 | Click to Sign Out | Sign Out was successful. |

    \ud83d\uddc2\ufe0f Before you can generate a case_summary.md file that includes your existing Case Plans, first you'll need to select which existing tests you want to create boilerplate Case Plans from. For that, you can use the SeleniumBase Case Plans GUI:

    sbase caseplans\n

    \ud83d\uddc2\ufe0f Once you are running the Case Plans GUI, select the existing tests that need Case Plans, and then click: Generate boilerplate Case Plans for selected tests missing them. For each selected test that didn't already have a Case Plan file, one will be generated. Each new Case Plan file starts with default boilerplate code with a Markdown table. Eg:

    ``proxy_test.py::ProxyTests::test_proxy``\n---\n| # | Step Description | Expected Result |\n| - | ---------------- | --------------- |\n| 1 | Perform Action 1 | Verify Action 1 |\n| 2 | Perform Action 2 | Verify Action 2 |\n

    \ud83d\uddc2\ufe0f When rendered as a Markdown table, the result looks like this:

    "}, {"location": "help_docs/case_plans/#proxy_testpyproxyteststest_proxy", "title": "proxy_test.py::ProxyTests::test_proxy", "text": "# Step Description Expected Result 1 Perform Action 1 Verify Action 1 2 Perform Action 2 Verify Action 2

    \ud83d\uddc2\ufe0f Markdown tables are flexible, but must be constructed correctly to be displayed. For a Markdown table to render, it's important that you place pipes (|), dashes (-), and spaces in the correct locations. If you want a line break in a step, use <br />. If you want an empty step, put a space between pipes, eg: | |.

    \ud83d\uddc2\ufe0f Here's an example of a Case Plan for my_first_test.py:

    "}, {"location": "help_docs/case_plans/#my_first_testpymytestclasstest_swag_labs", "title": "my_first_test.py::MyTestClass::test_swag_labs", "text": "# Step Description Expected Result 1 Log in to https://www.saucedemo.com with standard_user. Login was successful. 2 Click on the Backpack ADD TO CART button. The button text changed to REMOVE. 3 Click on the cart icon. The Backpack is seen in the cart. 4 Click on the CHECKOUT button. Enter user details and click CONTINUE. The Backpack is seen in the cart on the CHECKOUT: OVERVIEW page. 5 Click on the FINISH button. There is a Thank you message. 6 Log out from the website. Logout was successful.

    \ud83d\uddc2\ufe0f After you've created some Case Plans, you can use the Generate Summary of existing Case Plans button in the Case Plans GUI to generate the Case Plans Summary file.

    \ud83d\uddc2\ufe0f The generated Case Plans summary file, case_summary.md, gets created in the same location where the Case Plans GUI was launched. This is NOT the same location where individual Case Plan boilerplates are generated, which is in the case_plans/ folders. The case_plans/ folders are generated where individual tests live, which means that if you have your tests in multiple folders, then you could also have multiple case_plans/ folders. A case_summary.md file may look like this when rendered:

    \ud83d\uddc2\ufe0f When calling sbase caseplans, you can provide additional arguments to limit the tests that appear in the list. The same discovery rules apply as when using pytest. Eg:

    sbase caseplans\nsbase caseplans -k agent\nsbase caseplans -m marker2\nsbase caseplans test_suite.py\nsbase caseplans offline_examples/\n
    To learn more about SeleniumBase, check out the Docs Site:

    All the code is on GitHub:

    "}, {"location": "help_docs/commander/", "title": "\ud83c\udf96\ufe0f GUI / Commander", "text": ""}, {"location": "help_docs/commander/#seleniumbase-commander", "title": "SeleniumBase Commander \ud83c\udf96\ufe0f", "text": "

    \ud83c\udf96\ufe0f SeleniumBase Commander lets you run pytest scripts from a Desktop GUI.

    \ud83c\udf96\ufe0f To launch it, call sbase commander or sbase gui:

    sbase gui\n* Starting the SeleniumBase Commander Desktop App...\n

    \ud83c\udf96\ufe0f SeleniumBase Commander loads the same tests that are found by:

    pytest --co -q\n

    \ud83c\udf96\ufe0f You can customize which tests are loaded by passing additional args:

    sbase commander [OPTIONAL PATH or TEST FILE]\nsbase gui [OPTIONAL PATH or TEST FILE]\n

    \ud83c\udf96\ufe0f Here are examples of customizing test collection:

    sbase gui\nsbase gui -k agent\nsbase gui -m marker2\nsbase gui test_suite.py\nsbase gui offline_examples/\n

    \ud83c\udf96\ufe0f Once launched, you can further customize which tests to run and what settings to use. There are various controls for changing settings, modes, and other pytest command line options that are specific to SeleniumBase. You can also set additional options that don't have a visible toggle. When you're ready to run the selected tests with the specified options, click on the Run Selected Tests button.

    Other SeleniumBase Commanders:

    To learn more about SeleniumBase, check out the Docs Site:

    All the code is on GitHub:

    "}, {"location": "help_docs/customizing_test_runs/", "title": "\ud83c\udf9b\ufe0f Command Line Options", "text": ""}, {"location": "help_docs/customizing_test_runs/#pytest-options-for-seleniumbase", "title": "pytest options for SeleniumBase", "text": "

    \ud83c\udf9b\ufe0f SeleniumBase's pytest plugin lets you customize test runs from the CLI (Command-Line Interface), which adds options for setting/enabling the browser type, Dashboard Mode, Demo Mode, Headless Mode, Mobile Mode, Multi-threading Mode, Recorder Mode, reuse-session mode, proxy config, user agent config, browser extensions, html-report mode, and more.

    \ud83c\udf9b\ufe0f Here are some examples of configuring tests, which can be run from the examples/ folder:

    # Run a test in Chrome (default browser)\npytest my_first_test.py\n\n# Run a test in Firefox\npytest test_swag_labs.py --firefox\n\n# Run a test in Demo Mode (highlight assertions)\npytest test_demo_site.py --demo\n\n# Run a test in Headless Mode (invisible browser)\npytest test_demo_site.py --headless\n\n# Run tests multi-threaded using [n] threads\npytest test_suite.py -n4\n\n# Reuse the browser session for all tests (\"--reuse-session\")\npytest test_suite.py --rs\n\n# Reuse the browser session, but erase cookies between tests\npytest test_suite.py --rs --crumbs\n\n# Create a real-time dashboard for test results\npytest test_suite.py --dashboard\n\n# Create a pytest html report after tests are done\npytest test_suite.py --html=report.html\n\n# Activate Debug Mode on failures (\"c\" to continue)\npytest test_fail.py --pdb -s\n\n# Rerun failing tests more times\npytest test_suite.py --reruns=1\n\n# Activate Debug Mode as the test begins (\"n\": next. \"c\": continue)\npytest test_null.py --trace -s\n\n# Activate Recorder/Debug Mode as the test begins (\"c\" to continue)\npytest test_null.py --recorder --trace -s\n\n# Pass extra data into tests (retrieve by calling self.data)\npytest my_first_test.py --data=\"ABC,DEF\"\n\n# Run tests on a local Selenium Grid\npytest test_suite.py --server=\"127.0.0.1\"\n\n# Run tests on a remote Selenium Grid\npytest test_suite.py --server=IP_ADDRESS --port=4444\n\n# Run tests on a remote Selenium Grid with authentication\npytest test_suite.py --server=USERNAME:KEY@IP_ADDRESS --port=80\n\n# Run tests through a proxy server\npytest proxy_test.py --proxy=IP_ADDRESS:PORT\n\n# Run tests through a proxy server with authentication\npytest proxy_test.py --proxy=USERNAME:PASSWORD@IP_ADDRESS:PORT\n\n# Run tests while setting the web browser's User Agent\npytest user_agent_test.py --agent=\"USER-AGENT-STRING\"\n\n# Run tests using Chrome's mobile device emulator (default settings)\npytest test_swag_labs.py --mobile\n\n# Run mobile tests specifying CSS Width, CSS Height, and Pixel-Ratio\npytest test_swag_labs.py --mobile --metrics=\"360,640,2\"\n\n# Run a test with an option to evade bot-detection services\npytest verify_undetected.py --uc\n\n# Run tests while changing SeleniumBase default settings\npytest my_first_test.py --settings-file=custom_settings.py\n

    \ud83c\udf9b\ufe0f You can interchange pytest with nosetests for most tests, but using pytest is recommended. (chrome is the default browser if not specified.)

    \ud83c\udf9b\ufe0f If you're using pytest for running tests outside of the SeleniumBase repo, you'll want a copy of pytest.ini at the base of the new folder structure. If using nosetests, the same applies for setup.cfg.

    \ud83c\udf9b\ufe0f Here are some useful command-line options that come with pytest:

    -v  # Verbose mode. Prints the full name of each test and shows more details.\n-q  # Quiet mode. Print fewer details in the console output when running tests.\n-x  # Stop running the tests after the first failure is reached.\n--html=report.html  # Creates a detailed pytest-html report after tests finish.\n--co | --collect-only  # Show what tests would get run. (Without running them)\n--co -q  # (Both options together!) - Do a dry run with full test names shown.\n-n=NUM  # Multithread the tests using that many threads. (Speed up test runs!)\n-s  # See print statements. (Should be on by default with pytest.ini present.)\n--junit-xml=report.xml  # Creates a junit-xml report after tests finish.\n--pdb  # If a test fails, enter Post Mortem Debug Mode. (Don't use with CI!)\n--trace  # Enter Debug Mode at the beginning of each test. (Don't use with CI!)\n-m=MARKER  # Run tests with the specified pytest marker.\n

    \ud83c\udf9b\ufe0f SeleniumBase provides additional pytest command-line options for tests:

    --browser=BROWSER  # (The web browser to use. Default: \"chrome\".)\n--chrome  # (Shortcut for \"--browser=chrome\". On by default.)\n--edge  # (Shortcut for \"--browser=edge\".)\n--firefox  # (Shortcut for \"--browser=firefox\".)\n--safari  # (Shortcut for \"--browser=safari\".)\n--settings-file=FILE  # (Override default SeleniumBase settings.)\n--env=ENV  # (Set the test env. Access with \"self.env\" in tests.)\n--account=STR  # (Set account. Access with \"self.account\" in tests.)\n--data=STRING  # (Extra test data. Access with \"self.data\" in tests.)\n--var1=STRING  # (Extra test data. Access with \"self.var1\" in tests.)\n--var2=STRING  # (Extra test data. Access with \"self.var2\" in tests.)\n--var3=STRING  # (Extra test data. Access with \"self.var3\" in tests.)\n--variables=DICT  # (Extra test data. Access with \"self.variables\".)\n--user-data-dir=DIR  # (Set the Chrome user data directory to use.)\n--protocol=PROTOCOL  # (The Selenium Grid protocol: http|https.)\n--server=SERVER  # (The Selenium Grid server/IP used for tests.)\n--port=PORT  # (The Selenium Grid port used by the test server.)\n--cap-file=FILE  # (The web browser's desired capabilities to use.)\n--cap-string=STRING  # (The web browser's desired capabilities to use.)\n--proxy=SERVER:PORT  # (Connect to a proxy server:port as tests are running)\n--proxy=USERNAME:PASSWORD@SERVER:PORT  # (Use an authenticated proxy server)\n--proxy-bypass-list=STRING # (\";\"-separated hosts to bypass, Eg \"*.foo.com\")\n--proxy-pac-url=URL  # (Connect to a proxy server using a PAC_URL.pac file.)\n--proxy-pac-url=USERNAME:PASSWORD@URL  # (Authenticated proxy with PAC URL.)\n--proxy-driver  # (If a driver download is needed, will use: --proxy=PROXY.)\n--multi-proxy  # (Allow multiple authenticated proxies when multi-threaded.)\n--agent=STRING  # (Modify the web browser's User-Agent string.)\n--mobile  # (Use the mobile device emulator while running tests.)\n--metrics=STRING  # (Set mobile metrics: \"CSSWidth,CSSHeight,PixelRatio\".)\n--chromium-arg=\"ARG=N,ARG2\"  # (Set Chromium args, \",\"-separated, no spaces.)\n--firefox-arg=\"ARG=N,ARG2\"  # (Set Firefox args, comma-separated, no spaces.)\n--firefox-pref=SET  # (Set a Firefox preference:value set, comma-separated.)\n--extension-zip=ZIP  # (Load a Chrome Extension .zip|.crx, comma-separated.)\n--extension-dir=DIR  # (Load a Chrome Extension directory, comma-separated.)\n--binary-location=PATH  # (Set path of the Chromium browser binary to use.)\n--driver-version=VER  # (Set the chromedriver or uc_driver version to use.)\n--sjw  # (Skip JS Waits for readyState to be \"complete\" or Angular to load.)\n--pls=PLS  # (Set pageLoadStrategy on Chrome: \"normal\", \"eager\", or \"none\".)\n--headless  # (Run tests in headless mode. The default arg on Linux OS.)\n--headless2  # (Use the new headless mode, which supports extensions.)\n--headed  # (Run tests in headed/GUI mode on Linux OS, where not default.)\n--xvfb  # (Run tests using the Xvfb virtual display server on Linux OS.)\n--locale=LOCALE_CODE  # (Set the Language Locale Code for the web browser.)\n--interval=SECONDS  # (The autoplay interval for presentations & tour steps)\n--start-page=URL  # (The starting URL for the web browser when tests begin.)\n--archive-logs  # (Archive existing log files instead of deleting them.)\n--archive-downloads  # (Archive old downloads instead of deleting them.)\n--time-limit=SECONDS  # (Safely fail any test that exceeds the time limit.)\n--slow  # (Slow down the automation. Faster than using Demo Mode.)\n--demo  # (Slow down and visually see test actions as they occur.)\n--demo-sleep=SECONDS  # (Set the wait time after Slow & Demo Mode actions.)\n--highlights=NUM  # (Number of highlight animations for Demo Mode actions.)\n--message-duration=SECONDS  # (The time length for Messenger alerts.)\n--check-js  # (Check for JavaScript errors after page loads.)\n--ad-block  # (Block some types of display ads from loading.)\n--block-images  # (Block images from loading during tests.)\n--do-not-track  # (Indicate to websites that you don't want to be tracked.)\n--verify-delay=SECONDS  # (The delay before MasterQA verification checks.)\n--recorder  # (Enables the Recorder for turning browser actions into code.)\n--rec-behave  # (Same as Recorder Mode, but also generates behave-gherkin.)\n--rec-sleep  # (If the Recorder is enabled, also records self.sleep calls.)\n--rec-print  # (If the Recorder is enabled, prints output after tests end.)\n--disable-js  # (Disable JavaScript on websites. Pages might break!)\n--disable-csp  # (Disable the Content Security Policy of websites.)\n--disable-ws  # (Disable Web Security on Chromium-based browsers.)\n--enable-ws  # (Enable Web Security on Chromium-based browsers.)\n--enable-sync  # (Enable \"Chrome Sync\" on websites.)\n--uc | --undetected  # (Use undetected-chromedriver to evade bot-detection.)\n--uc-cdp-events  # (Capture CDP events when running in \"--undetected\" mode.)\n--remote-debug  # (Sync to Chrome Remote Debugger chrome://inspect/#devices)\n--final-debug  # (Enter Debug Mode after each test ends. Don't use with CI!)\n--dashboard  # (Enable the SeleniumBase Dashboard. Saved at: dashboard.html)\n--dash-title=STRING  # (Set the title shown for the generated dashboard.)\n--enable-3d-apis  # (Enables WebGL and 3D APIs.)\n--swiftshader  # (Use Chrome's \"--use-gl=swiftshader\" feature.)\n--incognito  # (Enable Chrome's Incognito mode.)\n--guest  # (Enable Chrome's Guest mode.)\n--dark  # (Enable Chrome's Dark mode.)\n--devtools  # (Open Chrome's DevTools when the browser opens.)\n--rs | --reuse-session  # (Reuse browser session for all tests.)\n--rcs | --reuse-class-session  # (Reuse session for tests in class.)\n--crumbs  # (Delete all cookies between tests reusing a session.)\n--disable-beforeunload  # (Disable the \"beforeunload\" event on Chrome.)\n--window-size=WIDTH,HEIGHT  # (Set the browser's starting window size.)\n--maximize  # (Start tests with the browser window maximized.)\n--screenshot  # (Save a screenshot at the end of each test.)\n--no-screenshot  # (No screenshots saved unless tests directly ask it.)\n--visual-baseline  # (Set the visual baseline for Visual/Layout tests.)\n--wire  # (Use selenium-wire's webdriver for replacing selenium webdriver.)\n--external-pdf  # (Set Chromium \"plugins.always_open_pdf_externally\":True.)\n--timeout-multiplier=MULTIPLIER  # (Multiplies the default timeout values.)\n--list-fail-page  # (After each failing test, list the URL of the failure.)\n

    (For more details, see the full list of command-line options here.)

    \ud83c\udf9b\ufe0f You can also view a list of popular pytest options for SeleniumBase by typing:

    seleniumbase options\n

    Or the short form:

    sbase options\n
    Example tests using Logging:

    To see logging abilities, you can run a test suite that includes tests that fail on purpose:

    pytest test_suite.py\n

    \ud83d\udd35 During test failures, logs and screenshots from the most recent test run will get saved to the latest_logs/ folder. If --archive-logs is specified (or if ARCHIVE_EXISTING_LOGS is set to True in settings.py), test logs will also get archived to the archived_logs/ folder. Otherwise, the log files will be cleaned out when the next test run begins (by default).

    Demo Mode:

    \ud83d\udd35 If any test is moving too fast for your eyes to see what's going on, you can run it in Demo Mode by adding --demo on the command line, which pauses the browser briefly between actions, highlights page elements being acted on, and lets you know what test assertions are happening in real time:

    pytest my_first_test.py --demo\n

    \ud83d\udd35 You can override the default wait time by either updating settings.py or by using --demo-sleep=NUM when using Demo Mode. (NOTE: If you use --demo-sleep=NUM without using --demo, nothing will happen.)

    pytest my_first_test.py --demo --demo-sleep=1.2\n
    Passing additional data to tests:

    If you want to pass additional data from the command line to your tests, you can use --data=STRING. Now inside your tests, you can use self.data to access that.

    Running tests multithreaded:

    To run pytest with multiple processes, add -n=NUM, -n NUM, or -nNUM on the command line, where NUM is the number of CPUs you want to use.

    pytest -n=8\npytest -n 8\npytest -n8\n
    How to retry failing tests automatically:

    You can use pytest --reruns=NUM to retry failing tests that many times. Add --reruns-delay=SECONDS to wait that many seconds between retries. Example:

    pytest --reruns=1 --reruns-delay=1\n
    Debugging tests:

    \ud83d\udd35 You can use the following calls in your scripts to help you debug issues:

    import time; time.sleep(5)  # Makes the test wait and do nothing for 5 seconds.\nimport pdb; pdb.set_trace()  # Debug Mode. n: next, c: continue, s: step, u: up, d: down.\nimport pytest; pytest.set_trace()  # Debug Mode. n: next, c: continue, s: step, u: up, d: down.\n

    \ud83d\udd35 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:

    pytest test_fail.py --pdb\n

    \ud83d\udd35 To start tests in Debug Mode, add --trace as a pytest option:

    pytest test_coffee_cart.py --trace\n

    (pdb commands: n, c, s, u, d => next, continue, step, up, down).

    Combinations of options:

    \ud83c\udf9b\ufe0f There are times when you'll want to combine various command-line options for added effect. For instance, the multi-process option, -n8, can be customized by adding: --dist=loadscope or --dist=loadfile to it. There's more info on that here: pytest-xdist:

    \u25b6\ufe0f -n8 --dist=loadgroup (click to expand)
    @pytest.mark.xdist_group(name=\"group1\")\ndef test_1():\n    pass\n\nclass Test:\n    @pytest.mark.xdist_group(\"group1\")\n    def test_2():\n        pass\n

    This makes test_1 and Test::test_2 run in the same worker. Tests without the xdist_group mark are distributed normally.

    \ud83c\udf9b\ufe0f You might also want to combine multiple options at once. For example:

    pytest --headless -n8 --dashboard --html=report.html -v --rs --crumbs\n

    The above not only runs tests in parallel processes, but it also tells tests in the same process to share the same browser session, runs the tests in headless mode, displays the full name of each test on a separate line, creates a realtime dashboard of the test results, and creates a full report after all tests complete.

    The SeleniumBase Dashboard:

    \ud83d\udd35 The --dashboard option for pytest generates a SeleniumBase Dashboard located at dashboard.html, which updates automatically as tests run and produce results. Example:

    pytest --dashboard --rs --headless\n

    \ud83d\udd35 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:

    python -m http.server 1948\n

    \ud83d\udd35 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.)

    \ud83d\udd35 Here's a full example of what the SeleniumBase Dashboard may look like:

    pytest test_suite.py --dashboard --rs --headless\n

    Pytest Reports:

    \ud83d\udd35 Using --html=report.html gives you a fancy report of the name specified after your test suite completes.

    pytest test_suite.py --html=report.html\n

    \ud83d\udd35 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.

    \ud83d\udd35 Here's an example of an upgraded html report:

    pytest test_suite.py --dashboard --html=report.html\n

    If viewing pytest html reports in Jenkins, you may need to configure Jenkins settings for the html to render correctly. This is due to Jenkins CSP changes.

    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.

    pytest test_suite.py --junit-xml=report.xml\n
    Nosetest Reports:

    The --report option gives you a fancy report after your test suite completes.

    nosetests test_suite.py --report\n

    (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.)

    Language Locale Codes

    You can specify a Language Locale Code to customize web pages on supported websites. With SeleniumBase, you can change the web browser's Locale on the command line by doing this:

    pytest --locale=CODE  # Example: --locale=ru\n

    Visit \ud83d\uddfe Locales for a full list of codes.

    Customizing default settings:

    \ud83c\udf9b\ufe0f An easy way to override seleniumbase/config/settings.py is by using a custom settings file. Here's the command-line option to add to tests: (See examples/custom_settings.py)

    pytest --settings-file=custom_settings.py\n

    (Settings include default timeout values, a two-factor auth key, DB credentials, S3 credentials, and other important settings used by tests.)

    Running tests on a remote Selenium Grid:

    \ud83c\udf10 SeleniumBase lets you run tests on remote Selenium Grids such as BrowserStack's Selenium Grid, LambdaTest's Selenium Grid, Sauce Labs's Selenium Grid, other Grids, and even your own Grid:

    \ud83c\udf10 For setting browser desired capabilities while running Selenium remotely, see the ReadMe located here: https://github.com/seleniumbase/SeleniumBase/tree/master/examples/capabilities

    Here's how to connect to a BrowserStack Selenium Grid server for running tests:

    pytest test_demo_site.py --server=USERNAME:KEY@hub.browserstack.com --port=80\n

    Here's how to connect to a Sauce Labs Selenium Grid server for running tests:

    pytest test_demo_site.py --server=USERNAME:KEY@ondemand.us-east-1.saucelabs.com --port=443 --protocol=https\n

    Here's how to connect to a Perfecto Selenium Grid server for running tests:

    pytest test_demo_site.py --server=USERNAME:KEY@demo.perfectomobile.com/nexperience/perfectomobile --port=443\n

    Here's how to connect to a TestingBot Selenium Grid server for running tests:

    pytest test_demo_site.py --server=USERNAME:KEY@hub.testingbot.com --port=80\n

    Here's how to connect to a LambdaTest Selenium Grid server for running tests:

    pytest test_demo_site.py --server=USERNAME:KEY@hub.lambdatest.com --port=80\n

    Here's how to connect to a CrossBrowserTesting Selenium Grid server for running tests:

    pytest test_demo_site.py --server=USERNAME:KEY@hub.crossbrowsertesting.com --port=80\n

    \ud83c\udf10 Or you can create your own Selenium Grid for test distribution. (See this ReadMe for details)

    \ud83c\udf10 To use a server on the https protocol, add --protocol=https: (Now automatic if the port is 443.)

    pytest test_demo_site.py --protocol=https --server=IP_ADDRESS --port=PORT\n
    Using a Proxy Server:

    \ud83c\udf10 If you wish to use a proxy server for your browser tests (Chromium or Firefox), you can add --proxy=IP_ADDRESS:PORT as an argument on the command line.

    pytest proxy_test.py --proxy=IP_ADDRESS:PORT\n

    \ud83c\udf10 If the proxy server that you wish to use requires authentication, you can do the following (Chromium only):

    pytest proxy_test.py --proxy=USERNAME:PASSWORD@IP_ADDRESS:PORT\n

    \ud83c\udf10 SeleniumBase also supports SOCKS4 and SOCKS5 proxies:

    pytest proxy_test.py --proxy=\"socks4://IP_ADDRESS:PORT\"\n\npytest proxy_test.py --proxy=\"socks5://IP_ADDRESS:PORT\"\n

    To make things easier, you can add your frequently-used proxies to PROXY_LIST in proxy_list.py, and then use --proxy=KEY_FROM_PROXY_LIST to use the IP_ADDRESS:PORT of that key.

    pytest proxy_test.py --proxy=proxy1\n
    Changing the User-Agent:

    \ud83d\udd24 If you wish to change the User-Agent for your browser tests (Chrome and Firefox only), you can add --agent=\"USER-AGENT-STRING\" as an argument on the command line.

    pytest user_agent_test.py --agent=\"Mozilla/5.0 (Nintendo 3DS; U; ; en) Version/1.7412.EU\"\n
    Mobile Device Testing:

    \ud83d\udcf1 Use --mobile to quickly run your tests using Chrome's mobile device emulator with default values for device metrics (CSS Width, CSS Height, Pixel-Ratio) and a default value set for the user agent. To configure the mobile device metrics, use --metrics=\"CSS_Width,CSS_Height,Pixel_Ratio\" to set those values. You'll also be able to set the user agent with --agent=\"USER-AGENT-STRING\" (a default user agent will be used if not specified). To find real values for device metrics, see this GitHub Gist. For a list of available user agent strings, check out this page.

    # Run tests using Chrome's mobile device emulator (default settings)\npytest test_swag_labs.py --mobile\n\n# Run mobile tests specifying CSS Width, CSS Height, and Pixel-Ratio\npytest test_swag_labs.py --mobile --metrics=\"411,731,3\"\n\n# Run mobile tests specifying the user agent\npytest test_swag_labs.py --mobile --agent=\"Mozilla/5.0 (Linux; Android 9; Pixel 3 XL)\"\n

    "}, {"location": "help_docs/demo_mode/", "title": "\ud83c\udfa6 Demo Mode", "text": ""}, {"location": "help_docs/demo_mode/#demo-mode", "title": "Demo Mode \ud83c\udfa6", "text": "

    \ud83d\udd35 Demo Mode helps you see what a test is doing.

    \ud83c\udfc7\ud83d\udca8 \ud83d\udc40 If a test runs too fast for your eyes, use Demo Mode to slow it down, highlight actions, and display assertions. Example usage:

    pytest my_first_test.py --demo\n

    Here's how to run test_swag_labs.py from examples/ in Demo Mode:

    pytest test_swag_labs.py --demo\n

    Here's an example that only uses the highlight() method for highlighting browser actions:

    (test_error_page.py from examples/)

    pytest test_error_page.py\n

    Here's an example of a mobile test in Demo Mode:

    "}, {"location": "help_docs/desired_capabilities/", "title": "\ud83d\udcc3 Desired Capabilities", "text": ""}, {"location": "help_docs/desired_capabilities/#using-desired-capabilities", "title": "Using Desired Capabilities", "text": "

    You can specify browser capabilities when running SeleniumBase tests on a remote Selenium Grid server such as BrowserStack, LambdaTest, or Sauce Labs.

    Sample run commands may look like this when run from the SeleniumBase/examples/ folder: (The browser is now specified in the capabilities file.)

    pytest test_demo_site.py --browser=remote --server=USERNAME:KEY@hub.browserstack.com --port=80 --cap_file=capabilities/sample_cap_file_BS.py\n
    pytest test_demo_site.py --browser=remote --server=USERNAME:KEY@https://@hub.lambdatest.com --port=80 --protocol=https --cap_file=capabilities/sample_cap_file_LT.py\n
    pytest test_demo_site.py --browser=remote --server=USERNAME:KEY@ondemand.us-east-1.saucelabs.com --port=443 --protocol=https --cap_file=capabilities/sample_cap_file_SL.py\n

    (Parameters: --browser=remote, --server=SERVER, --port=PORT, and --cap_file=CAP_FILE.py)

    Here's an example desired capabilities file for BrowserStack:

    desired_cap = {\n    \"os\" : \"Windows\",\n    \"os_version\" : \"11\",\n    \"browser\" : \"Chrome\",\n    \"browser_version\" : \"101.0\",\n    \"browserstack.local\" : \"false\",\n    \"browserstack.debug\" : \"true\",\n    \"browserstack.selenium_version\" : \"4.1.2\",\n}\n

    Here's an example desired capabilities file for LambdaTest:

    capabilities = {\n    \"build\" : \"your build name\",\n    \"name\" : \"your test name\",\n    \"platform\" : \"Windows 11\",\n    \"browserName\" : \"Chrome\",\n    \"version\" : \"101.0\",\n    \"timezone\" : \"UTC+05:30\",\n    \"geoLocation\" : \"IN\",\n}\n

    Here's an example desired capabilities file for Sauce Labs:

    capabilities = {\n    \"browserName\": \"chrome\",\n    \"browserVersion\": \"latest\",\n    \"platformName\": \"macOS 10.14\",\n    \"sauce:options\": {},\n}\n

    (Note that the browser is now being specified in the capabilities file, rather than with --browser=BROWSER when using a remote Selenium Grid. If using a local Selenium Grid, specify the browser, eg: --browser=chrome or --browser=firefox.)

    You can generate specific desired capabilities using: Parsing desired capabilities:

    SeleniumBase has a desired capabilities parser that can capture all lines from the specified file in the following formats:

    'KEY': 'VALUE'\n'KEY': True\n'KEY': False\ncaps['KEY'] = \"VALUE\"\ncaps['KEY'] = True\ncaps['KEY'] = False\n

    (Each pair must be on a separate line. You can interchange single and double quotes.)

    You can also swap --browser=remote with an actual browser, eg --browser=chrome, which will combine the default SeleniumBase desired capabilities with those that were specified in the capabilities file when using --cap_file=FILE.py. Capabilities will override other parameters, so if you set the browser to one thing and the capabilities browser to another, SeleniumBase will use the capabilities browser as the browser.

    You'll need default SeleniumBase capabilities for: * Using a proxy server (not the same as a Selenium Grid server) * Downloading files to a desired folder * Disabling some warnings on Chrome * Overriding a website's Content Security Policy on Chrome * Other possible reasons

    You can also set browser desired capabilities from a command line string: Example:

    pytest test_swag_labs.py --cap-string='{\"browserName\":\"chrome\",\"name\":\"test1\"}' --server=\"127.0.0.1\" --browser=remote\n

    (Enclose cap-string in single quotes. Enclose parameter keys in double quotes.)

    If you pass \"*\" into the \"name\" field of --cap-string, the name will become the test identifier. Example:

    pytest my_first_test.py --cap-string='{\"browserName\":\"chrome\",\"name\":\"*\"}' --server=\"127.0.0.1\" --browser=chrome\n

    Example name: \"my_first_test.MyTestClass.test_basics\"

    Using a local Selenium Grid

    If using a local Selenium Grid with SeleniumBase, start up the Grid Hub and nodes first:

    sbase grid-hub start\nsbase grid-node start\n

    (The Selenium Server JAR file will be automatically downloaded for first-time Grid users. You'll also need Java installed to start up the Grid.)

    "}, {"location": "help_docs/features_list/", "title": "\ud83c\udff0 List of Features", "text": ""}, {"location": "help_docs/features_list/#seleniumbase-features", "title": "SeleniumBase Features: \ud83c\udff0", "text": ""}, {"location": "help_docs/handling_iframes/", "title": "\ud83d\uddbc\ufe0f How to handle iframes", "text": ""}, {"location": "help_docs/handling_iframes/#how-to-handle-iframes", "title": "How to handle iframes", "text": "

    \ud83d\uddbc\ufe0f iframes follow the same principle as new windows: You must first switch to the iframe if you want to perform actions in there:

    self.switch_to_frame(\"iframe\")\n# ... Now perform actions inside the iframe\nself.switch_to_parent_frame()  # Exit the current iframe\n

    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().)

    self.switch_to_frame('iframe[name=\"frame1\"]')\nself.switch_to_frame('iframe[name=\"frame2\"]')\n# ... Now perform actions inside the inner iframe\nself.switch_to_default_content()  # Back to the main page\n

    \ud83d\uddbc\ufe0f You can also use a context manager to act inside iframes:

    with self.frame_switch(\"iframe\"):\n    # ... Now perform actions while inside the code block\n# You have left the iframe\n

    This also works with nested iframes:

    with self.frame_switch('iframe[name=\"frame1\"]'):\n    with self.frame_switch('iframe[name=\"frame2\"]'):\n        # ... Now perform actions while inside the code block\n    # You are now back inside the first iframe\n# You have left all the iframes\n

    \ud83d\uddbc\ufe0f In special cases, you may want to set the page to the content of an iframe:

    self.set_content_to_frame(\"iframe\")\n

    To back out of one call of that, use:

    self.set_content_to_parent()\n

    To back out of all nested calls of that, use:

    self.set_content_to_default()\n

    \ud83d\uddbc\ufe0f See examples/iframe_tests.py for tests that use all available iframe commands.

    "}, {"location": "help_docs/happy_customers/", "title": "\ud83d\udccb Case Studies", "text": ""}, {"location": "help_docs/happy_customers/#businesses-who-have-used-seleniumbase", "title": "Businesses who have used SeleniumBase", "text": ""}, {"location": "help_docs/happy_customers/#case-study", "title": "Case Study", "text": "

    HubSpot:

    In addition to using SeleniumBase for testing the UI of their content management system, HubSpot used SeleniumBase to automate the migration of website pages from their old CMS to their new one, which saved them over one million USD and a significant amount of time.

    Learn how HubSpot uses SeleniumBase for website testing by reading: Automated Testing with Selenium

    For more reading about automation at HubSpot, see: The Classic \"QA Team\" is Obsolete

    "}, {"location": "help_docs/happy_customers/#how-is-this-list-generated", "title": "How is this list generated?", "text": "

    Most of these rows come from LinkedIn search results of profile descriptions, where employees mentioned that they have used SeleniumBase at their company. These details may also be found in other public networks and social media sites, such as GitHub (where organizations could have public repos that use SeleniumBase).

    "}, {"location": "help_docs/hidden_files_info/", "title": "\ud83d\udc65 macOS Hidden Files", "text": ""}, {"location": "help_docs/hidden_files_info/#showing-hidden-files-on-macos", "title": "Showing hidden files on macOS", "text": "

    Depending on your macOS settings, some files may be hidden from view in your Finder window, such as .gitignore.

    Press the \u201cCommand\u201d + \u201cShift\u201d + \u201c.\u201d (period) keys at the same time.

    (The hidden files will show up as translucent in the folder. If you want to obscure the files again, press the same \u201cCommand\u201d + \u201cShift\u201d + \u201c.\u201d (period) combination.)

    defaults write com.apple.finder AppleShowAllFiles -bool true\n

    More info on that can be found here:

    "}, {"location": "help_docs/how_it_works/", "title": "\ud83d\udc41\ufe0f How it Works", "text": ""}, {"location": "help_docs/how_it_works/#how-seleniumbase-works", "title": "How SeleniumBase Works \ud83d\udc41\ufe0f", "text": "

    \ud83d\udc41\ufe0f\ud83d\udd0e At the core, SeleniumBase works by extending pytest as a direct plugin. SeleniumBase automatically spins up web browsers for tests (using Selenium WebDriver), and then gives those tests access to the SeleniumBase libraries through the BaseCase class. Tests are also given access to SeleniumBase command-line options and SeleniumBase methods, which provide additional functionality.

    \ud83d\udc41\ufe0f\ud83d\udd0e pytest uses a feature called test discovery to automatically find and run Python methods that start with test_ when those methods are located in Python files that start with test_ or end with _test.py.

    \ud83d\udc41\ufe0f\ud83d\udd0e The most common way of using SeleniumBase is by importing BaseCase:

    from seleniumbase import BaseCase\n

    \ud83d\udc41\ufe0f\ud83d\udd0e This line activates pytest when a file is called directly with python:

    BaseCase.main(__name__, __file__)\n

    \ud83d\udc41\ufe0f\ud83d\udd0e Classes can inherit BaseCase to gain SeleniumBase functionality:

    class MyTestClass(BaseCase):\n

    \ud83d\udc41\ufe0f\ud83d\udd0e Test methods inside BaseCase classes become SeleniumBase tests: (These tests automatically launch a web browser before starting, and quit the web browser after ending. Default settings can be changed via command-line options.)

        def test_abc(self):\n

    \ud83d\udc41\ufe0f\ud83d\udd0e SeleniumBase APIs can be called from tests via self:

            self.open(\"https://example.com\")\n

    \ud83d\udc41\ufe0f\ud83d\udd0e Here's what a full test might look like:

    from seleniumbase import BaseCase\nBaseCase.main(__name__, __file__)\n\nclass TestMFALogin(BaseCase):\n    def test_mfa_login(self):\n        self.open(\"https://seleniumbase.io/realworld/login\")\n        self.type(\"#username\", \"demo_user\")\n        self.type(\"#password\", \"secret_pass\")\n        self.enter_mfa_code(\"#totpcode\", \"GAXG2MTEOR3DMMDG\")  # 6-digit\n        self.assert_text(\"Welcome!\", \"h1\")\n        self.highlight(\"img#image1\")  # A fancier assert_element() call\n        self.click('a:contains(\"This Page\")')  # Use :contains() on any tag\n        self.save_screenshot_to_logs()  # (\"./latest_logs\" folder for test)\n        self.click_link(\"Sign out\")  # Link must be \"a\" tag. Not \"button\".\n        self.assert_element('a:contains(\"Sign in\")')\n        self.assert_exact_text(\"You have been signed out!\", \"#top_message\")\n

    (See the example, test_mfa_login.py, for reference.)

    \ud83d\udc41\ufe0f\ud83d\udd0e Here are some examples of running tests with pytest:

    pytest test_mfa_login.py\npytest --headless -n8 --dashboard --html=report.html -v --rs --crumbs\npytest -m marker2\npytest -k agent\npytest offline_examples/\n

    (See Syntax_Formats for more ways of structuring SeleniumBase tests.)

    "}, {"location": "help_docs/how_it_works/#no-more-flaky-tests", "title": "\u2705 No More Flaky Tests!", "text": "

    SeleniumBase methods automatically wait for page elements to finish loading before interacting with them (up to a timeout limit). This means you no longer need random time.sleep() statements in your scripts.

    There are three layers of protection that provide reliability for tests using SeleniumBase:

    If you want to speed up your tests and you think the third level of protection is enough by itself, you can use command-line options to remove the first, the second, or both of those first two levels of protection:

    "}, {"location": "help_docs/html_inspector/", "title": "\ud83d\udd75\ufe0f The HTML Inspector", "text": ""}, {"location": "help_docs/html_inspector/#the-html-inspector", "title": "The HTML Inspector \ud83d\udd75\ufe0f", "text": "

    \ud83d\udd75\ufe0f HTML Inspector provides useful info about a web page.

    \ud83d\udd75\ufe0f (Based on: github.com/philipwalton/html-inspector)

    \ud83d\udd75\ufe0f Example: examples/test_inspect_html.py (Chromium-only)

    from seleniumbase import BaseCase\nBaseCase.main(__name__, __file__)\n\nclass HtmlInspectorTests(BaseCase):\n    def test_html_inspector(self):\n        self.open(\"https://xkcd.com/1144/\")\n        self.inspect_html()\n
    pytest test_inspect_html.py\n============== test session starts ==============\n\n* HTML Inspection Results: https://xkcd.com/1144/\n\u26a0\ufe0f  'property' is not a valid attribute of the <meta> element.\n\u26a0\ufe0f  Do not use <div> or <span> elements without any attributes.\n\u26a0\ufe0f  'srcset' is not a valid attribute of the <img> element.\n\u26a0\ufe0f  The 'border' attribute is no longer valid on the <img> element.\n\u26a0\ufe0f  The <center> element is obsolete.\n\u26a0\ufe0f  The id 'comicLinks' appears more than once in the document.\n* (See the Console output for details!)\n
    "}, {"location": "help_docs/install/", "title": "\ud83c\udfc4 Install SeleniumBase", "text": ""}, {"location": "help_docs/install/#seleniumbase-installation", "title": "SeleniumBase Installation", "text": "If installing seleniumbase directly from PyPI, (the Python Package Index), use:
    pip install seleniumbase\n
    To upgrade an existing seleniumbase install from PyPI:
    pip install -U seleniumbase\n
    If installing seleniumbase from a Git clone, use:
    git clone https://github.com/seleniumbase/SeleniumBase.git\ncd SeleniumBase/\npip install .\n
    For a development mode install in editable mode, use:
    git clone https://github.com/seleniumbase/SeleniumBase.git\ncd SeleniumBase/\npip install -e .\n
    To upgrade an existing seleniumbase install from GitHub:
    git pull  # To pull the latest version\npip install -e .  # Or \"pip install .\"\n
    If installing seleniumbase from a GitHub branch, use:
    pip install git+https://github.com/seleniumbase/SeleniumBase.git@master#egg=seleniumbase\n
    pip install can be customized:

    (If you're not using a virtual environment, you may need to add --user to your pip command if you're seeing errors during installation.)

    "}, {"location": "help_docs/install_python_pip_git/", "title": "\ud83d\udc09 Get Python, pip, & git", "text": ""}, {"location": "help_docs/install_python_pip_git/#installation-instructions-for-git-python-and-pip", "title": "Installation instructions for Git, Python, and pip", "text": ""}, {"location": "help_docs/install_python_pip_git/#git", "title": "Git", "text": "

    You can download Git from here.

    (A Git GUI tool like SourceTree or GitHub Desktop can help you with Git commands.)

    (You can also download SeleniumBase from GitHub without using git-related commands.)

    "}, {"location": "help_docs/install_python_pip_git/#python", "title": "Python", "text": "

    You can download Python from https://www.python.org/downloads/ if it's not already preinstalled on your machine.

    "}, {"location": "help_docs/install_python_pip_git/#pip", "title": "pip", "text": "

    pip already comes with Python! (It lets you install packages, such as seleniumbase.)

    \u26a0\ufe0f If something went wrong with your pip installation, try this:

    python -m ensurepip --default-pip\n

    If your existing version of pip is old, upgrade to the latest version:

    python -m pip install --upgrade pip setuptools\n

    On CentOS 7 and some versions of Linux, you may need to install pip with yum:

    yum -y update\nyum -y install python-pip\n

    If you're having any trouble getting pip, you can GET PIP HERE.

    When done, make sure the location of pip is on your path, which is $PATH for macOS/Linux. (On Windows, it's the System Variables Path within System Environment Variables.)

    You can also get pip (or fix pip) by using:

    curl https://bootstrap.pypa.io/get-pip.py | python\n

    Keep Pip and Setuptools up-to-date:

    python -m pip install -U pip setuptools\n
    "}, {"location": "help_docs/js_package_manager/", "title": "\ud83d\udd79\ufe0f Package Manager", "text": ""}, {"location": "help_docs/js_package_manager/#js-package-manager-and-code-generators", "title": "JS Package Manager and Code Generators", "text": "\ud83d\udd79\ufe0f SeleniumBase lets you load JavaScript packages from any CDN link into any website via Python.

    \ud83c\udfa8 The following SeleniumBase solutions utilize this feature:

    \ud83c\udfa6 (Demo Mode)

    \ud83d\ude8e (Website Tours)

    \ud83c\udf9e\ufe0f (Presentation Maker)

    \ud83d\udcca (Chart Maker / Dashboard)

    \ud83d\udec2 (Dialog Boxes / MasterQA)

    \ud83d\uddfa\ufe0f Here's an example of loading a website-tour library into the browser for a Google Maps tour:

    \ud83d\uddfa\ufe0f This example is from maps_introjs_tour.py. (The --interval=1 makes the tour go automatically to the next step after 1 second.)

    cd examples/tour_examples\npytest maps_introjs_tour.py --interval=1\n

    \ud83d\udd79\ufe0f SeleniumBase includes powerful JS code generators for converting Python into JavaScript for using the supported JS packages. A few lines of Python in your tests might generate hundreds of lines of JavaScript.

    \ud83d\uddfa\ufe0f Here is some tour code in Python from maps_introjs_tour.py that expands into a lot of JavaScript.

    self.open(\"https://www.google.com/maps/@42.3591234,-71.0915634,15z\")\nself.create_tour(theme=\"introjs\")\nself.add_tour_step(\"Welcome to Google Maps!\", title=\"SeleniumBase Tours\")\nself.add_tour_step(\"Enter Location\", \"#searchboxinput\", title=\"Search Box\")\nself.add_tour_step(\"See it\", \"#searchbox-searchbutton\", alignment=\"bottom\")\nself.add_tour_step(\"Thanks for using Tours!\", title=\"End of Guided Tour\")\nself.export_tour(filename=\"maps_introjs_tour.js\")\nself.play_tour()\n

    \ud83d\udd79\ufe0f For existing features, SeleniumBase already takes care of loading all the necessary JS and CSS files into the web browser. To load other packages, here are a few useful methods that you should know about:

    self.add_js_link(js_link)\n

    \ud83d\udd79\ufe0f This example loads the IntroJS JavaScript library:

    self.add_js_link(\"https://cdnjs.cloudflare.com/ajax/libs/intro.js/2.9.3/intro.min.js\")\n
    \ud83d\udd79\ufe0f You can load any JS package this way as long as you know the URL.

    \ud83d\udd79\ufe0f If you're wondering how SeleniumBase does this, here's the full Python code from js_utils.py, which uses WebDriver's execute_script() method for making JS calls after escaping quotes with backslashes as needed:

    def add_js_link(driver, js_link):\n    script_to_add_js = (\n\"\"\"function injectJS(link) {\n              var body = document.getElementsByTagName(\"body\")[0];\n              var script = document.createElement(\"script\");\n              script.src = link;\n              script.defer;\n              script.type=\"text/javascript\";\n              script.crossorigin = \"anonymous\";\n              script.onload = function() { null };\n              body.appendChild(script);\n           }\n           injectJS(\"%s\");\"\"\")\n    js_link = escape_quotes_if_needed(js_link)\n    driver.execute_script(script_to_add_js % js_link)\n

    \ud83d\udd79\ufe0f Now that you've loaded JavaScript into the browser, you may also want to load some CSS to go along with it:

    self.add_css_link(css_link)\n

    \ud83d\udd79\ufe0f Here's code that loads the IntroJS CSS:

    self.add_css_link(\"https://cdnjs.cloudflare.com/ajax/libs/intro.js/2.9.3/introjs.css\")\n

    \ud83d\udd79\ufe0f And here's the Python WebDriver code that makes this possible:

    def add_css_link(driver, css_link):\n    script_to_add_css = (\n\"\"\"function injectCSS(css) {\n              var head = document.getElementsByTagName(\"head\")[0];\n              var link = document.createElement(\"link\");\n              link.rel = \"stylesheet\";\n              link.type = \"text/css\";\n              link.href = css;\n              link.crossorigin = \"anonymous\";\n              head.appendChild(link);\n           }\n           injectCSS(\"%s\");\"\"\")\n    css_link = escape_quotes_if_needed(css_link)\n    driver.execute_script(script_to_add_css % css_link)\n
    \ud83d\udd79\ufe0f Website tours are just one of the many uses of the JS Package Manager.

    \ud83d\udec2 The following example shows the JqueryConfirm package loaded into a website for creating fancy dialog boxes:

    \u2195\ufe0f (Example: dialog_box_tour.py) \u2195\ufe0f

    Here's how to run that example:
    cd examples/dialog_boxes\npytest test_dialog_boxes.py\n

    (Example from the Dialog Boxes ReadMe)

    \ud83d\udd79\ufe0f Since packages are loaded directly from a CDN link, you won't need other package managers like NPM, Bower, or Yarn to get the packages that you need into the websites that you want.

    To learn more about SeleniumBase, check out the Docs Site:

    All the code is on GitHub:

    "}, {"location": "help_docs/locale_codes/", "title": "\ud83d\uddfe Locale Codes", "text": ""}, {"location": "help_docs/locale_codes/#language-locale-codes", "title": "Language Locale Codes", "text": "

    You can specify a Language Locale Code to customize web pages on supported websites. With SeleniumBase, you can change the web browser's Locale on the command line by doing this:

    pytest --locale=CODE  # Example: --locale=ru\n
    List of Language Locale Codes: LanguageCode Afrikaansaf Amharicam Arabicar Arabic (Egypt)ar_eg Arabic (Saudi Arabia)ar_sa Basqueeu Belarusianbe Bengalibn Bulgarianbg Catalanca Chinesezh Chinese (China Mainland)zh_cn Chinese (Hong Kong)zh_hk Chinese (Taiwan)zh_tw Croatianhr Czechcs Danishda Dutchnl Englishen English (United States)en_us English (Australia)en_au English (Canada)en_ca English (United Kingdom)en_gb English (Ireland)en_ie English (India)en_in English (Singapore)en_sg English (South Africa)en_za Estonianet Farsifa Filipinofil Finnishfi Frenchfr French (Canada)fr_ca French (Switzerland)fr_ch Galiciangl Germande German (Austria)de_at Greekel Gujaratigu Hebrewhe Hindihi Hungarianhu Icelandicis Indonesianid Italianit Japaneseja Kannadakn Koreanko Laolo Latvianlv Lingalaln Lithuanianlt Malayms Malayalamml Marathimr Norwegianno Polishpl Portuguesept Portuguese (Brazil)pt_br Portuguese (Portugal)pt_pt Romanianro Russianru Serbiansr Slovaksk Sloveniansl Spanishes Spanish (Latin America)es_419 Spanish (Argentina)es_ar Spanish (Chile)es_cl Spanish (Colombia)es_co Spanish (Costa Rica)es_cr Spanish (Dominican Rep.)es_do Spanish (Ecuador)es_ec Spanish (El Salvador)es_sv Spanish (Guatemala)es_gt Spanish (Honduras)es_hn Spanish (Mexico)es_mx Spanish (Nicaragua)es_ni Spanish (Panama)es_pa Spanish (Peru)es_pe Spanish (Puerto Rico)es_pr Spanish (Paraguay)es_py Spanish (United States)es_us Spanish (Uruguay)es_uy Spanish (Venezuela)es_ve Swahilisw Swedishsv Swiss Germangsw Tagalogtl Tamilta Telugute Thaith Turkishtr Ukrainianuk Urduur Vietnamesevi Zuluzu"}, {"location": "help_docs/method_summary/", "title": "\ud83d\udcd8 API Reference", "text": ""}, {"location": "help_docs/method_summary/#seleniumbase-methods-api-reference", "title": "SeleniumBase Methods (API Reference)\ud83d\udd35 Examples", "text": "

    Here's a list of SeleniumBase method definitions, which are defined in base_case.py

    For backwards compatibility, older versions of method names have remained to keep older scripts working. (E.g: wait_for_element_visible was shortened to wait_for_element and then to find_element.)

    self.open(url)\n# Duplicates: self.open_url(url), self.visit(url), visit_url(url),\n#             self.goto(url), self.go_to(url)\n\nself.get(url)\n# If the url parameter is a URL: Perform self.open(url)\n# Otherwise: return self.get_element(URL_AS_A_SELECTOR)\n\nself.click(selector, by=\"css selector\", timeout=None, delay=0, scroll=True)\n\nself.slow_click(selector, by=\"css selector\", timeout=None)\n\nself.double_click(selector, by=\"css selector\", timeout=None)\n\nself.context_click(selector, by=\"css selector\", timeout=None)\n# Duplicates\n# self.right_click(selector, by=\"css selector\", timeout=None)\n\nself.click_chain(selectors_list, by=\"css selector\", timeout=None, spacing=0)\n\nself.type(selector, text, by=\"css selector\", timeout=None)\n# Duplicates\n# self.update_text(selector, text, by=\"css selector\", timeout=None)\n# self.input(selector, text, by=\"css selector\", timeout=None)\n# self.fill(selector, text, by=\"css selector\", timeout=None)\n# self.write(selector, text, by=\"css selector\", timeout=None)\n\nself.send_keys(selector, text, by=\"css selector\", timeout=None)\n# Duplicates\n# self.add_text(selector, text, by=\"css selector\", timeout=None)\n\nself.submit(selector, by=\"css selector\")\n\nself.clear(selector, by=\"css selector\", timeout=None)\n\nself.focus(selector, by=\"css selector\", timeout=None)\n\nself.refresh()\n# Duplicates: self.refresh_page(), self.reload_page(), self.reload()\n\nself.get_current_url()\n\nself.get_origin()\n\nself.get_page_source()\n\nself.get_title()\n# Duplicates: self.get_page_title()\n\nself.get_user_agent()\n\nself.get_locale_code()\n\nself.go_back()\n\nself.go_forward()\n\nself.open_start_page()\n\nself.open_if_not_url(url)\n\nself.is_element_present(selector, by=\"css selector\")\n\nself.is_element_visible(selector, by=\"css selector\")\n\nself.is_element_clickable(selector, by=\"css selector\")\n\nself.is_element_enabled(selector, by=\"css selector\")\n\nself.is_text_visible(text, selector=\"html\", by=\"css selector\")\n\nself.is_exact_text_visible(text, selector=\"html\", by=\"css selector\")\n\nself.is_non_empty_text_visible(selector=\"html\", by=\"css selector\")\n\nself.is_attribute_present(selector, attribute, value=None, by=\"css selector\")\n\nself.is_link_text_visible(link_text)\n\nself.is_partial_link_text_visible(partial_link_text)\n\nself.is_link_text_present(link_text)\n\nself.is_partial_link_text_present(link_text)\n\nself.get_link_attribute(link_text, attribute, hard_fail=True)\n# Duplicates\n# self.get_link_text_attribute(link_text, attribute, hard_fail=True)\n\nself.get_partial_link_text_attribute(link_text, attribute, hard_fail=True)\n\nself.click_link(link_text, timeout=None)\n# Duplicates\n# self.click_link_text(link_text, timeout=None)\n\nself.click_partial_link(partial_link_text, timeout=None)\n# Duplicates\n# self.click_partial_link_text(partial_link_text, timeout=None)\n\nself.get_text(selector, by=\"css selector\", timeout=None)\n\nself.get_attribute(selector, attribute, by=\"css selector\", timeout=None, hard_fail=True)\n\nself.set_attribute(selector, attribute, value, by=\"css selector\", timeout=None, scroll=False)\n\nself.set_attributes(selector, attribute, value, by=\"css selector\")\n# Duplicates\n# self.set_attribute_all(selector, attribute, value, by=\"css selector\")\n\nself.remove_attribute(selector, attribute, by=\"css selector\", timeout=None)\n\nself.remove_attributes(selector, attribute, by=\"css selector\")\n\nself.get_property(selector, property, by=\"css selector\", timeout=None)\n\nself.get_text_content(selector, by=\"css selector\", timeout=None)\n\nself.get_property_value(selector, property, by=\"css selector\", timeout=None)\n\nself.get_image_url(selector, by=\"css selector\", timeout=None)\n\nself.find_elements(selector, by=\"css selector\", limit=0)\n\nself.find_visible_elements(selector, by=\"css selector\", limit=0)\n\nself.click_visible_elements(selector, by=\"css selector\", limit=0, timeout=None)\n\nself.click_nth_visible_element(selector, number, by=\"css selector\", timeout=None)\n\nself.click_if_visible(selector, by=\"css selector\", timeout=0)\n\nself.click_active_element()\n\nself.click_with_offset(\n    selector, x, y, by=\"css selector\", mark=None, timeout=None, center=None)\n\nself.double_click_with_offset(\n    selector, x, y, by=\"css selector\", mark=None, timeout=None, center=None)\n\nself.is_checked(selector, by=\"css selector\", timeout=None)\n# Duplicates\n# self.is_selected(selector, by=\"css selector\", timeout=None)\n\nself.check_if_unchecked(selector, by=\"css selector\")\n# Duplicates\n# self.select_if_unselected(selector, by=\"css selector\")\n\nself.uncheck_if_checked(selector, by=\"css selector\")\n# Duplicates\n# self.unselect_if_selected(selector, by=\"css selector\")\n\nself.is_element_in_an_iframe(selector, by=\"css selector\")\n\nself.switch_to_frame_of_element(selector, by=\"css selector\")\n\nself.hover(selector, by=\"css selector\", timeout=None)\n# Duplicates\n# self.hover_on_element(selector, by=\"css selector\", timeout=None)\n# self.hover_over_element(selector, by=\"css selector\", timeout=None)\n\nself.hover_and_click(\n    hover_selector, click_selector,\n    hover_by=\"css selector\", click_by=\"css selector\",\n    timeout=None)\n\nself.hover_and_double_click(\n    hover_selector, click_selector,\n    hover_by=\"css selector\", click_by=\"css selector\",\n    timeout=None)\n\nself.drag_and_drop(\n    drag_selector, drop_selector,\n    drag_by=\"css selector\", drop_by=\"css selector\",\n    timeout=None, jquery=False)\n\nself.drag_and_drop_with_offset(\n    selector, x, y, by=\"css selector\", timeout=None)\n\nself.select_option_by_text(\n    dropdown_selector, option, dropdown_by=\"css selector\", timeout=None)\n\nself.select_option_by_index(\n    dropdown_selector, option, dropdown_by=\"css selector\", timeout=None)\n\nself.select_option_by_value(\n    dropdown_selector, option, dropdown_by=\"css selector\", timeout=None)\n\nself.get_select_options(\n    dropdown_selector, attribute=\"text\", by=\"css selector\", timeout=None)\n\nself.load_html_string(html_string, new_page=True)\n\nself.set_content(html_string, new_page=False)\n\nself.load_html_file(html_file, new_page=True)\n\nself.open_html_file(html_file)\n\nself.execute_script(script, *args, **kwargs)\n\nself.execute_cdp_cmd(script, *args, **kwargs)\n\nself.execute_async_script(script, timeout=None)\n\nself.safe_execute_script(script, *args, **kwargs)\n\nself.set_window_rect(x, y, width, height)\n\nself.set_window_size(width, height)\n\nself.maximize_window()\n\nself.switch_to_frame(frame, timeout=None)\n\nself.switch_to_default_content()\n\nself.switch_to_parent_frame()\n\nwith self.frame_switch(frame, timeout=None):\n    # Indented Code Block for Context Manager (Must use \"with\")\n\nself.set_content_to_frame(frame, timeout=None)\n\nself.set_content_to_default(nested=False)\n# Duplicates: self.set_content_to_default_content(nested=False)\n\nself.set_content_to_parent()\n# Duplicates: self.set_content_to_parent_frame()\n\nself.open_new_window(switch_to=True)\n# Duplicates: self.open_new_tab(switch_to=True)\n\nself.switch_to_window(window, timeout=None)\n# Duplicates: self.switch_to_tab(tab, timeout=None)\n\nself.switch_to_default_window()\n# Duplicates: self.switch_to_default_tab()\n\nself.switch_to_newest_window()\n# Duplicates: self.switch_to_newest_tab()\n\nself.get_new_driver(\n    browser=None,\n    headless=None,\n    locale_code=None,\n    protocol=None,\n    servername=None,\n    port=None,\n    proxy=None,\n    proxy_bypass_list=None,\n    proxy_pac_url=None,\n    multi_proxy=None,\n    agent=None,\n    switch_to=True,\n    cap_file=None,\n    cap_string=None,\n    recorder_ext=None,\n    disable_js=None,\n    disable_csp=None,\n    enable_ws=None,\n    enable_sync=None,\n    use_auto_ext=None,\n    undetectable=None,\n    uc_cdp_events=None,\n    uc_subprocess=None,\n    no_sandbox=None,\n    disable_gpu=None,\n    headless2=None,\n    incognito=None,\n    guest_mode=None,\n    devtools=None,\n    remote_debug=None,\n    enable_3d_apis=None,\n    swiftshader=None,\n    ad_block_on=None,\n    block_images=None,\n    do_not_track=None,\n    chromium_arg=None,\n    firefox_arg=None,\n    firefox_pref=None,\n    user_data_dir=None,\n    extension_zip=None,\n    extension_dir=None,\n    binary_location=None,\n    page_load_strategy=None,\n    use_wire=None,\n    external_pdf=None,\n    is_mobile=None,\n    d_width=None,\n    d_height=None,\n    d_p_r=None,\n)\n\nself.switch_to_driver(driver)\n\nself.switch_to_default_driver()\n\nself.save_screenshot(name, folder=None, selector=None, by=\"css selector\")\n\nself.save_screenshot_to_logs(name=None, selector=None, by=\"css selector\")\n\nself.save_data_to_logs(data, file_name=None)\n\nself.append_data_to_logs(data, file_name=None)\n\nself.save_page_source(name, folder=None)\n\nself.save_cookies(name=\"cookies.txt\")\n\nself.load_cookies(name=\"cookies.txt\")\n\nself.delete_all_cookies()\n# Duplicates: self.clear_all_cookies()\n\nself.delete_saved_cookies(name=\"cookies.txt\")\n\nself.wait_for_ready_state_complete(timeout=None)\n\nself.wait_for_angularjs(timeout=None)\n\nself.sleep(seconds)\n# Duplicates: self.wait(seconds)\n\nself.install_addon(xpi_file)\n\nself.activate_jquery()\n\nself.activate_demo_mode()\n\nself.deactivate_demo_mode()\n\nself.activate_design_mode()\n\nself.deactivate_design_mode()\n\nself.activate_recorder()\n\nself.save_recorded_actions()\n\nself.bring_active_window_to_front()\n\nself.bring_to_front(selector, by=\"css selector\")\n\nself.highlight_click(selector, by=\"css selector\", loops=3, scroll=True)\n\nself.highlight_type(selector, text, by=\"css selector\", loops=3, scroll=True)\n# Duplicates\n# self.highlight_update_text(selector, text, by=\"css selector\", loops=3, scroll=True)\n\nself.highlight(selector, by=\"css selector\", loops=4, scroll=True)\n\nself.press_up_arrow(selector=\"html\", times=1, by=\"css selector\")\n\nself.press_down_arrow(selector=\"html\", times=1, by=\"css selector\")\n\nself.press_left_arrow(selector=\"html\", times=1, by=\"css selector\")\n\nself.press_right_arrow(selector=\"html\", times=1, by=\"css selector\")\n\nself.scroll_to(selector, by=\"css selector\", timeout=None)\n# Duplicates: self.scroll_to_element(selector, by=\"css selector\")\n\nself.slow_scroll_to(selector, by=\"css selector\", timeout=None)\n# Duplicates: self.slow_scroll_to_element(selector, by=\"css selector\")\n\nself.scroll_into_view(selector, by=\"css selector\", timeout=None)\n\nself.scroll_to_top()\n\nself.scroll_to_bottom()\n\nself.click_xpath(xpath)\n\nself.js_click(selector, by=\"css selector\", all_matches=False, scroll=True)\n\nself.js_click_if_present(selector, by=\"css selector\", timeout=0)\n\nself.js_click_if_visible(selector, by=\"css selector\", timeout=0)\n\nself.js_click_all(selector, by=\"css selector\")\n\nself.jquery_click(selector, by=\"css selector\")\n\nself.jquery_click_all(selector, by=\"css selector\")\n\nself.hide_element(selector, by=\"css selector\")\n\nself.hide_elements(selector, by=\"css selector\")\n\nself.show_element(selector, by=\"css selector\")\n\nself.show_elements(selector, by=\"css selector\")\n\nself.remove_element(selector, by=\"css selector\")\n\nself.remove_elements(selector, by=\"css selector\")\n\nself.ad_block()\n# Duplicates: self.block_ads()\n\nself.show_file_choosers()\n\nself.disable_beforeunload()\n\nself.get_domain_url(url)\n\nself.get_beautiful_soup(source=None)\n\nself.get_unique_links()\n\nself.get_link_status_code(link, allow_redirects=False, timeout=5, verify=False)\n\nself.assert_link_status_code_is_not_404(link)\n\nself.assert_no_404_errors(multithreaded=True, timeout=None)\n# Duplicates\n# self.assert_no_broken_links(multithreaded=True, timeout=None)\n\nself.print_unique_links_with_status_codes()\n\nself.get_pdf_text(\n    pdf, page=None, maxpages=None, password=None,\n    codec='utf-8', wrap=False, nav=False, override=False, caching=True)\n\nself.assert_pdf_text(\n    pdf, text, page=None, maxpages=None, password=None,\n    codec='utf-8', wrap=True, nav=False, override=False, caching=True)\n\nself.create_folder(folder)\n\nself.choose_file(selector, file_path, by=\"css selector\", timeout=None)\n\nself.save_element_as_image_file(selector, file_name, folder=None, overlay_text=\"\")\n\nself.download_file(file_url, destination_folder=None)\n\nself.save_file_as(file_url, new_file_name, destination_folder=None)\n\nself.save_data_as(data, file_name, destination_folder=None)\n\nself.append_data_to_file(data, file_name, destination_folder=None)\n\nself.get_file_data(file_name, folder=None)\n\nself.get_downloads_folder()\n\nself.get_browser_downloads_folder()\n\nself.get_path_of_downloaded_file(file, browser=False)\n\nself.is_downloaded_file_present(file, browser=False)\n\nself.delete_downloaded_file_if_present(file, browser=False)\n# Duplicates: self.delete_downloaded_file(file, browser=False)\n\nself.assert_downloaded_file(file, timeout=None, browser=False)\n\nself.assert_true(expr, msg=None)\n\nself.assert_false(expr, msg=None)\n\nself.assert_equal(first, second, msg=None)\n\nself.assert_not_equal(first, second, msg=None)\n\nself.assert_in(first, second, msg=None)\n\nself.assert_not_in(first, second, msg=None)\n\nself.assert_raises(*args, **kwargs)\n\nself.wait_for_attribute(selector, attribute, value=None, by=\"css selector\", timeout=None)\n\nself.assert_attribute(selector, attribute, value=None, by=\"css selector\", timeout=None)\n\nself.assert_title(title)\n\nself.assert_title_contains(substring)\n\nself.assert_url(url)\n\nself.assert_url_contains(substring)\n\nself.assert_no_js_errors(exclude=[])\n\nself.inspect_html()\n\nself.is_valid_url(url)\n\nself.is_online()\n\nself.is_chromium()\n\nself.get_chrome_version()\n\nself.get_chromium_version()\n\nself.get_chromedriver_version()\n\nself.get_chromium_driver_version()\n\nself.get_mfa_code(totp_key=None)\n# Duplicates\n# self.get_totp_code(totp_key=None)\n# self.get_google_auth_password(totp_key=None)\n# self.get_google_auth_code(totp_key=None)\n\nself.enter_mfa_code(selector, totp_key=None, by=\"css selector\", timeout=None)\n# Duplicates\n# self.enter_totp_code(selector, totp_key=None, by=\"css selector\", timeout=None)\n\nself.convert_css_to_xpath(css)\n\nself.convert_xpath_to_css(xpath)\n\nself.convert_to_css_selector(selector, by)\n\nself.set_value(selector, text, by=\"css selector\", timeout=None, scroll=True)\n\nself.js_update_text(selector, text, by=\"css selector\", timeout=None)\n# Duplicates\n# self.js_type(selector, text, by=\"css selector\", timeout=None)\n# self.set_text(selector, text, by=\"css selector\", timeout=None)\n\nself.set_text_content(selector, text, by=\"css selector\", timeout=None, scroll=False)\n\nself.jquery_update_text(selector, text, by=\"css selector\", timeout=None)\n# Duplicates\n# self.jquery_type(selector, text, by=\"css selector\", timeout=None)\n\nself.get_value(selector, by=\"css selector\", timeout=None)\n\nself.set_time_limit(time_limit)\n\nself.set_default_timeout(timeout)\n\nself.reset_default_timeout()\n\nself.fail(msg=None)\n\nself.skip(reason=\"\")\n\n############\n\nself.start_recording_console_logs()\n\nself.console_log_string(string)\n\nself.console_log_script(script)\n\nself.get_recorded_console_logs()\n\n############\n\nself.set_local_storage_item(key, value)\n\nself.get_local_storage_item(key)\n\nself.remove_local_storage_item(key)\n\nself.clear_local_storage()\n\nself.get_local_storage_keys()\n\nself.get_local_storage_items()\n\nself.set_session_storage_item(key, value)\n\nself.get_session_storage_item(key)\n\nself.remove_session_storage_item(key)\n\nself.clear_session_storage()\n\nself.get_session_storage_keys()\n\nself.get_session_storage_items()\n\n############\n\nself.set_wire_proxy(string)  # Requires \"--wire\"!\n\n############\n\nself.add_css_link(css_link)\n\nself.add_js_link(js_link)\n\nself.add_css_style(css_style)\n\nself.add_js_code_from_link(js_link)\n\nself.add_js_code(js_code)\n\nself.add_meta_tag(http_equiv=None, content=None)\n\n############\n\nself.create_presentation(name=None, theme=\"default\", transition=\"default\")\n\nself.add_slide(\n    content=None, image=None, code=None, iframe=None,\n    content2=None, notes=None, transition=None, name=None)\n\nself.save_presentation(\n    name=None, filename=None, show_notes=False, interval=0)\n\nself.begin_presentation(\n    name=None, filename=None, show_notes=False, interval=0)\n\n############\n\nself.create_pie_chart(\n    chart_name=None, title=None, subtitle=None,\n    data_name=None, unit=None, libs=True,\n    labels=True, legend=True)\n\nself.create_bar_chart(\n    chart_name=None, title=None, subtitle=None,\n    data_name=None, unit=None, libs=True,\n    labels=True, legend=True)\n\nself.create_column_chart(\n    chart_name=None, title=None, subtitle=None,\n    data_name=None, unit=None, libs=True,\n    labels=True, legend=True)\n\nself.create_line_chart(\n    chart_name=None, title=None, subtitle=None,\n    data_name=None, unit=None, zero=False, libs=True,\n    labels=True, legend=True)\n\nself.create_area_chart(\n    chart_name=None, title=None, subtitle=None,\n    data_name=None, unit=None, zero=False, libs=True,\n    labels=True, legend=True)\n\nself.add_series_to_chart(data_name=None, chart_name=None)\n\nself.add_data_point(label, value, color=None, chart_name=None)\n\nself.save_chart(chart_name=None, filename=None, folder=None)\n\nself.display_chart(chart_name=None, filename=None, interval=0)\n\nself.extract_chart(chart_name=None)\n\n############\n\nself.create_tour(name=None, theme=None)\n\nself.create_shepherd_tour(name=None, theme=None)\n\nself.create_bootstrap_tour(name=None)\n\nself.create_hopscotch_tour(name=None)\n\nself.create_introjs_tour(name=None)\n\nself.set_introjs_colors(theme_color=None, hover_color=None)\n\nself.add_tour_step(\n    message, selector=None, name=None, title=None, theme=None, alignment=None)\n\nself.play_tour(name=None, interval=0)\n# Duplicates\n# self.start_tour(name=None, interval=0):\n\nself.export_tour(name=None, filename=\"my_tour.js\", url=None)\n\n############\n\nself.activate_jquery_confirm()\n\nself.set_jqc_theme(theme, color=None, width=None)\n\nself.reset_jqc_theme()\n\nself.get_jqc_button_input(message, buttons, options=None)\n\nself.get_jqc_text_input(message, button=None, options=None)\n\nself.get_jqc_form_inputs(message, buttons, options=None)\n\n############\n\nself.activate_messenger()\n\nself.post_message(message, duration=None, pause=True, style=\"info\")\n\nself.post_message_and_highlight(message, selector, by=\"css selector\")\n\nself.post_success_message(message, duration=None, pause=True)\n\nself.post_error_message(message, duration=None, pause=True)\n\nself.set_messenger_theme(\n    theme=\"default\", location=\"default\", max_messages=\"default\")\n\n############\n\nself.generate_referral(start_page, destination_page, selector=None)\n\nself.generate_traffic(start_page, destination_page, loops=1, selector=None)\n\nself.generate_referral_chain(pages)\n\nself.generate_traffic_chain(pages, loops=1)\n\n############\n\nself.get_element(selector, by=\"css selector\", timeout=None)\n# Duplicates\n# self.wait_for_element_present(selector, by=\"css selector\", timeout=None)\n\nself.wait_for_query_selector(selector, by=\"css selector\", timeout=None)\n\nself.assert_element_present(selector, by=\"css selector\", timeout=None)\n\nself.assert_elements_present(*args, **kwargs)\n\n############\n\nself.find_element(selector, by=\"css selector\", timeout=None)\n# Duplicates\n# self.wait_for_element(selector, by=\"css selector\", timeout=None)\n# self.wait_for_element_visible(selector, by=\"css selector\", timeout=None)\n\nself.assert_element(selector, by=\"css selector\", timeout=None)\n# Duplicates\n# self.assert_element_visible(selector, by=\"css selector\", timeout=None)\n\nself.assert_elements(*args, **kwargs)\n# Duplicates\n# self.assert_elements_visible(*args, **kwargs)\n\n############\n\nself.find_text(text, selector=\"html\", by=\"css selector\", timeout=None)\n# Duplicates\n# self.wait_for_text(text, selector=\"html\", by=\"css selector\", timeout=None)\n# self.wait_for_text_visible(text, selector=\"html\", by=\"css selector\", timeout=None)\n\nself.find_exact_text(text, selector=\"html\", by=\"css selector\", timeout=None)\n# Duplicates\n# self.wait_for_exact_text(text, selector=\"html\", by=\"css selector\", timeout=None)\n# self.wait_for_exact_text_visible(text, selector=\"html\", by=\"css selector\", timeout=None)\n\nself.find_non_empty_text(selector=\"html\", by=\"css selector\", timeout=None)\n# Duplicates\n# self.wait_for_non_empty_text(selector=\"html\", by=\"css selector\", timeout=None)\n# self.wait_for_non_empty_text_visible(selector=\"html\", by=\"css selector\", timeout=None)\n\nself.assert_text(text, selector=\"html\", by=\"css selector\", timeout=None)\n# Duplicates\n# self.assert_text_visible(text, selector=\"html\", by=\"css selector\", timeout=None)\n\nself.assert_exact_text(text, selector=\"html\", by=\"css selector\", timeout=None)\n\n############\n\nself.wait_for_link_text_present(link_text, timeout=None)\n\nself.wait_for_partial_link_text_present(link_text, timeout=None)\n\nself.find_link_text(link_text, timeout=None)\n# Duplicates\n# self.wait_for_link_text(link_text, timeout=None)\n# self.wait_for_link_text_visible(link_text, timeout=None)\n\nself.assert_link_text(link_text, timeout=None)\n# Duplicates\n# self.assert_link(link_text, timeout=None)\n\n############\n\nself.find_partial_link_text(partial_link_text, timeout=None)\n# Duplicates\n# self.wait_for_partial_link_text(partial_link_text, timeout=None)\n\nself.assert_partial_link_text(partial_link_text, timeout=None)\n\n############\n\nself.wait_for_element_absent(selector, by=\"css selector\", timeout=None)\n# Duplicates\n# self.wait_for_element_not_present(selector, by=\"css selector\", timeout=None)\n\nself.assert_element_absent(selector, by=\"css selector\", timeout=None)\n# Duplicates\n# self.assert_element_not_present(selector, by=\"css selector\", timeout=None)\n\n############\n\nself.wait_for_element_clickable(selector, by=\"css selector\", timeout=None)\n\n############\n\nself.wait_for_element_not_visible(selector, by=\"css selector\", timeout=None)\n\nself.assert_element_not_visible(selector, by=\"css selector\", timeout=None)\n\n############\n\nself.wait_for_text_not_visible(text, selector=\"html\", by=\"css selector\", timeout=None)\n\nself.wait_for_exact_text_not_visible(text, selector=\"html\", by=\"css selector\", timeout=None)\n\nself.assert_text_not_visible(text, selector=\"html\", by=\"css selector\", timeout=None)\n\nself.assert_exact_text_not_visible(text, selector=\"html\", by=\"css selector\", timeout=None)\n\nself.assert_non_empty_text(selector=\"html\", by=\"css selector\", timeout=None)\n\n############\n\nself.wait_for_attribute_not_present(\n    selector, attribute, value=None, by=\"css selector\", timeout=None)\n\nself.assert_attribute_not_present(\n    selector, attribute, value=None, by=\"css selector\", timeout=None)\n\n############\n\nself.accept_alert(timeout=None)\n# Duplicates\n# self.wait_for_and_accept_alert(timeout=None)\n\nself.dismiss_alert(timeout=None)\n# Duplicates\n# self.wait_for_and_dismiss_alert(timeout=None)\n\nself.switch_to_alert(timeout=None)\n# Duplicates\n# self.wait_for_and_switch_to_alert(timeout=None)\n\n############\n\nself.quit_extra_driver(driver=None)\n\n############\n\nself.check_window(\n    name=\"default\", level=0, baseline=False, check_domain=True, full_diff=False)\n\n############\n\nself.deferred_assert_element(\n    selector, by=\"css selector\", timeout=None, fs=False)\n# Duplicates\n# self.delayed_assert_element(\n#     selector, by=\"css selector\", timeout=None, fs=False)\n\nself.deferred_assert_element_present(\n    selector, by=\"css selector\", timeout=None, fs=False)\n# Duplicates\n# self.delayed_assert_element_present(\n#     selector, by=\"css selector\", timeout=None, fs=False)\n\nself.deferred_assert_text(\n    text, selector=\"html\", by=\"css selector\", timeout=None, fs=False)\n# Duplicates\n# self.delayed_assert_text(\n#     text, selector=\"html\", by=\"css selector\", timeout=None, fs=False)\n\nself.deferred_assert_exact_text(\n    text, selector=\"html\", by=\"css selector\", timeout=None, fs=False)\n# Duplicates\n# self.delayed_assert_exact_text(\n#     text, selector=\"html\", by=\"css selector\", timeout=None, fs=False)\n\nself.deferred_assert_non_empty_text(\n    selector=\"html\", by=\"css selector\", timeout=None, fs=False)\n# Duplicates\n# self.delayed_assert_non_empty_text(\n#     selector=\"html\", by=\"css selector\", timeout=None, fs=False)\n\nself.deferred_check_window(\n    name=\"default\", level=0, baseline=False, check_domain=True, full_diff=False, fs=False)\n# Duplicates\n# self.delayed_check_window(\n#     name=\"default\", level=0, baseline=False,\n#     check_domain=True, full_diff=False, fs=False)\n\nself.process_deferred_asserts(print_only=False)\n# Duplicates: self.process_delayed_asserts(print_only=False)\n\n############\n\nself.fail(msg=None)  # Inherited from \"unittest\"\n\nself._print(TEXT)  # Calls Python's print() / Allows for translations\n

    \u2705 Test Folder: SeleniumBase/examples

    "}, {"location": "help_docs/mobile_testing/", "title": "\ud83d\udcf1 Mobile Testing", "text": ""}, {"location": "help_docs/mobile_testing/#mobile-testing", "title": "Mobile Testing", "text": "

    Use --mobile to run SeleniumBase tests using Chrome's mobile device emulator with default values for Device Metrics and User-Agent.

    Here's an example mobile test:

    SeleniumBase/examples/test_skype_site.py

    pytest test_skype_site.py --mobile\n

    To configure Device Metrics, use:

    --metrics=\"CSS_Width,CSS_Height,Pixel_Ratio\"\n

    To configure the User-Agent, use:

    --agent=\"USER-AGENT-STRING\"\n

    To find real values for Device Metrics, see:

    To find real User-Agent strings, see:

    Here's another example of a mobile test:

    SeleniumBase/examples/test_swag_labs.py

    pytest test_swag_labs.py --mobile\n

    Here's an example of configuring mobile settings for that test:

    # Run tests using Chrome's mobile device emulator (default settings)\npytest test_swag_labs.py --mobile\n\n# Run mobile tests specifying CSS Width, CSS Height, and Pixel-Ratio\npytest test_swag_labs.py --mobile --metrics=\"360,640,2\"\n\n# Run mobile tests specifying the user agent\npytest test_swag_labs.py --mobile --agent=\"Mozilla/5.0 (Linux; Android 9; Pixel 3 XL)\"\n

    "}, {"location": "help_docs/mysql_installation/", "title": "\ud83d\uddc4\ufe0f MySQL Instructions", "text": ""}, {"location": "help_docs/mysql_installation/#mysql-installation-instructions", "title": "MySQL Installation Instructions", "text": ""}, {"location": "help_docs/mysql_installation/#mysql-optional", "title": "MySQL (OPTIONAL)", "text": "

    (NOTE: If you don't plan on using the SeleniumBase MySQL DB feature, then you can skip this section.)

    "}, {"location": "help_docs/mysql_installation/#github-actions-ubuntu-linux-mysql-setup", "title": "GitHub Actions Ubuntu Linux MySQL Setup", "text": "
    sudo /etc/init.d/mysql start\nmysql -e 'CREATE DATABASE IF NOT EXISTS test_db;' -uroot -proot\nwget https://raw.githubusercontent.com/seleniumbase/SeleniumBase/master/seleniumbase/core/create_db_tables.sql\nsudo mysql -h 127.0.0.1 -uroot -proot test_db < create_db_tables.sql\nsudo mysql -e 'ALTER USER \"root\"@\"localhost\" IDENTIFIED BY \"test\";' -uroot -proot\nsudo service mysql restart\n

    Have SeleniumBase tests write to the MySQL DB:

    pytest --with-db_reporting\n

    Query MySQL DB Results:

    mysql -e 'select test_address,browser,state,start_time,runtime from test_db.test_run_data;' -uroot -ptest\n
    "}, {"location": "help_docs/mysql_installation/#standard-ubuntu-linux-mysql-setup", "title": "Standard Ubuntu Linux MySQL Setup", "text": "
    sudo apt update\nsudo apt install mysql-server\nsudo mysql_secure_installation\nsudo mysql -e 'CREATE DATABASE IF NOT EXISTS test_db;'\nsudo mysql -h 127.0.0.1 -u root test_db < seleniumbase/core/create_db_tables.sql\nsudo service mysql restart\n

    To change the password from root to test:

    mysqladmin -u root -p'root' password 'test'\nsudo service mysql restart\n
    "}, {"location": "help_docs/mysql_installation/#macos-mysql-setup", "title": "MacOS MySQL Setup", "text": "
    brew install mysql\n

    Then start the MySQL service:

    brew services start mysql\n

    (Continue with additional steps below to set up your DB.)

    "}, {"location": "help_docs/mysql_installation/#windows-mysql-setup", "title": "Windows MySQL Setup", "text": "

    Download MySQL here Follow the steps from the MySQL Downloads page.

    (Continue with additional steps below to set up your DB.)

    "}, {"location": "help_docs/mysql_installation/#access-your-mysql-db", "title": "Access your MySQL DB", "text": "

    If you want a visual tool to help make your MySQL life easier, try MySQL Workbench.

    "}, {"location": "help_docs/mysql_installation/#prepare-your-mysql-db", "title": "Prepare your MySQL DB", "text": "

    Use the create_db_tables.sql file to create the necessary tables for storing test data.

    "}, {"location": "help_docs/mysql_installation/#configure-your-mysql-db-for-seleniumbase", "title": "Configure your MySQL DB for SeleniumBase", "text": "

    Update your settings.py file with your MySQL DB credentials so that tests can write to the database when they run.

    "}, {"location": "help_docs/mysql_installation/#have-seleniumbase-tests-write-to-your-mysql-db", "title": "Have SeleniumBase tests write to your MySQL DB", "text": "

    Add the --with-db_reporting argument on the command line when you want tests to write to your MySQL database. Example:

    pytest --with-db_reporting\n
    "}, {"location": "help_docs/recorder_mode/", "title": "\ud83d\udd34 Recorder Mode", "text": ""}, {"location": "help_docs/recorder_mode/#recorder-mode", "title": "Recorder Mode \ud83d\udd34/\u23fa\ufe0f", "text": "

    \ud83d\udd34 SeleniumBase Recorder Mode lets you record & export browser actions into test automation scripts.

    \u23fa\ufe0f To make a new recording with Recorder Mode, use sbase mkrec, sbase codegen, or sbase record):

    sbase mkrec TEST_NAME.py --url=URL\n

    If the file already exists, you'll get an error. If no URL is provided, you'll start on a blank page and will need to navigate somewhere for the Recorder to activate. (The Recorder captures events on URLs that start with https, http, or file.) The command above runs an empty test that stops at a breakpoint so that you can perform manual browser actions for the Recorder. When you have finished recording, type \"c\" on the command-line and press [ENTER] to continue from the breakpoint. The test will complete and a file called TEST_NAME_rec.py will be automatically created in the ./recordings folder. That file will get copied back to the original folder with the name you gave it. (You can run with Edge instead of Chrome by adding --edge to the command above. For headed Linux machines, add --gui to prevent the default headless mode on Linux.)

    Example:

    sbase mkrec new_test.py --url=wikipedia.org\n\n* RECORDING initialized: new_test.py\n\npytest new_test.py --rec -q -s --url=wikipedia.org\n\n>>>>>>>>>>>>>>>>>> PDB set_trace >>>>>>>>>>>>>>>>>\n\n> PATH_TO_YOUR_CURRENT_DIRECTORY/new_test.py(9)\n.\n   5         def test_recording(self):\n   6             if self.recorder_ext:\n   7                 # When done recording actions,\n8                 # type \"c\", and press [Enter].\n9  ->             import pdb; pdb.set_trace()\nreturn None\n(Pdb+) c\n\n>>>>>>>>>>>>>>>>>> PDB continue >>>>>>>>>>>>>>>>>>\n\n>>> RECORDING SAVED as: recordings/new_test_rec.py\n**************************************************\n\n*** RECORDING COPIED to: new_test.py\n

    \ud83d\udd34 You can also activate Recorder Mode from the Desktop App:

    sbase recorder\n* Starting the SeleniumBase Recorder Desktop App...\n

    \u23fa\ufe0f While a recording is in progress, you can press the [ESC] key to pause the Recorder. To resume the recording, you can hit the [~`] key, which is located directly below the [ESC] key on most keyboards.

    \u23fa\ufe0f From within Recorder Mode there are two additional modes: \"Assert Element Mode\" and \"Assert Text Mode\". To switch into \"Assert Element Mode\", press the [^]-key (SHIFT+6): The border will become purple, and you'll be able to click on elements to assert from your test. To switch into \"Assert Text Mode\", press the [&]-key (SHIFT+7): The border will become teal, and you'll be able to click on elements for asserting text from your test.

    While using either of the two special Assertion Modes, certain actions such as clicking on links won't have any effect. This lets you make assertions on elements without navigating away from the page, etc. To add an assertion for buttons without triggering default \"click\" behavior, mouse-down on the button and then mouse-up somewhere else. (This prevents a detected click while still recording the assert.) To return back to the original Recorder Mode, press any key other than [SHIFT] or [BACKSPACE] (Eg: Press [CONTROL], etc.). Press [ESC] once to leave the Assertion Modes, but it'll stop the Recorder if you press it again.

    \u23fa\ufe0f For extra flexibility, the sbase mkrec command can be split into four separate commands:

    sbase mkfile TEST_NAME.py --rec\n\npytest TEST_NAME.py --rec -q -s\n\nsbase print ./recordings/TEST_NAME_rec.py -n\n\ncp ./recordings/TEST_NAME_rec.py ./TEST_NAME.py\n

    The first command creates a boilerplate test with a breakpoint; the second command runs the test with the Recorder activated; the third command prints the completed test to the console; and the fourth command replaces the initial boilerplate with the completed test. If you're just experimenting with the Recorder, you can run the second command as many times as you want, and it'll override previous recordings saved to ./recordings/TEST_NAME_rec.py. (Note that -s is needed to allow breakpoints, unless you already have a pytest.ini file present with addopts = --capture=no in it. The -q is optional, which shortens pytest console output.)

    \u23fa\ufe0f You can also use the Recorder to add code to an existing test. To do that, you'll first need to create a breakpoint in your code to insert manual browser actions:

    import pdb; pdb.set_trace()\n

    Now you'll be able to run your test with pytest, and it will stop at the breakpoint for you to add in actions: (Press c and ENTER on the command-line to continue from the breakpoint.)

    pytest TEST_NAME.py --rec -s\n

    \u23fa\ufe0f You can also set a breakpoint at the start of your test by adding --trace as a pytest command-line option: (This is useful when running Recorder Mode without any pdb breakpoints.)

    pytest TEST_NAME.py --trace --rec -s\n

    \u23fa\ufe0f After the test completes, a file called TEST_NAME_rec.py will be automatically created in the ./recordings folder, which will include the actions performed by the test, and the manual actions that you added in.

    \u23fa\ufe0f Here's a command-line notification for a completed recording:

    >>> RECORDING SAVED as: recordings/TEST_NAME_rec.py\n***************************************************\n

    \u23fa\ufe0f When running additional tests from the same Python module, Recordings will get added to the file that was created from the first test:

    >>> RECORDING ADDED to: recordings/TEST_NAME_rec.py\n***************************************************\n

    \u23fa\ufe0f Recorder Mode works by saving your recorded actions into the browser's sessionStorage. SeleniumBase then reads from the browser's sessionStorage to take the raw data and generate a full test from it. Keep in mind that sessionStorage is only present while the browser tab remains in the same domain/origin. (The sessionStorage of that tab goes away if you leave that domain/origin.) To compensate, links to web pages of different domain/origin will automatically open a new tab for you in Recorder Mode.

    \u23fa\ufe0f Additionally, the SeleniumBase self.open(URL) method will also open a new tab for you in Recorder Mode if the domain/origin is different from the current URL. If you need to navigate to a different domain/origin from within the same tab, call self.save_recorded_actions() first, which saves the recorded data for later. When a recorded test completes, SeleniumBase scans the sessionStorage data of all open browser tabs for generating the completed script.

    \u23fa\ufe0f As an alternative to activating Recorder Mode with the --rec command-line arg, you can also call self.activate_recorder() from your tests. Using the Recorder this way is only useful for tests that stay on the same URL. This is because the standard Recorder Mode functions as a Chrome extension and persists wherever the browser goes. (This version only stays on the page where called.)

    \u23fa\ufe0f (Note that same domain/origin is not the same as same URL. Example: https://xkcd.com/353 and https://xkcd.com/1537 are two different URLs with the same domain/origin. That means both URLs share the same sessionStorage, and that changes persist to different URLs of the same domain/origin. If you want to find out a website's origin during a test, just call: self.get_origin(), which returns the value of window.location.origin from the browser's console.)

    \u23fa\ufe0f Inside recorded tests, you might find the self.open_if_not_url(URL) method, which opens the URL given if the browser is not currently on that page. SeleniumBase uses this method in recorded scripts when the Recorder detects that a browser action changed the current URL. This method prevents an unnecessary page load and shows what page the test visited after a browser action.

    To learn more about SeleniumBase, check out the Docs Site:

    All the code is on GitHub:

    "}, {"location": "help_docs/shadow_dom/", "title": "\ud83d\udc64 Shadow DOM Support", "text": ""}, {"location": "help_docs/shadow_dom/#shadow-dom-support-shadow-root-interaction", "title": "Shadow DOM support / Shadow-root interaction", "text": "

    \ud83d\udd35 SeleniumBase lets you pierce through open Shadow DOM selectors (to interact with elements inside) by adding ::shadow to CSS fragments that include a shadow-root element. For multi-layered shadow-roots, you must individually pierce through each shadow-root element that you want to get through.

    \ud83d\udd35 Here are some examples of Shadow DOM selectors:

    css_1 = \"downloads-manager::shadow #no-downloads\"\n\ncss_2 = \"downloads-manager::shadow #downloadsList downloads-item::shadow #file-link\"\n\ncss_3 = \"downloads-manager::shadow downloads-toolbar::shadow cr-toolbar::shadow cr-toolbar-search-field::shadow cr-icon-button\"\n\ncss_4 = \"downloads-manager::shadow downloads-toolbar::shadow cr-toolbar::shadow cr-toolbar-search-field::shadow #searchInput\"\n\ncss_5 = \"downloads-manager::shadow downloads-toolbar::shadow cr-toolbar::shadow cr-toolbar-search-field::shadow #clearSearch\"\n

    \ud83d\udd35 The shadow-root (::shadow) elements are transitional, and therefore cannot be the final part of your CSS selectors. Complete your CSS selectors by including an element that's inside a shadow-root.

    \ud83d\udd35 NOTE: ::shadow selectors only exist within SeleniumBase. (They are not part of standard CSS.)

    \ud83d\udd35 Here are some examples of tests that interact with Shadow DOM elements: * examples/shadow_root_test.py * examples/test_shadow_dom.py * examples/old_wordle_script.py

    "}, {"location": "help_docs/syntax_formats/", "title": "\ud83d\udd21 Syntax Formats", "text": ""}, {"location": "help_docs/syntax_formats/#the-23-syntax-formats-design-patterns", "title": "The 23 Syntax Formats / Design Patterns 1. BaseCase direct class inheritance 2. BaseCase subclass inheritance 3. The \"sb\" pytest fixture (no class) 4. The \"sb\" pytest fixture (in class) 5. Page Object Model with BaseCase 6. Page Object Model with the \"sb\" fixture 7. Using \"request\" to get \"sb\" (no class) 8. Using \"request\" to get \"sb\" (in class) 9. Overriding the driver via BaseCase 10. Overriding the driver via \"sb\" fixture 11. BaseCase with Chinese translations 12. BaseCase with Dutch translations 13. BaseCase with French translations 14. BaseCase with Italian translations 15. BaseCase with Japanese translations 16. BaseCase with Korean translations 17. BaseCase with Portuguese translations 18. BaseCase with Russian translations 19. BaseCase with Spanish translations 20. Gherkin syntax with \"behave\" BDD runner 21. SeleniumBase SB (Python context manager) 22. The driver manager (via context manager) 23. The driver manager (via direct import)", "text": "SeleniumBase supports multiple ways of structuring tests:

    In this format, (which is used by most of the tests in the SeleniumBase examples folder), BaseCase is imported at the top of a Python file, followed by a Python class inheriting BaseCase. Then, any test method defined in that class automatically gains access to SeleniumBase methods, including the setUp() and tearDown() methods that are automatically called for opening and closing web browsers at the start and end of tests.

    To run a test of this format, use pytest or pynose. Adding BaseCase.main(__name__, __file__) enables python to run pytest on your file indirectly. Here's an example:

    from seleniumbase import BaseCase\nBaseCase.main(__name__, __file__)\n\nclass MyTestClass(BaseCase):\n    def test_demo_site(self):\n        self.open(\"https://seleniumbase.io/demo_page\")\n        self.type(\"#myTextInput\", \"This is Automated\")\n        self.click(\"#myButton\")\n        self.assert_element(\"tbody#tbodyId\")\n        self.assert_text(\"Automation Practice\", \"h3\")\n        self.click_link(\"SeleniumBase Demo Page\")\n        self.assert_exact_text(\"Demo Page\", \"h1\")\n        self.assert_no_js_errors()\n

    (See examples/test_demo_site.py for the full test.)

    Using BaseCase inheritance is a great starting point for anyone learning SeleniumBase, and it follows good object-oriented programming principles.

    There are situations where you may want to customize the setUp and tearDown of your tests. Maybe you want to have all your tests login to a specific web site first, or maybe you want to have your tests report results through an API call depending on whether a test passed or failed. This can be done by creating a subclass of BaseCase and then carefully creating custom setUp() and tearDown() methods that don't overwrite the critical functionality of the default SeleniumBase setUp() and tearDown() methods. Afterwards, your test classes will inherit the subclass of BaseCase with the added functionality, rather than directly inheriting BaseCase itself. Here's an example of that:

    from seleniumbase import BaseCase\nBaseCase.main(__name__, __file__)\n\nclass BaseTestCase(BaseCase):\n    def setUp(self):\n        super().setUp()\n        # <<< Run custom setUp() code for tests AFTER the super().setUp() >>>\n\n    def tearDown(self):\n        self.save_teardown_screenshot()  # On failure or \"--screenshot\"\n        if self.has_exception():\n            # <<< Run custom code if the test failed. >>>\n            pass\n        else:\n            # <<< Run custom code if the test passed. >>>\n            pass\n        # (Wrap unreliable tearDown() code in a try/except block.)\n        # <<< Run custom tearDown() code BEFORE the super().tearDown() >>>\n        super().tearDown()\n\n    def login(self):\n        # <<< Placeholder. Add your code here. >>>\n        # Reduce duplicate code in tests by having reusable methods like this.\n        # If the UI changes, the fix can be applied in one place.\n        pass\n\n    def example_method(self):\n        # <<< Placeholder. Add your code here. >>>\n        pass\n\nclass MyTests(BaseTestCase):\n    def test_example(self):\n        self.login()\n        self.example_method()\n        self.type(\"input\", \"Name\")\n        self.click(\"form button\")\n        # ...\n

    (See examples/boilerplates/base_test_case.py for more info.)

    The pytest framework comes with a unique system called fixtures, which replaces import statements at the top of Python files by importing libraries directly into test definitions. More than just being an import, a pytest fixture can also automatically call predefined setUp() and tearDown() methods at the beginning and end of test methods. To work, sb is added as an argument to each test method definition that needs SeleniumBase functionality. This means you no longer need import statements in your Python files to use SeleniumBase. If using other pytest fixtures in your tests, you may need to use the SeleniumBase fixture (instead of BaseCase class inheritance) for compatibility reasons. Here's an example of the sb fixture in a test that does not use Python classes:

    def test_sb_fixture_with_no_class(sb):\n    sb.open(\"https://google.com/ncr\")\n    sb.type('[title=\"Search\"]', 'SeleniumBase\\n')\n    sb.click('a[href*=\"github.com/seleniumbase/SeleniumBase\"]')\n    sb.click('a[title=\"seleniumbase\"]')\n

    (See the top of examples/test_sb_fixture.py for the test.)

    The sb pytest fixture can also be used inside of a class. There is a slight change to the syntax because that means test methods must also include self in their argument definitions when test methods are defined. (The self argument represents the class object, and is used in every test method that lives inside of a class.) Once again, no import statements are needed in your Python files for this to work. Here's an example of using the sb fixture in a test method that lives inside of a Python class:

    class Test_SB_Fixture:\n    def test_sb_fixture_inside_class(self, sb):\n        sb.open(\"https://google.com/ncr\")\n        sb.type('[title=\"Search\"]', 'SeleniumBase\\n')\n        sb.click('a[href*=\"github.com/seleniumbase/SeleniumBase\"]')\n        sb.click('a[title=\"examples\"]')\n

    (See the bottom of examples/test_sb_fixture.py for the test.)

    With SeleniumBase, you can use Page Objects to break out code from tests, but remember, the self variable (from test methods that inherit BaseCase) contains the driver and all other framework-specific variable definitions. Therefore, that self must be passed as an arg into any outside class method in order to call SeleniumBase methods from there. In the example below, the self variable from the test method is passed into the sb arg of the Page Object class method because the self arg of the Page Object class method is already being used for its own class. Every Python class method definition must include the self as the first arg.

    from seleniumbase import BaseCase\nBaseCase.main(__name__, __file__)\n\nclass LoginPage:\n    def login_to_swag_labs(self, sb, username):\n        sb.open(\"https://www.saucedemo.com\")\n        sb.type(\"#user-name\", username)\n        sb.type(\"#password\", \"secret_sauce\")\n        sb.click('input[type=\"submit\"]')\n\nclass MyTests(BaseCase):\n    def test_swag_labs_login(self):\n        LoginPage().login_to_swag_labs(self, \"standard_user\")\n        self.assert_element(\"div.inventory_list\")\n        self.assert_element('div:contains(\"Sauce Labs Backpack\")')\n

    (See examples/boilerplates/samples/swag_labs_test.py for the full test.)

    This is similar to the classic Page Object Model with BaseCase inheritance, except that this time we pass the sb pytest fixture from the test into the sb arg of the page object class method, (instead of passing self). Now that you're using sb as a pytest fixture, you no longer need to import BaseCase anywhere in your code. See the example below:

    class LoginPage:\n    def login_to_swag_labs(self, sb, username):\n        sb.open(\"https://www.saucedemo.com\")\n        sb.type(\"#user-name\", username)\n        sb.type(\"#password\", \"secret_sauce\")\n        sb.click('input[type=\"submit\"]')\n\nclass MyTests:\n    def test_swag_labs_login(self, sb):\n        LoginPage().login_to_swag_labs(sb, \"standard_user\")\n        sb.assert_element(\"div.inventory_list\")\n        sb.assert_element('div:contains(\"Sauce Labs Backpack\")')\n

    (See examples/boilerplates/samples/sb_swag_test.py for the full test.)

    The pytest request fixture can be used to retrieve other pytest fixtures from within tests, such as the sb fixture. This allows you to have more control over when fixtures get initialized because the fixture no longer needs to be loaded at the very beginning of test methods. This is done by calling request.getfixturevalue('sb') from the test. Here's an example of using the pytest request fixture to load the sb fixture in a test method that does not use Python classes:

    def test_request_sb_fixture(request):\n    sb = request.getfixturevalue('sb')\n    sb.open(\"https://seleniumbase.io/demo_page\")\n    sb.assert_text(\"SeleniumBase\", \"#myForm h2\")\n    sb.assert_element(\"input#myTextInput\")\n    sb.type(\"#myTextarea\", \"This is me\")\n    sb.click(\"#myButton\")\n    sb.tearDown()\n

    (See the top of examples/test_request_sb_fixture.py for the test.)

    The pytest request fixture can also be used to get the sb fixture from inside a Python class. Here's an example of that:

    class Test_Request_Fixture:\n    def test_request_sb_fixture_in_class(self, request):\n        sb = request.getfixturevalue('sb')\n        sb.open(\"https://seleniumbase.io/demo_page\")\n        sb.assert_element(\"input#myTextInput\")\n        sb.type(\"#myTextarea\", \"Automated\")\n        sb.assert_text(\"This Text is Green\", \"#pText\")\n        sb.click(\"#myButton\")\n        sb.assert_text(\"This Text is Purple\", \"#pText\")\n        sb.tearDown()\n

    (See the bottom of examples/test_request_sb_fixture.py for the test.)

    When you want to use SeleniumBase methods via BaseCase, but you want total freedom to control how you spin up your web browsers, this is the format you want. Although SeleniumBase gives you plenty of command-line options to change how your browsers are launched, this format gives you more control when the existing options aren't enough. Here's an example of that:

    from selenium import webdriver\nfrom seleniumbase import BaseCase\nBaseCase.main(__name__, __file__)\n\nclass OverrideDriverTest(BaseCase):\n    def get_new_driver(self, *args, **kwargs):\n\"\"\"This method overrides get_new_driver() from BaseCase.\"\"\"\n        options = webdriver.ChromeOptions()\n        options.add_argument(\"--disable-3d-apis\")\n        options.add_argument(\"--disable-notifications\")\n        if self.headless:\n            options.add_argument(\"--headless=new\")\n            options.add_argument(\"--disable-gpu\")\n        options.add_experimental_option(\n            \"excludeSwitches\", [\"enable-automation\", \"enable-logging\"],\n        )\n        prefs = {\n            \"credentials_enable_service\": False,\n            \"profile.password_manager_enabled\": False,\n        }\n        options.add_experimental_option(\"prefs\", prefs)\n        return webdriver.Chrome(options=options)\n\n    def test_simple(self):\n        self.open(\"https://seleniumbase.io/demo_page\")\n        self.assert_text(\"Demo Page\", \"h1\")\n

    (From examples/test_override_driver.py)

    The above format lets you customize selenium-wire for intercepting and inspecting requests and responses during SeleniumBase tests. Here's how a selenium-wire integration may look:

    from seleniumbase import BaseCase\nfrom seleniumwire import webdriver  # Requires \"pip install selenium-wire\"\nBaseCase.main(__name__, __file__)\n\n\nclass WireTestCase(BaseCase):\n    def get_new_driver(self, *args, **kwargs):\n        options = webdriver.ChromeOptions()\n        options.add_experimental_option(\n            \"excludeSwitches\", [\"enable-automation\"]\n        )\n        options.add_experimental_option(\"useAutomationExtension\", False)\n        return webdriver.Chrome(options=options)\n\n    def test_simple(self):\n        self.open(\"https://seleniumbase.io/demo_page\")\n        for request in self.driver.requests:\n            print(request.url)\n

    (NOTE: The selenium-wire integration is now included with seleniumbase: Add --wire as a pytest command-line option to activate.)

    When you want to use SeleniumBase methods via the sb pytest fixture, but you want total freedom to control how you spin up your web browsers, this is the format you want. Although SeleniumBase gives you plenty of command-line options to change how your browsers are launched, this format gives you more control when the existing options aren't enough.

    \"\"\"Overriding the \"sb\" fixture to override the driver.\"\"\"\nimport pytest\n\n@pytest.fixture()\ndef sb(request):\n    from selenium import webdriver\n    from seleniumbase import BaseCase\n\n    class BaseClass(BaseCase):\n        def get_new_driver(self, *args, **kwargs):\n\"\"\"This method overrides get_new_driver() from BaseCase.\"\"\"\n            options = webdriver.ChromeOptions()\n            if self.headless:\n                options.add_argument(\"--headless=new\")\n                options.add_argument(\"--disable-gpu\")\n            options.add_experimental_option(\n                \"excludeSwitches\", [\"enable-automation\"],\n            )\n            return webdriver.Chrome(options=options)\n\n        def setUp(self):\n            super().setUp()\n\n        def base_method(self):\n            pass\n\n        def tearDown(self):\n            self.save_teardown_screenshot()  # On failure or \"--screenshot\"\n            super().tearDown()\n\n    sb = BaseClass(\"base_method\")\n    sb.setUpClass()\n    sb.setUp()\n    yield sb\n    sb.tearDown()\n    sb.tearDownClass()\n\ndef test_override_fixture_no_class(sb):\n    sb.open(\"https://seleniumbase.io/demo_page\")\n    sb.type(\"#myTextInput\", \"This is Automated\")\n\nclass TestOverride:\n    def test_override_fixture_inside_class(self, sb):\n        sb.open(\"https://seleniumbase.io/demo_page\")\n        sb.type(\"#myTextInput\", \"This is Automated\")\n

    (From examples/test_override_sb_fixture.py)

    Here's how the selenium-wire integration may look when overriding the sb pytest fixture to override the driver:

    import pytest\n\n@pytest.fixture()\ndef sb(request):\n    import sys\n    from seleniumbase import BaseCase\n    from seleniumwire import webdriver  # Requires \"pip install selenium-wire\"\n\n    class BaseClass(BaseCase):\n        def get_new_driver(self, *args, **kwargs):\n            options = webdriver.ChromeOptions()\n            if \"linux\" in sys.platform:\n                options.add_argument(\"--headless=new\")\n            options.add_experimental_option(\n                \"excludeSwitches\", [\"enable-automation\"],\n            )\n            return webdriver.Chrome(options=options)\n\n        def setUp(self):\n            super().setUp()\n\n        def tearDown(self):\n            self.save_teardown_screenshot()  # On failure or \"--screenshot\"\n            super().tearDown()\n\n        def base_method(self):\n            pass\n\n    sb = BaseClass(\"base_method\")\n    sb.setUpClass()\n    sb.setUp()\n    yield sb\n    sb.tearDown()\n    sb.tearDownClass()\n\ndef test_wire_with_no_class(sb):\n    sb.open(\"https://seleniumbase.io/demo_page\")\n    for request in sb.driver.requests:\n        print(request.url)\n\nclass TestWire:\n    def test_wire_inside_class(self, sb):\n        sb.open(\"https://seleniumbase.io/demo_page\")\n        for request in sb.driver.requests:\n            print(request.url)\n

    (NOTE: The selenium-wire integration is now included with seleniumbase: Add --wire as a pytest command-line option to activate. If you need both --wire with --undetected modes together, you'll still need to override get_new_driver().)

    This format is similar to the English version with BaseCase inheritance, but there's a different import statement, and method names have been translated into Chinese. Here's an example of that:

    from seleniumbase.translate.chinese import \u7852\u6d4b\u8bd5\u7528\u4f8b\n\u7852\u6d4b\u8bd5\u7528\u4f8b.main(__name__, __file__)\n\n\nclass \u6211\u7684\u6d4b\u8bd5\u7c7b(\u7852\u6d4b\u8bd5\u7528\u4f8b):\n    def test_\u4f8b\u5b501(self):\n        self.\u5f00\u542f(\"https://zh.wikipedia.org/wiki/\")\n        self.\u65ad\u8a00\u6807\u9898(\"\u7ef4\u57fa\u767e\u79d1\uff0c\u81ea\u7531\u7684\u767e\u79d1\u5168\u4e66\")\n        self.\u65ad\u8a00\u5143\u7d20('a[title=\"Wikipedia:\u5173\u4e8e\"]')\n        self.\u65ad\u8a00\u6587\u672c(\"\u65b0\u95fb\u52a8\u6001\", \"span#\u65b0\u95fb\u52a8\u6001\")\n        self.\u8f93\u5165\u6587\u672c('input[name=\"search\"]', \"\u821e\u9f8d\")\n        self.\u5355\u51fb('button:contains(\"\u641c\u7d22\")')\n        self.\u65ad\u8a00\u6587\u672c(\"\u821e\u9f8d\", \"#firstHeading\")\n        self.\u65ad\u8a00\u5143\u7d20('img[src*=\"Chinese_draak.jpg\"]')\n        self.\u8f93\u5165\u6587\u672c('input[name=\"search\"]', \"\u9ebb\u5a46\u8c46\u8150\")\n        self.\u5355\u51fb('button:contains(\"\u641c\u7d22\")')\n        self.\u65ad\u8a00\u6587\u672c(\"\u9ebb\u5a46\u8c46\u8150\", \"#firstHeading\")\n        self.\u65ad\u8a00\u5143\u7d20('figure:contains(\"\u4e00\u5bb6\u4e2d\u9910\u9928\u7684\u9ebb\u5a46\u8c46\u8150\")')\n        self.\u8f93\u5165\u6587\u672c('input[name=\"search\"]', \"\u7cbe\u6b66\u82f1\u96c4\")\n        self.\u5355\u51fb('button:contains(\"\u641c\u7d22\")')\n        self.\u65ad\u8a00\u5143\u7d20('img[src*=\"Fist_of_legend.jpg\"]')\n        self.\u65ad\u8a00\u6587\u672c(\"\u674e\u8fde\u6770\", 'li a[title=\"\u674e\u8fde\u6770\"]')\n

    (See examples/translations/chinese_test_1.py for the Chinese test.)

    This format is similar to the English version with BaseCase inheritance, but there's a different import statement, and method names have been translated into Dutch. Here's an example of that:

    from seleniumbase.translate.dutch import Testgeval\nTestgeval.main(__name__, __file__)\n\n\nclass MijnTestklasse(Testgeval):\n    def test_voorbeeld_1(self):\n        self.openen(\"https://nl.wikipedia.org/wiki/Hoofdpagina\")\n        self.controleren_element('a[title*=\"hoofdpagina gaan\"]')\n        self.controleren_tekst(\"Welkom op Wikipedia\", \"td.hp-welkom\")\n        self.typ(\"#searchInput\", \"Stroopwafel\")\n        self.klik(\"#searchButton\")\n        self.controleren_tekst(\"Stroopwafel\", \"#firstHeading\")\n        self.controleren_element('img[src*=\"Stroopwafels\"]')\n        self.typ(\"#searchInput\", \"Rijksmuseum Amsterdam\")\n        self.klik(\"#searchButton\")\n        self.controleren_tekst(\"Rijksmuseum\", \"#firstHeading\")\n        self.controleren_element('img[src*=\"Rijksmuseum\"]')\n        self.terug()\n        self.controleren_url_bevat(\"Stroopwafel\")\n        self.vooruit()\n        self.controleren_url_bevat(\"Rijksmuseum\")\n

    (See examples/translations/dutch_test_1.py for the Dutch test.)

    This format is similar to the English version with BaseCase inheritance, but there's a different import statement, and method names have been translated into French. Here's an example of that:

    from seleniumbase.translate.french import CasDeBase\nCasDeBase.main(__name__, __file__)\n\n\nclass MaClasseDeTest(CasDeBase):\n    def test_exemple_1(self):\n        self.ouvrir(\"https://fr.wikipedia.org/wiki/\")\n        self.v\u00e9rifier_texte(\"Wikip\u00e9dia\")\n        self.v\u00e9rifier_\u00e9l\u00e9ment('[alt=\"Wikip\u00e9dia\"]')\n        self.js_taper(\"#searchform input\", \"Cr\u00e8me br\u00fbl\u00e9e\")\n        self.cliquer(\"#searchform button\")\n        self.v\u00e9rifier_texte(\"Cr\u00e8me br\u00fbl\u00e9e\", \"#firstHeading\")\n        self.v\u00e9rifier_\u00e9l\u00e9ment('img[alt*=\"Cr\u00e8me br\u00fbl\u00e9e\"]')\n        self.js_taper(\"#searchform input\", \"Jardin des Tuileries\")\n        self.cliquer(\"#searchform button\")\n        self.v\u00e9rifier_texte(\"Jardin des Tuileries\", \"#firstHeading\")\n        self.v\u00e9rifier_\u00e9l\u00e9ment('img[alt*=\"Jardin des Tuileries\"]')\n        self.retour()\n        self.v\u00e9rifier_url_contient(\"br\u00fbl\u00e9e\")\n        self.en_avant()\n        self.v\u00e9rifier_url_contient(\"Jardin\")\n

    (See examples/translations/french_test_1.py for the French test.)

    This format is similar to the English version with BaseCase inheritance, but there's a different import statement, and method names have been translated into Italian. Here's an example of that:

    from seleniumbase.translate.italian import CasoDiProva\nCasoDiProva.main(__name__, __file__)\n\n\nclass MiaClasseDiTest(CasoDiProva):\n    def test_esempio_1(self):\n        self.apri(\"https://it.wikipedia.org/wiki/\")\n        self.verificare_testo(\"Wikipedia\")\n        self.verificare_elemento('a[title=\"Lingua italiana\"]')\n        self.digitare(\"#searchInput\", \"Pizza\")\n        self.fare_clic(\"#searchButton\")\n        self.verificare_testo(\"Pizza\", \"#firstHeading\")\n        self.verificare_elemento('figure img[src*=\"pizza\"]')\n        self.digitare(\"#searchInput\", \"Colosseo\")\n        self.fare_clic(\"#searchButton\")\n        self.verificare_testo(\"Colosseo\", \"#firstHeading\")\n        self.verificare_elemento('figure img[src*=\"Colosseo\"]')\n        self.indietro()\n        self.verificare_url_contiene(\"Pizza\")\n        self.avanti()\n        self.verificare_url_contiene(\"Colosseo\")\n

    (See examples/translations/italian_test_1.py for the Italian test.)

    This format is similar to the English version with BaseCase inheritance, but there's a different import statement, and method names have been translated into Japanese. Here's an example of that:

    from seleniumbase.translate.japanese import \u30bb\u30ec\u30cb\u30a6\u30e0\u30c6\u30b9\u30c8\u30b1\u30fc\u30b9\n\u30bb\u30ec\u30cb\u30a6\u30e0\u30c6\u30b9\u30c8\u30b1\u30fc\u30b9.main(__name__, __file__)\n\n\nclass \u79c1\u306e\u30c6\u30b9\u30c8\u30af\u30e9\u30b9(\u30bb\u30ec\u30cb\u30a6\u30e0\u30c6\u30b9\u30c8\u30b1\u30fc\u30b9):\n    def test_\u4f8b1(self):\n        self.\u3092\u958b\u304f(\"https://ja.wikipedia.org/wiki/\")\n        self.\u30c6\u30ad\u30b9\u30c8\u3092\u78ba\u8a8d\u3059\u308b(\"\u30a6\u30a3\u30ad\u30da\u30c7\u30a3\u30a2\")\n        self.\u8981\u7d20\u3092\u78ba\u8a8d\u3059\u308b('[title*=\"\u30a6\u30a3\u30ad\u30da\u30c7\u30a3\u30a2\u3078\u3088\u3046\u3053\u305d\"]')\n        self.JS\u5165\u529b('input[name=\"search\"]', \"\u30a2\u30cb\u30e1\")\n        self.\u30af\u30ea\u30c3\u30af\u3057\u3066(\"#searchform button\")\n        self.\u30c6\u30ad\u30b9\u30c8\u3092\u78ba\u8a8d\u3059\u308b(\"\u30a2\u30cb\u30e1\", \"#firstHeading\")\n        self.JS\u5165\u529b('input[name=\"search\"]', \"\u5bff\u53f8\")\n        self.\u30af\u30ea\u30c3\u30af\u3057\u3066(\"#searchform button\")\n        self.\u30c6\u30ad\u30b9\u30c8\u3092\u78ba\u8a8d\u3059\u308b(\"\u5bff\u53f8\", \"#firstHeading\")\n        self.\u8981\u7d20\u3092\u78ba\u8a8d\u3059\u308b('img[alt=\"\u63e1\u308a\u5bff\u53f8\"]')\n        self.JS\u5165\u529b(\"#searchInput\", \"\u30ec\u30b4\u30e9\u30f3\u30c9\u30fb\u30b8\u30e3\u30d1\u30f3\")\n        self.\u30af\u30ea\u30c3\u30af\u3057\u3066(\"#searchform button\")\n        self.\u8981\u7d20\u3092\u78ba\u8a8d\u3059\u308b('img[src*=\"LEGOLAND_JAPAN\"]')\n        self.\u30ea\u30f3\u30af\u30c6\u30ad\u30b9\u30c8\u3092\u78ba\u8a8d\u3059\u308b(\"\u540d\u53e4\u5c4b\u57ce\")\n        self.\u30ea\u30f3\u30af\u30c6\u30ad\u30b9\u30c8\u3092\u30af\u30ea\u30c3\u30af\u3057\u307e\u3059(\"\u30c6\u30fc\u30de\u30d1\u30fc\u30af\")\n        self.\u30c6\u30ad\u30b9\u30c8\u3092\u78ba\u8a8d\u3059\u308b(\"\u30c6\u30fc\u30de\u30d1\u30fc\u30af\", \"#firstHeading\")\n

    (See examples/translations/japanese_test_1.py for the Japanese test.)

    This format is similar to the English version with BaseCase inheritance, but there's a different import statement, and method names have been translated into Korean. Here's an example of that:

    from seleniumbase.translate.korean import \uc140\ub808\ub284_\ud14c\uc2a4\ud2b8_\ucf00\uc774\uc2a4\n\uc140\ub808\ub284_\ud14c\uc2a4\ud2b8_\ucf00\uc774\uc2a4.main(__name__, __file__)\n\n\nclass \ud14c\uc2a4\ud2b8_\ud074\ub798\uc2a4(\uc140\ub808\ub284_\ud14c\uc2a4\ud2b8_\ucf00\uc774\uc2a4):\n    def test_\uc2e4\uc2dc\uc608_1(self):\n        self.\uc5f4\uae30(\"https://ko.wikipedia.org/wiki/\")\n        self.\ud14d\uc2a4\ud2b8_\ud655\uc778(\"\uc704\ud0a4\ubc31\uacfc\")\n        self.\uc694\uc18c_\ud655\uc778('[title=\"\uc704\ud0a4\ubc31\uacfc:\uc18c\uac1c\"]')\n        self.JS_\uc785\ub825(\"#searchform input\", \"\uae40\uce58\")\n        self.\ud074\ub9ad(\"#searchform button\")\n        self.\ud14d\uc2a4\ud2b8_\ud655\uc778(\"\uae40\uce58\", \"#firstHeading\")\n        self.\uc694\uc18c_\ud655\uc778('img[src*=\"Various_kimchi.jpg\"]')\n        self.\ub9c1\ud06c_\ud14d\uc2a4\ud2b8_\ud655\uc778(\"\ud55c\uad6d \uc694\ub9ac\")\n        self.JS_\uc785\ub825(\"#searchform input\", \"\ube44\ube54\ubc25\")\n        self.\ud074\ub9ad(\"#searchform button\")\n        self.\ud14d\uc2a4\ud2b8_\ud655\uc778(\"\ube44\ube54\ubc25\", \"#firstHeading\")\n        self.\uc694\uc18c_\ud655\uc778('img[src*=\"Dolsot-bibimbap.jpg\"]')\n        self.\ub9c1\ud06c_\ud14d\uc2a4\ud2b8\ub97c_\ud074\ub9ad\ud569\ub2c8\ub2e4(\"\ub3cc\uc1a5\ube44\ube54\ubc25\")\n        self.\ud14d\uc2a4\ud2b8_\ud655\uc778(\"\ub3cc\uc1a5\ube44\ube54\ubc25\", \"#firstHeading\")\n

    (See examples/translations/korean_test_1.py for the Korean test.)

    This format is similar to the English version with BaseCase inheritance, but there's a different import statement, and method names have been translated into Portuguese. Here's an example of that:

    from seleniumbase.translate.portuguese import CasoDeTeste\nCasoDeTeste.main(__name__, __file__)\n\n\nclass MinhaClasseDeTeste(CasoDeTeste):\n    def test_exemplo_1(self):\n        self.abrir(\"https://pt.wikipedia.org/wiki/\")\n        self.verificar_texto(\"Wikip\u00e9dia\")\n        self.verificar_elemento('[title=\"L\u00edngua portuguesa\"]')\n        self.digitar(\"#searchform input\", \"Jo\u00e3o Pessoa\")\n        self.clique(\"#searchform button\")\n        self.verificar_texto(\"Jo\u00e3o Pessoa\", \"#firstHeading\")\n        self.verificar_elemento('img[alt*=\"Jo\u00e3o Pessoa\"]')\n        self.digitar(\"#searchform input\", \"Florian\u00f3polis\")\n        self.clique(\"#searchform button\")\n        self.verificar_texto(\"Florian\u00f3polis\", \"h1#firstHeading\")\n        self.verificar_elemento('td:contains(\"Avenida Beira-Mar\")')\n        self.voltar()\n        self.verificar_url_cont\u00e9m(\"Jo\u00e3o_Pessoa\")\n        self.atualizar_a_p\u00e1gina()\n        self.js_digitar(\"#searchform input\", \"Teatro Amazonas\")\n        self.clique(\"#searchform button\")\n        self.verificar_texto(\"Teatro Amazonas\", \"#firstHeading\")\n        self.verificar_texto_do_link(\"Festival Amazonas de \u00d3pera\")\n

    (See examples/translations/portuguese_test_1.py for the Portuguese test.)

    This format is similar to the English version with BaseCase inheritance, but there's a different import statement, and method names have been translated into Russian. Here's an example of that:

    from seleniumbase.translate.russian import \u0422\u0435\u0441\u0442\u041d\u0430\u0421\u0435\u043b\u0435\u043d\n\u0422\u0435\u0441\u0442\u041d\u0430\u0421\u0435\u043b\u0435\u043d.main(__name__, __file__)\n\n\nclass \u041c\u043e\u0439\u0422\u0435\u0441\u0442\u043e\u0432\u044b\u0439\u041a\u043b\u0430\u0441\u0441(\u0422\u0435\u0441\u0442\u041d\u0430\u0421\u0435\u043b\u0435\u043d):\n    def test_\u043f\u0440\u0438\u043c\u0435\u0440_1(self):\n        self.\u043e\u0442\u043a\u0440\u044b\u0442\u044c(\"https://ru.wikipedia.org/wiki/\")\n        self.\u043f\u043e\u0434\u0442\u0432\u0435\u0440\u0434\u0438\u0442\u044c_\u044d\u043b\u0435\u043c\u0435\u043d\u0442('[title=\"\u0420\u0443\u0441\u0441\u043a\u0438\u0439 \u044f\u0437\u044b\u043a\"]')\n        self.\u043f\u043e\u0434\u0442\u0432\u0435\u0440\u0434\u0438\u0442\u044c_\u0442\u0435\u043a\u0441\u0442(\"\u0412\u0438\u043a\u0438\u043f\u0435\u0434\u0438\u044f\", \"h2.main-wikimedia-header\")\n        self.\u0432\u0432\u0435\u0434\u0438\u0442\u0435(\"#searchInput\", \"\u041c\u0413\u0423\")\n        self.\u043d\u0430\u0436\u043c\u0438\u0442\u0435(\"#searchButton\")\n        self.\u043f\u043e\u0434\u0442\u0432\u0435\u0440\u0434\u0438\u0442\u044c_\u0442\u0435\u043a\u0441\u0442(\"\u0443\u043d\u0438\u0432\u0435\u0440\u0441\u0438\u0442\u0435\u0442\", \"#firstHeading\")\n        self.\u043f\u043e\u0434\u0442\u0432\u0435\u0440\u0434\u0438\u0442\u044c_\u044d\u043b\u0435\u043c\u0435\u043d\u0442('img[alt*=\"\u0413\u043b\u0430\u0432\u043d\u043e\u0435 \u0437\u0434\u0430\u043d\u0438\u0435 \u041c\u0413\u0423\"]')\n        self.\u0432\u0432\u0435\u0434\u0438\u0442\u0435(\"#searchInput\", \"\u043f\u0440\u0438\u043a\u043b\u044e\u0447\u0435\u043d\u0438\u044f \u0428\u0443\u0440\u0438\u043a\u0430\")\n        self.\u043d\u0430\u0436\u043c\u0438\u0442\u0435(\"#searchButton\")\n        self.\u043f\u043e\u0434\u0442\u0432\u0435\u0440\u0434\u0438\u0442\u044c_\u0442\u0435\u043a\u0441\u0442(\"\u041e\u043f\u0435\u0440\u0430\u0446\u0438\u044f \u00ab\u042b\u00bb \u0438 \u0434\u0440\u0443\u0433\u0438\u0435 \u043f\u0440\u0438\u043a\u043b\u044e\u0447\u0435\u043d\u0438\u044f \u0428\u0443\u0440\u0438\u043a\u0430\")\n        self.\u043f\u043e\u0434\u0442\u0432\u0435\u0440\u0434\u0438\u0442\u044c_\u044d\u043b\u0435\u043c\u0435\u043d\u0442('img[alt=\"\u041f\u043e\u0441\u0442\u0435\u0440 \u0444\u0438\u043b\u044c\u043c\u0430\"]')\n        self.\u043d\u0430\u0437\u0430\u0434()\n        self.\u043f\u043e\u0434\u0442\u0432\u0435\u0440\u0434\u0438\u0442\u044c_URL_\u0441\u043e\u0434\u0435\u0440\u0436\u0438\u0442(\"\u0443\u043d\u0438\u0432\u0435\u0440\u0441\u0438\u0442\u0435\u0442\")\n        self.\u0432\u043f\u0435\u0440\u0435\u0434()\n        self.\u043f\u043e\u0434\u0442\u0432\u0435\u0440\u0434\u0438\u0442\u044c_URL_\u0441\u043e\u0434\u0435\u0440\u0436\u0438\u0442(\"\u0428\u0443\u0440\u0438\u043a\u0430\")\n

    (See examples/translations/russian_test_1.py for the Russian test.)

    This format is similar to the English version with BaseCase inheritance, but there's a different import statement, and method names have been translated into Spanish. Here's an example of that:

    from seleniumbase.translate.spanish import CasoDePrueba\nCasoDePrueba.main(__name__, __file__)\n\n\nclass MiClaseDePrueba(CasoDePrueba):\n    def test_ejemplo_1(self):\n        self.abrir(\"https://es.wikipedia.org/wiki/\")\n        self.verificar_texto(\"Wikipedia\")\n        self.verificar_elemento('[title=\"Wikipedia:Bienvenidos\"]')\n        self.escriba('[name=\"search\"]', \"Parque de Atracciones Tibidabo\")\n        self.haga_clic('button:contains(\"Buscar\")')\n        self.verificar_texto(\"Tibidabo\", \"#firstHeading\")\n        self.verificar_elemento('img[src*=\"Tibidabo\"]')\n        self.escriba('input[name=\"search\"]', \"Palma de Mallorca\")\n        self.haga_clic('button:contains(\"Buscar\")')\n        self.verificar_texto(\"Palma de Mallorca\", \"#firstHeading\")\n        self.verificar_elemento('img[src*=\"Palma\"]')\n        self.volver()\n        self.verificar_url_contiene(\"Tibidabo\")\n        self.adelante()\n        self.verificar_url_contiene(\"Mallorca\")\n

    (See examples/translations/spanish_test_1.py for the Spanish test.)

    With Behave's BDD Gherkin format, you can use natural language to write tests that work with SeleniumBase methods. Behave tests are run by calling behave on the command-line. This requires some special files in a specific directory structure. Here's an example of that structure:

    features/\n\u251c\u2500\u2500 __init__.py\n\u251c\u2500\u2500 behave.ini\n\u251c\u2500\u2500 environment.py\n\u251c\u2500\u2500 feature_file.feature\n\u2514\u2500\u2500 steps/\n    \u251c\u2500\u2500 __init__.py\n    \u251c\u2500\u2500 imported.py\n    \u2514\u2500\u2500 step_file.py\n

    A *.feature file might look like this:

    Feature: SeleniumBase scenarios for the RealWorld App\n\nScenario: Verify RealWorld App (log in / sign out)\n    Given Open \"seleniumbase.io/realworld/login\"\nAnd Clear Session Storage\nWhen Type \"demo_user\" into \"#username\"\nAnd Type \"secret_pass\" into \"#password\"\nAnd Do MFA \"GAXG2MTEOR3DMMDG\" into \"#totpcode\"\nThen Assert exact text \"Welcome!\" in \"h1\"\nAnd Highlight \"img#image1\"\nAnd Click 'a:contains(\"This Page\")'\nAnd Save screenshot to logs\nWhen Click link \"Sign out\"\nThen Assert element 'a:contains(\"Sign in\")'\nAnd Assert text \"You have been signed out!\"\n

    (From examples/behave_bdd/features/realworld.feature)

    You'll need the environment.py file for tests to work. Here it is:

    from seleniumbase import BaseCase\nfrom seleniumbase.behave import behave_sb\nbehave_sb.set_base_class(BaseCase)  # Accepts a BaseCase subclass\nfrom seleniumbase.behave.behave_sb import before_all  # noqa\nfrom seleniumbase.behave.behave_sb import before_feature  # noqa\nfrom seleniumbase.behave.behave_sb import before_scenario  # noqa\nfrom seleniumbase.behave.behave_sb import before_step  # noqa\nfrom seleniumbase.behave.behave_sb import after_step  # noqa\nfrom seleniumbase.behave.behave_sb import after_scenario  # noqa\nfrom seleniumbase.behave.behave_sb import after_feature  # noqa\nfrom seleniumbase.behave.behave_sb import after_all  # noqa\n

    (From examples/behave_bdd/features/environment.py)

    Inside that file, you can use BaseCase (or a subclass) for the inherited class.

    For your behave tests to have access to SeleniumBase Behave steps, you can create an imported.py file with the following line:

    from seleniumbase.behave import steps  # noqa\n

    That will allow you to use lines like this in your *.feature files:

    Feature: SeleniumBase scenarios for the RealWorld App\n\nScenario: Verify RealWorld App (log in / sign out)\n    Given Open \"seleniumbase.io/realworld/login\"\nAnd Clear Session Storage\nWhen Type \"demo_user\" into \"#username\"\nAnd Type \"secret_pass\" into \"#password\"\nAnd Do MFA \"GAXG2MTEOR3DMMDG\" into \"#totpcode\"\nThen Assert exact text \"Welcome!\" in \"h1\"\nAnd Highlight \"img#image1\"\nAnd Click 'a:contains(\"This Page\")'\nAnd Save screenshot to logs\n

    You can also create your own step files (Eg. step_file.py):

    from behave import step\n\n@step(\"Open the Swag Labs Login Page\")\ndef go_to_swag_labs(context):\n    sb = context.sb\n    sb.open(\"https://www.saucedemo.com\")\n    sb.clear_local_storage()\n\n@step(\"Login to Swag Labs with {user}\")\ndef login_to_swag_labs(context, user):\n    sb = context.sb\n    sb.type(\"#user-name\", user)\n    sb.type(\"#password\", \"secret_sauce\\n\")\n

    (For more information, see the SeleniumBase Behave BDD ReadMe.)

    This format provides a pure Python way of using SeleniumBase without a test runner. Options can be passed via method instantiation or from the command-line. When setting the test option to True (or calling python --test), then standard test logging will occur, such as screenshots and reports for failing tests. All the usual SeleniumBase options are available, such as customizing the browser settings, etc. Here are some examples:

    from seleniumbase import SB\n\nwith SB() as sb:  # By default, browser=\"chrome\" if not set.\n    sb.open(\"https://seleniumbase.github.io/realworld/login\")\n    sb.type(\"#username\", \"demo_user\")\n    sb.type(\"#password\", \"secret_pass\")\n    sb.enter_mfa_code(\"#totpcode\", \"GAXG2MTEOR3DMMDG\")  # 6-digit\n    sb.assert_text(\"Welcome!\", \"h1\")\n    sb.highlight(\"img#image1\")  # A fancier assert_element() call\n    sb.click('a:contains(\"This Page\")')  # Use :contains() on any tag\n    sb.click_link(\"Sign out\")  # Link must be \"a\" tag. Not \"button\".\n    sb.assert_element('a:contains(\"Sign in\")')\n    sb.assert_exact_text(\"You have been signed out!\", \"#top_message\")\n

    (See examples/raw_sb.py for the test.)

    Here's another example, which uses test mode:

    from seleniumbase import SB\n\nwith SB(test=True) as sb:\n    sb.open(\"https://google.com/ncr\")\n    sb.type('[name=\"q\"]', \"SeleniumBase on GitHub\\n\")\n    sb.click('a[href*=\"github.com/seleniumbase\"]')\n    sb.highlight(\"div.Layout-main\")\n    sb.highlight(\"div.Layout-sidebar\")\n    sb.sleep(0.5)\n\nwith SB(test=True, rtf=True, demo=True) as sb:\n    sb.open(\"seleniumbase.github.io/demo_page\")\n    sb.type(\"#myTextInput\", \"This is Automated\")\n    sb.assert_text(\"This is Automated\", \"#myTextInput\")\n    sb.assert_text(\"This Text is Green\", \"#pText\")\n    sb.click('button:contains(\"Click Me\")')\n    sb.assert_text(\"This Text is Purple\", \"#pText\")\n    sb.click(\"#checkBox1\")\n    sb.assert_element_not_visible(\"div#drop2 img#logo\")\n    sb.drag_and_drop(\"img#logo\", \"div#drop2\")\n    sb.assert_element(\"div#drop2 img#logo\")\n

    (See examples/raw_test_scripts.py for the test.)

    This pure Python format gives you a raw webdriver instance in a with block. The SeleniumBase Driver Manager will automatically make sure that your driver is compatible with your browser version. It gives you full access to customize driver options via method args or via the command-line. The driver will automatically call quit() after the code leaves the with block. Here are some examples:

    \"\"\"This script can be run with pure \"python\". (pytest not needed).\"\"\"\nfrom seleniumbase import js_utils\nfrom seleniumbase import page_actions\nfrom seleniumbase import DriverContext\n\n# Driver Context Manager - (By default, browser=\"chrome\". Lots of options)\nwith DriverContext() as driver:\n    driver.get(\"https://seleniumbase.github.io/\")\n    js_utils.highlight_with_js(driver, 'img[alt=\"SeleniumBase\"]', loops=6)\n\nwith DriverContext(browser=\"chrome\", incognito=True) as driver:\n    driver.get(\"https://seleniumbase.io/apps/calculator\")\n    page_actions.wait_for_element(driver, '[id=\"4\"]').click()\n    page_actions.wait_for_element(driver, '[id=\"2\"]').click()\n    page_actions.wait_for_text(driver, \"42\", \"#output\")\n    js_utils.highlight_with_js(driver, \"#output\", loops=6)\n\nwith DriverContext() as driver:\n    driver.get(\"https://seleniumbase.github.io/demo_page\")\n    js_utils.highlight_with_js(driver, \"h2\", loops=5)\n    by_css = \"css selector\"\n    driver.find_element(by_css, \"#myTextInput\").send_keys(\"Automation\")\n    driver.find_element(by_css, \"#checkBox1\").click()\n    js_utils.highlight_with_js(driver, \"img\", loops=5)\n

    (See examples/raw_driver_context.py for an example.)

    Another way of running Selenium tests with pure python (as opposed to using pytest or pynose) is by using this format, which bypasses BaseCase methods while still giving you a flexible driver with a manager. SeleniumBase includes helper files such as page_actions.py, which may help you get around some of the limitations of bypassing BaseCase. Here's an example:

    \"\"\"This script can be run with pure \"python\". (pytest not needed).\"\"\"\nfrom seleniumbase import Driver\nfrom seleniumbase import js_utils\nfrom seleniumbase import page_actions\n\n# Example with options. (Also accepts command-line options.)\ndriver = Driver(browser=\"chrome\", headless=False)\ntry:\n    driver.get(\"https://seleniumbase.io/apps/calculator\")\n    page_actions.wait_for_element(driver, '[id=\"4\"]').click()\n    page_actions.wait_for_element(driver, '[id=\"2\"]').click()\n    page_actions.wait_for_text(driver, \"42\", \"#output\")\n    js_utils.highlight_with_js(driver, \"#output\", loops=6)\nfinally:\n    driver.quit()\n\n# Example 2 using default args or command-line options\ndriver = Driver()\ntry:\n    driver.get(\"https://seleniumbase.github.io/demo_page\")\n    js_utils.highlight_with_js(driver, \"h2\", loops=5)\n    by_css = \"css selector\"\n    driver.find_element(by_css, \"#myTextInput\").send_keys(\"Automation\")\n    driver.find_element(by_css, \"#checkBox1\").click()\n    js_utils.highlight_with_js(driver, \"img\", loops=5)\nfinally:\n    driver.quit()\n

    (From examples/raw_browser_launcher.py)

    The above format can be used as a drop-in replacement for virtually every Python/selenium framework, as it uses the raw driver instance for handling commands. The Driver() method simplifies the work of managing drivers with optimal settings, and it can be configured via multiple method args. The Driver also accepts command-line options (such as python --headless) so that you don't need to modify your tests directly to use different settings. These command-line options only take effect if the associated method args remain unset (or set to None) for the specified options.

    "}, {"location": "help_docs/thank_you/", "title": "\ud83d\ude4f Thank You", "text": ""}, {"location": "help_docs/thank_you/#thank-you-for-flying-with-seleniumbase", "title": "Thank you for flying with SeleniumBase! \ud83e\udd85", "text": "

    SeleniumBase Playlist on YouTube:

    SeleniumBase GitHub Repo Link:

    SeleniumBase Gitter Chat Link:

    Other Social Media Links:

    "}, {"location": "help_docs/translations/", "title": "\ud83c\udf0f Translations", "text": ""}, {"location": "help_docs/translations/#translated-tests", "title": "\ud83c\udf0f Translated Tests \ud83c\ude3a Translation API \ud83c\ude3a", "text": "

    SeleniumBase supports the following 10 languages: English, Chinese, Dutch, French, Italian, Japanese, Korean, Portuguese, Russian, and Spanish. (Examples can be found in SeleniumBase/examples/translations)

    Multi-language tests run with pytest like other tests. Test methods have a one-to-one mapping to supported languages. Here's an example of a translated test:

    # Chinese Translation\nfrom seleniumbase.translate.chinese import \u7852\u6d4b\u8bd5\u7528\u4f8b\n\nclass \u6211\u7684\u6d4b\u8bd5\u7c7b(\u7852\u6d4b\u8bd5\u7528\u4f8b):\n    def test_\u4f8b\u5b501(self):\n        self.\u5f00\u542f(\"https://zh.wikipedia.org/wiki/\")\n        self.\u65ad\u8a00\u6807\u9898(\"\u7ef4\u57fa\u767e\u79d1\uff0c\u81ea\u7531\u7684\u767e\u79d1\u5168\u4e66\")\n        self.\u65ad\u8a00\u5143\u7d20('a[title=\"Wikipedia:\u5173\u4e8e\"]')\n        self.\u65ad\u8a00\u6587\u672c(\"\u65b0\u95fb\u52a8\u6001\", \"span#\u65b0\u95fb\u52a8\u6001\")\n        self.\u8f93\u5165\u6587\u672c('input[name=\"search\"]', \"\u821e\u9f8d\")\n        self.\u5355\u51fb('button:contains(\"\u641c\u7d22\")')\n        self.\u65ad\u8a00\u6587\u672c(\"\u821e\u9f8d\", \"#firstHeading\")\n

    Here's another example:

    # Japanese Translation\nfrom seleniumbase.translate.japanese import \u30bb\u30ec\u30cb\u30a6\u30e0\u30c6\u30b9\u30c8\u30b1\u30fc\u30b9\n\nclass \u79c1\u306e\u30c6\u30b9\u30c8\u30af\u30e9\u30b9(\u30bb\u30ec\u30cb\u30a6\u30e0\u30c6\u30b9\u30c8\u30b1\u30fc\u30b9):\n    def test_\u4f8b1(self):\n        self.\u3092\u958b\u304f(\"https://ja.wikipedia.org/wiki/\")\n        self.\u30c6\u30ad\u30b9\u30c8\u3092\u78ba\u8a8d\u3059\u308b(\"\u30a6\u30a3\u30ad\u30da\u30c7\u30a3\u30a2\")\n        self.\u8981\u7d20\u3092\u78ba\u8a8d\u3059\u308b('[title*=\"\u30a6\u30a3\u30ad\u30da\u30c7\u30a3\u30a2\u3078\u3088\u3046\u3053\u305d\"]')\n        self.JS\u5165\u529b('input[name=\"search\"]', \"\u30a2\u30cb\u30e1\")\n        self.\u30af\u30ea\u30c3\u30af\u3057\u3066(\"#searchform button\")\n        self.\u30c6\u30ad\u30b9\u30c8\u3092\u78ba\u8a8d\u3059\u308b(\"\u30a2\u30cb\u30e1\", \"#firstHeading\")\n        self.JS\u5165\u529b('input[name=\"search\"]', \"\u5bff\u53f8\")\n

    You can use SeleniumBase to selectively translate the method names of any test from one language to another with the console scripts interface. Additionally, the import line at the top of the Python file will change to import the new BaseCase. Example: BaseCase becomes CasoDeTeste when a test is translated into Portuguese.

    seleniumbase translate\n
    * Usage:\nseleniumbase translate [SB_FILE.py] [LANGUAGE] [ACTION]\n\n* Languages:\n``--en`` / ``--English``  |  ``--zh`` / ``--Chinese``\n``--nl`` / ``--Dutch``    |  ``--fr`` / ``--French``\n``--it`` / ``--Italian``  |  ``--ja`` / ``--Japanese``\n``--ko`` / ``--Korean``   |  ``--pt`` / ``--Portuguese``\n``--ru`` / ``--Russian``  |  ``--es`` / ``--Spanish``\n\n* Actions:\n``-p`` / ``--print``  (Print translation output to the screen)\n``-o`` / ``--overwrite``  (Overwrite the file being translated)\n``-c`` / ``--copy``  (Copy the translation to a new ``.py`` file)\n\n* Options:\n``-n``  (include line Numbers when using the Print action)\n\n* Examples:\nTranslate test_1.py into Chinese and only print the output:\n>>> seleniumbase translate test_1.py --zh  -p\nTranslate test_2.py into Portuguese and overwrite the file:\n>>> seleniumbase translate test_2.py --pt  -o\nTranslate test_3.py into Dutch and make a copy of the file:\n>>> seleniumbase translate test_3.py --nl  -c\n\n* Output:\nTranslates a SeleniumBase Python file into the language\nspecified. Method calls and ``import`` lines get swapped.\nBoth a language and an action must be specified.\nThe ``-p`` action can be paired with one other action.\nWhen running with ``-c`` (or ``--copy``) the new file name\nwill be the original name appended with an underscore\nplus the 2-letter language code of the new language.\n(Example: Translating ``test_1.py`` into Japanese with\n``-c`` will create a new file called ``test_1_ja.py``.)\n
    "}, {"location": "help_docs/useful_grep_commands/", "title": "\ud83d\udcdc Useful grep commands", "text": ""}, {"location": "help_docs/useful_grep_commands/#useful-grep-commands", "title": "Useful grep commands", "text": "

    There are several useful grep commands for helping you find and/or replace text in multiple files. Examples:

    "}, {"location": "help_docs/useful_grep_commands/#list-all-files-containing-selfget_new_driver-ignoring-pyc-files-from-the-current-directory", "title": "List all files containing self.get_new_driver(, ignoring \".pyc\" files, from the current directory", "text": "

    grep -rl \"self.get_new_driver(\" * --exclude=\\*.pyc OR grep -rl * -e \"self.get_new_driver(\" --exclude=\\*.pyc

    To only search .py files, use --include=\\*.py:

    grep -rl \"self.get_new_driver(\" * --include=\\*.py

    "}, {"location": "help_docs/useful_grep_commands/#replace-all-occurrences-of-foo_abc-with-bar_xyz-on-linux-for-python-files-from-the-current-directory", "title": "Replace all occurrences of \"foo_abc\" with \"bar_xyz\" on Linux, for Python files from the current directory", "text": "

    sed -i 's/foo_abc/bar_xyz/g' *.py

    "}, {"location": "help_docs/useful_grep_commands/#replace-all-occurrences-of-foo_abc-with-bar_xyz-on-macos-for-python-files-from-the-current-directory", "title": "Replace all occurrences of \"foo_abc\" with \"bar_xyz\" on macOS, for Python files from the current directory", "text": "

    sed -i '' 's/foo_abc/bar_xyz/g' *.py

    "}, {"location": "help_docs/useful_grep_commands/#find-all-chromedriver-processes-this-combines-ps-with-grep", "title": "Find all chromedriver processes (this combines ps with grep):", "text": "

    ps -ef |grep chromedriver

    "}, {"location": "help_docs/useful_grep_commands/#references", "title": "References", "text": ""}, {"location": "help_docs/using_safari_driver/", "title": "\ud83e\udded Using Safari Driver", "text": ""}, {"location": "help_docs/using_safari_driver/#using-safaris-webdriver-for-running-browser-tests-on-macos", "title": "Using Safari's WebDriver for running browser tests on macOS", "text": "

    (NOTE: Safari's WebDriver requires macOS 10.13 \"High Sierra\" or later.)

    You can find the official Apple documentation regarding \"Testing with WebDriver in Safari\" on the following page: https://developer.apple.com/documentation/webkit/testing_with_webdriver_in_safari

    Run safaridriver --enable once in a terminal to enable Safari's WebDriver. (If you\u2019re upgrading from a previous macOS release, you may need to prefix the command with sudo.)

    Now you can use --browser=safari to run your SeleniumBase tests on Safari.

    "}, {"location": "help_docs/virtualenv_instructions/", "title": "\u2699\ufe0f Virtualenv Instructions", "text": ""}, {"location": "help_docs/virtualenv_instructions/#virtual-environment-tutorial", "title": "Virtual Environment Tutorial", "text": "

    There are multiple ways of creating a Python virtual environment. This tutorial covers two of those:

    venv creates virtual environments in the location where run (generally with Python projects).

    mkvirtualenv creates virtual environments in one place (generally in your home directory).

    (The Python Software Foundation recommends venv for creating virtual environments.)

    Option 1: Using \"venv\"

    macOS/Linux terminal (python3 -m venv ENV)

    python3 -m venv sbase_env\nsource sbase_env/bin/activate\n

    Windows CMD prompt (py -m venv ENV):

    py -m venv sbase_env\ncall sbase_env\\\\Scripts\\\\activate\n

    To exit a virtual env, type deactivate.

    Option 2: Using virtualenvwrapper

    macOS/Linux terminal:

    python3 -m pip install virtualenvwrapper --force-reinstall\nexport WORKON_HOME=$HOME/.virtualenvs\nsource `which virtualenvwrapper.sh`\n

    (Shortcut: Run source virtualenv_install.sh from the top-level SeleniumBase folder to perform the above steps.)

    (If you add source `which virtualenvwrapper.sh` to your local bash file (~/.bash_profile on macOS, or ~/.bashrc on Linux), virtualenvwrapper commands such as mkvirtualenv will be available whenever you open a new command prompt.)

    Windows CMD prompt:

    py -m pip install virtualenvwrapper-win --force-reinstall --user\n

    (Shortcut: Run win_virtualenv.bat from the top-level SeleniumBase folder to perform the above step.)

    Create a virtual environment:
    mkvirtualenv sbase_env\n

    (If you have multiple versions of Python installed on your machine, and you want your virtual environment to use a specific Python version, add --python=PATH_TO_PYTHON_EXE to your mkvirtualenv command with the Python executable to use.)

    virtualenvwrapper commands:

    Creating a virtual environment:

    mkvirtualenv sbase_env\n

    Leaving your virtual environment:

    deactivate\n

    Returning to a virtual environment:

    workon sbase_env\n

    Listing all virtual environments:

    workon\n

    Deleting a virtual environment:

    rmvirtualenv sbase_env\n

    If the python and python3 versions don't match (while in a virtualenv on macOS or Linux), the following command will sync the versions:

    alias python=python3\n

    (To remove an alias, use: unalias NAME)

    To verify the python version, use:

    python --version\n

    To see the PATH of your python (macOS/Linux), use:

    which python\n

    python-guide.org/en/latest/dev/virtualenvs has more information about Python virtual environments. For specific details about VirtualEnv and VirtualEnvWrapper, see http://virtualenv.readthedocs.org/en/latest/ and http://virtualenvwrapper.readthedocs.org/en/latest/.

    "}, {"location": "integrations/azure/azure_pipelines/ReadMe/", "title": "\ud83e\udd16 Azure Pipelines", "text": ""}, {"location": "integrations/azure/azure_pipelines/ReadMe/#running-browser-based-test-automation-with-azure-pipelines-by-using-seleniumbase", "title": "Running browser-based test automation with Azure Pipelines by using SeleniumBase", "text": ""}, {"location": "integrations/azure/azure_pipelines/ReadMe/#step-0-fork-the-seleniumbase-repo-on-github-to-get-started-quickly", "title": "Step 0. Fork the SeleniumBase repo on GitHub to get started quickly.", "text": ""}, {"location": "integrations/azure/azure_pipelines/ReadMe/#step-1-get-azure-pipelines-from-the-github-marketplace", "title": "Step 1. Get Azure Pipelines from the GitHub Marketplace", "text": ""}, {"location": "integrations/azure/azure_pipelines/ReadMe/#navigate-to-httpsgithubcommarketplaceazure-pipelines", "title": "Navigate to https://github.com/marketplace/azure-pipelines", "text": ""}, {"location": "integrations/azure/azure_pipelines/ReadMe/#step-2-go-to-microsoft-azure-devops-to-set-up-your-environment", "title": "Step 2. Go to Microsoft Azure DevOps to set up your environment", "text": ""}, {"location": "integrations/azure/azure_pipelines/ReadMe/#select-start-free-with-github", "title": "Select \"Start free with GitHub >\":", "text": ""}, {"location": "integrations/azure/azure_pipelines/ReadMe/#give-your-new-project-a-name-and-set-visibility-to-public-for-your-seleniumbase-fork", "title": "Give your new project a name and set visibility to public (for your SeleniumBase fork):", "text": ""}, {"location": "integrations/azure/azure_pipelines/ReadMe/#select-that-your-code-is-hosted-on-github", "title": "Select that your code is hosted on GitHub", "text": ""}, {"location": "integrations/azure/azure_pipelines/ReadMe/#select-your-fork-of-seleniumbase-as-your-repository", "title": "Select your fork of SeleniumBase as your repository", "text": ""}, {"location": "integrations/azure/azure_pipelines/ReadMe/#copy-the-azure-pipelinesyml-file-from-seleniumbase-into-the-azure-pipelinesyml-box-to-create-your-new-pipeline", "title": "Copy the azure-pipelines.yml file from SeleniumBase into the azure-pipelines.yml box to create your new pipeline", "text": ""}, {"location": "integrations/azure/azure_pipelines/ReadMe/#when-youre-done-copying-click-run", "title": "When you're done copying, click \"Run\".", "text": ""}, {"location": "integrations/azure/azure_pipelines/ReadMe/#step-3-congratulations-your-browser-tests-are-now-running", "title": "Step 3. Congratulations! Your browser tests are now running!", "text": "

    https://dev.azure.com/seleniumbase/seleniumbase/_build/results?buildId=234

    "}, {"location": "integrations/azure/azure_pipelines/ReadMe/#every-time-you-create-a-pull-request-now-azure-pipelines-will-run-your-tests-automatically", "title": "Every time you create a pull request now, Azure Pipelines will run your tests automatically.", "text": "

    To learn more, study SeleniumBase and see how the azure-pipelines.yml file works.

    "}, {"location": "integrations/azure/jenkins/ReadMe/", "title": "\ud83e\udd16 Jenkins on Azure", "text": ""}, {"location": "integrations/azure/jenkins/ReadMe/#building-a-browser-based-test-automation-server-with-jenkins-on-azure-by-using-seleniumbase", "title": "Building a browser-based test automation server with Jenkins on Azure by using SeleniumBase", "text": "

    (2022 NOTE: Steps from this 2019 tutorial from Boston Code Camp are now out-of-date. For installing Jenkins from the Azure Marketplace, you can try using Bitnami Jenkins. Or, for the newer official Microsoft tutorial, see Get Started: Install Jenkins on an Azure Linux VM, and then continue with Step 4 below to resume SeleniumBase setup after you've created your Jenkins instance.)

    "}, {"location": "integrations/azure/jenkins/ReadMe/#step-0-fork-the-seleniumbase-repo-on-github-to-get-started-quickly", "title": "Step 0. Fork the SeleniumBase repo on GitHub to get started quickly.", "text": ""}, {"location": "integrations/azure/jenkins/ReadMe/#step-1-find-jenkins-in-the-azure-marketplace", "title": "Step 1. Find Jenkins in the Azure Marketplace", "text": ""}, {"location": "integrations/azure/jenkins/ReadMe/#search-for-jenkins-in-the-azure-marketplace-and-select-the-jenkins-publisher-microsoft-result-to-get-to-the-jenkins-start-page", "title": "Search for \"Jenkins\" in the Azure Marketplace and select the Jenkins (Publisher: Microsoft) result to get to the Jenkins Start page.", "text": ""}, {"location": "integrations/azure/jenkins/ReadMe/#step-2-launch-a-jenkins-instance", "title": "Step 2. Launch a Jenkins instance", "text": ""}, {"location": "integrations/azure/jenkins/ReadMe/#click-create-and-follow-the-steps", "title": "Click \"Create\" and follow the steps...", "text": ""}, {"location": "integrations/azure/jenkins/ReadMe/#continue-to-additional-settings-when-youre-done-with-basics", "title": "Continue to \"Additional Settings\" when you're done with \"Basics\".", "text": ""}, {"location": "integrations/azure/jenkins/ReadMe/#on-the-additional-settings-section-set-the-size-to-b2s", "title": "On the \"Additional Settings\" section, set the Size to \"B2s\":", "text": ""}, {"location": "integrations/azure/jenkins/ReadMe/#once-youve-reached-step-5-click-create-to-complete-the-setup", "title": "Once you've reached Step 5, click \"Create\" to complete the setup.", "text": ""}, {"location": "integrations/azure/jenkins/ReadMe/#step-3-inspect-your-new-jenkins-instance-to-ssh-into-the-new-machine", "title": "Step 3. Inspect your new Jenkins instance to SSH into the new machine", "text": ""}, {"location": "integrations/azure/jenkins/ReadMe/#once-your-new-jenkins-instance-has-finished-launching-you-should-be-able-to-see-the-main-page", "title": "Once your new Jenkins instance has finished launching, you should be able to see the main page", "text": ""}, {"location": "integrations/azure/jenkins/ReadMe/#on-the-main-page-you-should-be-able-to-find-the-public-ip-address", "title": "On the main page, you should be able to find the Public IP Address.", "text": "
    ssh USERNAME@IP_ADDRESS\n
    "}, {"location": "integrations/azure/jenkins/ReadMe/#step-4-clone-the-seleniumbase-repository-from-the-root-directory", "title": "Step 4. Clone the SeleniumBase repository from the root (\"/\") directory.", "text": "
    cd /\nsudo git clone https://github.com/seleniumbase/SeleniumBase.git\n
    "}, {"location": "integrations/azure/jenkins/ReadMe/#step-5-enter-the-linux-folder", "title": "Step 5. Enter the \"linux\" folder", "text": "
    cd SeleniumBase/integrations/linux/\n
    "}, {"location": "integrations/azure/jenkins/ReadMe/#step-6-give-the-jenkins-user-sudo-access-see-jenkins_permissionssh-for-details", "title": "Step 6. Give the \"jenkins\" user sudo access (See jenkins_permissions.sh for details)", "text": "
    ./jenkins_permissions.sh\n
    "}, {"location": "integrations/azure/jenkins/ReadMe/#step-7-become-the-jenkins-user-and-enter-a-bash-shell", "title": "Step 7. Become the \"jenkins\" user and enter a \"bash\" shell", "text": "
    sudo su jenkins\nbash\n
    "}, {"location": "integrations/azure/jenkins/ReadMe/#step-8-install-dependencies-see-linuxfilesh-for-details", "title": "Step 8. Install dependencies (See Linuxfile.sh for details)", "text": "
    ./Linuxfile.sh\n
    "}, {"location": "integrations/azure/jenkins/ReadMe/#step-9-start-up-the-headless-browser-display-mechanism-xvfb-see-xvfb_launchersh-for-details", "title": "Step 9. Start up the headless browser display mechanism: Xvfb (See Xvfb_launcher.sh for details)", "text": "
    ./Xvfb_launcher.sh\n
    "}, {"location": "integrations/azure/jenkins/ReadMe/#step-10-go-to-the-seleniumbase-directory", "title": "Step 10. Go to the SeleniumBase directory", "text": "
    cd /SeleniumBase\n
    "}, {"location": "integrations/azure/jenkins/ReadMe/#step-11-install-the-requirements-for-seleniumbase", "title": "Step 11. Install the requirements for SeleniumBase", "text": "
    sudo pip install -r requirements.txt --upgrade\n
    "}, {"location": "integrations/azure/jenkins/ReadMe/#step-12-install-seleniumbase-make-sure-you-already-installed-the-requirements-above", "title": "Step 12. Install SeleniumBase (Make sure you already installed the requirements above)", "text": "
    sudo python setup.py develop\n
    "}, {"location": "integrations/azure/jenkins/ReadMe/#step-13-install-chromedriver", "title": "Step 13. Install chromedriver", "text": "
    sudo seleniumbase install chromedriver\n
    "}, {"location": "integrations/azure/jenkins/ReadMe/#step-14-run-an-example-test-in-chrome-to-verify-installation-may-take-up-to-10-seconds", "title": "Step 14. Run an example test in Chrome to verify installation (May take up to 10 seconds)", "text": "
    pytest examples/my_first_test.py --headless --browser=chrome\n
    "}, {"location": "integrations/azure/jenkins/ReadMe/#step-15-secure-your-jenkins-machine", "title": "Step 15. Secure your Jenkins machine", "text": ""}, {"location": "integrations/azure/jenkins/ReadMe/#navigate-to-httpjenkins_ip_addressjenkins-on-azure", "title": "Navigate to http://JENKINS_IP_ADDRESS/jenkins-on-azure/", "text": "

    (Depending on your version of Jenkins, you may see the following screen, or nothing at all.)

    "}, {"location": "integrations/azure/jenkins/ReadMe/#initially-jenkins-uses-only-http-which-makes-it-less-secure", "title": "Initially, Jenkins uses only http, which makes it less secure.", "text": ""}, {"location": "integrations/azure/jenkins/ReadMe/#youll-need-to-set-up-ssh-port-forwarding-in-order-to-secure-it", "title": "You'll need to set up SSH Port Forwarding in order to secure it.", "text": "

    ssh -L 127.0.0.1:8080:localhost:8080 USERNAME@DNS_NAME

    "}, {"location": "integrations/azure/jenkins/ReadMe/#step-16-login-to-jenkins", "title": "Step 16. Login to Jenkins", "text": ""}, {"location": "integrations/azure/jenkins/ReadMe/#if-youve-correctly-set-up-ssh-port-forwarding-the-url-will-be-http1270018080", "title": "If you've correctly set up SSH Port Forwarding, the url will be http://127.0.0.1:8080/", "text": ""}, {"location": "integrations/azure/jenkins/ReadMe/#youll-need-to-get-the-password-from-the-ssh-terminal-on-the-linux-machine-to-log-in", "title": "You'll need to get the password from the SSH terminal on the Linux machine to log in", "text": "
    sudo cat /var/lib/jenkins/secrets/initialAdminPassword\n
    "}, {"location": "integrations/azure/jenkins/ReadMe/#step-17-customize-jenkins", "title": "Step 17. Customize Jenkins", "text": ""}, {"location": "integrations/azure/jenkins/ReadMe/#step-18-create-an-admin-user", "title": "Step 18. Create an Admin user", "text": ""}, {"location": "integrations/azure/jenkins/ReadMe/#once-jenkins-has-finished-loading-the-top-left-of-the-page-should-look-like-this", "title": "Once Jenkins has finished loading, the top left of the page should look like this", "text": ""}, {"location": "integrations/azure/jenkins/ReadMe/#step-19-create-a-new-jenkins-job", "title": "Step 19. Create a new Jenkins job", "text": ""}, {"location": "integrations/azure/jenkins/ReadMe/#step-20-setup-your-new-jenkins-job", "title": "Step 20. Setup your new Jenkins job", "text": "
    cd examples\npytest my_first_test.py --headless\n
    "}, {"location": "integrations/azure/jenkins/ReadMe/#click-save-when-youre-done", "title": "Click \"Save\" when you're done.", "text": ""}, {"location": "integrations/azure/jenkins/ReadMe/#step-21-run-your-new-jenkins-job", "title": "Step 21. Run your new Jenkins job", "text": ""}, {"location": "integrations/azure/jenkins/ReadMe/#step-22-see-the-top-jenkins-page-for-an-overview-of-all-jobs", "title": "Step 22. See the top Jenkins page for an overview of all jobs", "text": ""}, {"location": "integrations/azure/jenkins/ReadMe/#step-23-future-work", "title": "Step 23. Future Work", "text": "

    If you have a web application that you want to test, you'll be able to create SeleniumBase tests and add them to Jenkins as you saw here. You may want to create a Deploy job, which downloads the latest version of your repository, and then kicks off all tests to run after that. You could then tell that Deploy job to auto-run whenever a change is pushed to your repository by using: \"Poll SCM\". All your tests would then be able to run by using: \"Build after other projects are built\".

    "}, {"location": "integrations/azure/jenkins/ReadMe/#congratulations-youre-now-well-on-your-way-to-becoming-a-build-release-automation-engineer", "title": "Congratulations! You're now well on your way to becoming a build & release / automation engineer!", "text": ""}, {"location": "integrations/docker/ReadMe/", "title": "\ud83d\udc33 Docker Start Guide", "text": ""}, {"location": "integrations/docker/ReadMe/#docker-setup-instructions-for-seleniumbase", "title": "Docker setup instructions for SeleniumBase", "text": ""}, {"location": "integrations/docker/ReadMe/#1-install-the-docker-toolbox", "title": "1. Install the Docker Toolbox", "text": "

    You can get that from here: https://www.docker.com/products/docker-toolbox

    You might also want to install the Docker Engine: https://docs.docker.com/engine/installation/

    "}, {"location": "integrations/docker/ReadMe/#2-create-your-seleniumbase-docker-environment", "title": "2. Create your SeleniumBase Docker environment", "text": "
    docker-machine create --driver virtualbox seleniumbase\n
    "}, {"location": "integrations/docker/ReadMe/#if-your-docker-environment-ever-goes-down-for-any-reason-you-can-bring-it-back-up-with-a-restart", "title": "(If your Docker environment ever goes down for any reason, you can bring it back up with a restart.)", "text": "
    docker-machine restart seleniumbase\n
    "}, {"location": "integrations/docker/ReadMe/#3-configure-your-shell", "title": "3. Configure your shell", "text": "
    eval \"$(docker-machine env seleniumbase)\"\n
    "}, {"location": "integrations/docker/ReadMe/#4-go-to-the-seleniumbase-home-directory-on-the-command-line-which-is-where-dockerfile-is-located-this-assumes-youve-already-cloned-the-seleniumbase-repo", "title": "4. Go to the SeleniumBase home directory on the command line, which is where Dockerfile is located. (This assumes you've already cloned the SeleniumBase repo.)", "text": ""}, {"location": "integrations/docker/ReadMe/#5-create-your-docker-image-from-your-dockerfile-get-ready-to-wait-awhile", "title": "5. Create your Docker image from your Dockerfile: (Get ready to wait awhile)", "text": "
    docker build -t seleniumbase .\n

    If running on an Apple M1 Mac, use this instead:

    docker build --platform linux/amd64 -t seleniumbase .\n
    "}, {"location": "integrations/docker/ReadMe/#6-run-the-example-test-with-chrome-inside-your-docker-once-the-test-completes-after-a-few-seconds-youll-automatically-exit-the-docker-shell", "title": "6. Run the example test with Chrome inside your Docker: (Once the test completes after a few seconds, you'll automatically exit the Docker shell)", "text": "
    docker run seleniumbase ./run_docker_test_in_chrome.sh\n
    "}, {"location": "integrations/docker/ReadMe/#7-now-run-the-same-test-with-firefox-inside-your-docker", "title": "7. Now run the same test with Firefox inside your Docker", "text": "
    docker run seleniumbase ./run_docker_test_in_firefox.sh\n
    "}, {"location": "integrations/docker/ReadMe/#8-you-can-also-enter-docker-and-stay-inside-the-shell", "title": "8. You can also enter Docker and stay inside the shell", "text": "
    docker run -i -t seleniumbase\n
    "}, {"location": "integrations/docker/ReadMe/#9-now-you-can-run-the-example-test-from-inside-the-docker-shell", "title": "9. Now you can run the example test from inside the Docker shell", "text": "
    ./run_docker_test_in_chrome.sh\n
    "}, {"location": "integrations/docker/ReadMe/#10-when-youre-satisfied-you-may-exit-the-docker-shell", "title": "10. When you're satisfied, you may exit the Docker shell", "text": "
    exit\n
    "}, {"location": "integrations/docker/ReadMe/#11-optional-since-docker-images-and-containers-take-up-a-lot-of-space-you-may-want-to-clean-up-your-machine-from-time-to-time-when-theyre-not-being-used", "title": "11. (Optional) Since Docker images and containers take up a lot of space, you may want to clean up your machine from time to time when they\u2019re not being used", "text": "

    Details on that can be found here: http://stackoverflow.com/questions/17236796/how-to-remove-old-docker-containers

    Here are a few of those cleanup commands:

    docker container prune\ndocker system prune\ndocker images | grep \"<none>\" | awk '{print $3}' | xargs docker rmi\ndocker rm 'docker ps --no-trunc -aq'\n

    If you want to completely remove all of your Docker containers and images, use these commands: (If there's nothing to delete, those commands will return an error.)

    docker rm -f $(docker ps -a -q)\ndocker rmi -f $(docker images -q)\n

    Finally, if you want to wipe out your SeleniumBase Docker virtualbox, use these commands:

    docker-machine kill seleniumbase\ndocker-machine rm seleniumbase\n

    For more cleanup commands, check out: https://codefresh.io/blog/everyday-hacks-docker/

    "}, {"location": "integrations/docker/ReadMe/#13-optional-more-reading-on-docker-can-be-found-here", "title": "13. (Optional) More reading on Docker can be found here", "text": ""}, {"location": "integrations/github/workflows/ReadMe/", "title": "\ud83e\udd16 GitHub CI", "text": ""}, {"location": "integrations/github/workflows/ReadMe/#running-browser-tests-on-github-actions-with-seleniumbase", "title": "Running browser tests on GitHub Actions with SeleniumBase", "text": ""}, {"location": "integrations/github/workflows/ReadMe/#step-0-create-a-fork-of-seleniumbase-on-github-to-help-you-get-started", "title": "Step 0. Create a fork of SeleniumBase on GitHub to help you get started.", "text": ""}, {"location": "integrations/github/workflows/ReadMe/#step-1-from-the-github-actions-tab-choose-to-set-up-a-python-package-workflow", "title": "Step 1. From the GitHub Actions tab, choose to set up a Python package Workflow.", "text": ""}, {"location": "integrations/github/workflows/ReadMe/#step-2-add-your-workflow-yml-script", "title": "Step 2. Add your workflow .yml script.", "text": ""}, {"location": "integrations/github/workflows/ReadMe/#step-3-commit-your-changes-to-github", "title": "Step 3. Commit your changes to GitHub.", "text": ""}, {"location": "integrations/github/workflows/ReadMe/#step-4-your-tests-will-now-run-on-every-pull-request-and-on-every-commit-to-the-master-branch", "title": "Step 4. Your tests will now run on every pull request and on every commit to the master branch.", "text": " "}, {"location": "integrations/github/workflows/ReadMe/#congratulations-you-now-know-how-to-create-and-run-browser-tests-with-github-actions", "title": "Congratulations! You now know how to create and run browser tests with GitHub Actions!", "text": ""}, {"location": "integrations/github/workflows/ReadMe/#study-seleniumbase-to-learn-more", "title": "Study SeleniumBase to learn more!", "text": ""}, {"location": "integrations/google_cloud/ReadMe/", "title": "\ud83e\udd16 Jenkins on Google Cloud", "text": ""}, {"location": "integrations/google_cloud/ReadMe/#building-a-browser-based-test-automation-server-on-the-google-cloud-platform-by-using-seleniumbase", "title": "Building a browser-based test automation server on the Google Cloud Platform by using SeleniumBase", "text": "

    (This tutorial, from a previous Google Cloud Meetup, will teach you how to setup a Linux server for running automated browser tests. The cost of running this server is about $13.60/month on Google Cloud (enough to handle 5 parallel tests). This is less expensive than using other platforms.)

    "}, {"location": "integrations/google_cloud/ReadMe/#step-1-open-the-google-cloud-platform-cloud-launcher", "title": "Step 1. Open the Google Cloud Platform Cloud Launcher", "text": ""}, {"location": "integrations/google_cloud/ReadMe/#step-2-launch-a-jenkins-instance", "title": "Step 2. Launch a Jenkins instance", "text": ""}, {"location": "integrations/google_cloud/ReadMe/#step-3-connect-with-your-new-jenkins-instance", "title": "Step 3. Connect with your new Jenkins instance", "text": ""}, {"location": "integrations/google_cloud/ReadMe/#step-4-clone-the-seleniumbase-repository-from-the-root-directory", "title": "Step 4. Clone the SeleniumBase repository from the root (\"/\") directory.", "text": "
    cd /\nsudo git clone https://github.com/seleniumbase/SeleniumBase.git\n
    "}, {"location": "integrations/google_cloud/ReadMe/#step-5-enter-the-linux-folder", "title": "Step 5. Enter the \"linux\" folder", "text": "
    cd SeleniumBase/integrations/linux/\n
    "}, {"location": "integrations/google_cloud/ReadMe/#step-6-give-jenkins-aka-tomcat-user-sudo-access-see-tomcat_permissionssh-for-details", "title": "Step 6. Give Jenkins (aka \"tomcat\" user) sudo access (See tomcat_permissions.sh for details)", "text": "
    ./tomcat_permissions.sh\n
    "}, {"location": "integrations/google_cloud/ReadMe/#step-7-become-tomcat-the-jenkins-user-and-enter-a-bash-shell", "title": "Step 7. Become \"tomcat\" (the Jenkins user) and enter a \"bash\" shell", "text": "
    sudo su tomcat\nbash\n
    "}, {"location": "integrations/google_cloud/ReadMe/#step-8-install-dependencies-see-linuxfilesh-for-details", "title": "Step 8. Install dependencies (See Linuxfile.sh for details)", "text": "
    ./Linuxfile.sh\n
    "}, {"location": "integrations/google_cloud/ReadMe/#step-9-start-up-the-headless-browser-display-mechanism-xvfb-see-xvfb_launchersh-for-details", "title": "Step 9. Start up the headless browser display mechanism: Xvfb (See Xvfb_launcher.sh for details)", "text": "
    ./Xvfb_launcher.sh\n
    "}, {"location": "integrations/google_cloud/ReadMe/#step-10-go-to-the-seleniumbase-directory", "title": "Step 10. Go to the SeleniumBase directory", "text": "
    cd /SeleniumBase\n
    "}, {"location": "integrations/google_cloud/ReadMe/#step-11-install-the-requirements-for-seleniumbase", "title": "Step 11. Install the requirements for SeleniumBase", "text": "
    sudo pip install -r requirements.txt --upgrade\n
    "}, {"location": "integrations/google_cloud/ReadMe/#step-12-install-seleniumbase", "title": "Step 12. Install SeleniumBase", "text": "
    sudo python setup.py develop\n
    "}, {"location": "integrations/google_cloud/ReadMe/#step-13-run-an-example-test-on-chrome-to-verify-installation-may-take-up-to-10-seconds", "title": "Step 13. Run an example test on Chrome to verify installation (May take up to 10 seconds)", "text": "
    pytest examples/my_first_test.py --headless\n
    "}, {"location": "integrations/google_cloud/ReadMe/#step-14-if-you-prefer-using-nosetests-that-works-too", "title": "Step 14. If you prefer using nosetests, that works too", "text": "
    nosetests examples/my_first_test.py --headless\n
    "}, {"location": "integrations/google_cloud/ReadMe/#step-15-you-can-also-verify-that-the-example-test-runs-on-firefox", "title": "Step 15. You can also verify that the example test runs on Firefox", "text": "
    pytest examples/my_first_test.py --headless --browser=firefox\n
    "}, {"location": "integrations/google_cloud/ReadMe/#step-16-login-to-jenkins", "title": "Step 16. Login to Jenkins", "text": ""}, {"location": "integrations/google_cloud/ReadMe/#step-17-create-a-new-jenkins-job", "title": "Step 17. Create a new Jenkins job", "text": ""}, {"location": "integrations/google_cloud/ReadMe/#step-18-setup-your-new-jenkins-job", "title": "Step 18. Setup your new Jenkins job", "text": "
    pytest examples/my_first_test.py --headless\n
    "}, {"location": "integrations/google_cloud/ReadMe/#step-19-run-your-new-jenkins-job", "title": "Step 19. Run your new Jenkins job", "text": ""}, {"location": "integrations/google_cloud/ReadMe/#step-20-future-work", "title": "Step 20. Future Work", "text": "

    If you have a web application that you want to test, you'll be able to create SeleniumBase tests and add them to Jenkins as you saw here. You may want to create a Deploy job, which downloads the latest version of your repository, and then kicks off all tests to run after that. You could then tell that Deploy job to auto-run whenever a change is pushed to your repository by using: \"Poll SCM\". All your tests would then be able to run by using: \"Build after other projects are built\". You can also use MySQL to save test results in the DB so that you can query the data at any time.

    "}, {"location": "integrations/google_cloud/ReadMe/#congratulations-youre-now-well-on-your-way-to-becoming-a-build-release-automation-engineer", "title": "Congratulations! You're now well on your way to becoming a build & release / automation engineer!", "text": ""}, {"location": "integrations/google_cloud/ReadMe/#mysql-db-setup-instructions", "title": "MySQL DB setup instructions", "text": ""}, {"location": "integrations/google_cloud/ReadMe/#step-21-return-to-the-google-cloud-launcher-and-launch-a-mysql-instance", "title": "Step 21. Return to the Google Cloud Launcher and launch a MySQL Instance", "text": ""}, {"location": "integrations/google_cloud/ReadMe/#step-22-get-the-connection-credentials-for-your-new-mysql-instance", "title": "Step 22. Get the Connection credentials for your new MySQL Instance", "text": ""}, {"location": "integrations/google_cloud/ReadMe/#step-23-get-a-mysql-gui-tool-so-that-you-can-connect-to-your-mysql-instance", "title": "Step 23. Get a MySQL GUI tool so that you can connect to your MySQL Instance", "text": ""}, {"location": "integrations/google_cloud/ReadMe/#step-24-create-a-new-connection-to-your-mysql-instance", "title": "Step 24. Create a new connection to your MySQL Instance", "text": ""}, {"location": "integrations/google_cloud/ReadMe/#step-25-create-a-new-databaseschema-in-your-mysql-instance", "title": "Step 25. Create a new database/schema in your MySQL Instance", "text": ""}, {"location": "integrations/google_cloud/ReadMe/#step-26-create-the-necessary-tables-in-your-mysql-databaseschema", "title": "Step 26. Create the necessary tables in your MySQL database/schema", "text": ""}, {"location": "integrations/google_cloud/ReadMe/#step-27-have-your-local-clone-of-seleniumbase-connect-to-your-mysql-db-instance", "title": "Step 27. Have your local clone of SeleniumBase connect to your MySQL DB Instance", "text": ""}, {"location": "integrations/google_cloud/ReadMe/#step-28-have-your-seleniumbase-jenkins-jobs-use-your-mysql-db-instance", "title": "Step 28. Have your SeleniumBase Jenkins jobs use your MySQL DB Instance", "text": "
    pytest examples/test_suite.py --headless --with-db_reporting\n
    "}, {"location": "integrations/google_cloud/ReadMe/#step-29-run-your-new-jenkins-job", "title": "Step 29. Run your new Jenkins job", "text": ""}, {"location": "integrations/google_cloud/ReadMe/#step-30-congratulations-youve-successfully-completed-this-tutorial", "title": "Step 30. Congratulations! You've successfully completed this tutorial!", "text": ""}, {"location": "seleniumbase/common/ReadMe/", "title": "\ud83d\udd10 Decorators / Security", "text": ""}, {"location": "seleniumbase/common/ReadMe/#using-seleniumbasecommon-methods", "title": "Using seleniumbase/common methods.", "text": ""}, {"location": "seleniumbase/common/ReadMe/#part-1-decorators-from-decoratorspy", "title": "Part 1: Decorators - (from decorators.py)", "text": ""}, {"location": "seleniumbase/common/ReadMe/#use-these-python-decorators-with-your-test-methods-as-needed", "title": "Use these Python decorators with your test methods as needed", "text": "

    Example demonstrating a rate-limited printing functionality:

    import unittest\nfrom seleniumbase import decorators\n\nclass MyTestClass(unittest.TestCase):\n\n    @decorators.rate_limited(3.5)  # The arg is max calls per second\n    def print_item(self, item):\n        print(item)\n\n    def test_rate_limited_printing(self):\n        print(\"\\nRunning rate-limited print test:\")\n        for item in range(1, 11):\n            self.print_item(item)\n
    "}, {"location": "seleniumbase/common/ReadMe/#part-2-stringpassword-obfuscation-encryption-and-decryption", "title": "Part 2: String/Password Obfuscation, Encryption, and Decryption", "text": ""}, {"location": "seleniumbase/common/ReadMe/#intro", "title": "Intro", "text": "

    Often in your tests, you may need to login to a website to perform testing. This generally means storing passwords in plaintext formats. For security reasons, that may not be an optimal solution. For this reason, encryption/obfuscation tools have been built here to help you mask your passwords in your tests. It's not a bulletproof solution, but it can keep anyone looking over your shoulder during test creation from getting your login passwords if they don't have your encryption key, which is stored in a separate file.

    "}, {"location": "seleniumbase/common/ReadMe/#usage", "title": "Usage", "text": "
    python obfuscate.py\n\nEnter password to obfuscate: (CTRL+C to exit)\nPassword: *********\nVerify password:\nPassword: *********\n\nHere is the obfuscated password:\n$^*ENCRYPT=RXlYMSJWTz8HSwM=?&#$\n

    (You can also use unobfuscate.py to encrypt passwords without having them masked while typing them. Or you can use it to decrypt an obfuscated password.)

    from seleniumbase import encryption\n...\npassword = encryption.decrypt('$^*ENCRYPT=RXlYMSJWTz8HSwM=?&#$')\n

    (You'll notice that encrypted strings have a common start token and end token. This is to help tell them apart from non-encrypted strings. You can customize these tokens in settings.py. The current default setting is $^*ENCRYPT= for the start token and ?&#$ for the end token.)

    See decryption_test.py for an example of decrypting encrypted passwords in tests.

    "}, {"location": "seleniumbase/console_scripts/ReadMe/", "title": "\ud83c\udf20 Console Scripts", "text": ""}, {"location": "seleniumbase/console_scripts/ReadMe/#console-scripts", "title": "Console Scripts \ud83c\udf20", "text": "

    \ud83c\udf1f SeleniumBase console scripts can do many things, such as downloading web drivers, creating test directories with config files, activating the SeleniumBase Recorder, launching the SeleniumBase Commander, translating tests into other languages, running a Selenium Grid, and more.

    (For running tests, use pytest with SeleniumBase.)

    COMMANDS:\n      get / install    [DRIVER] [OPTIONS]\nmethods          (List common Python methods)\noptions          (List common pytest options)\nbehave-options   (List common behave options)\ngui / commander  [OPTIONAL PATH or TEST FILE]\nbehave-gui       (SBase Commander for Behave)\ncaseplans        [OPTIONAL PATH or TEST FILE]\nmkdir            [DIRECTORY] [OPTIONS]\nmkfile           [FILE.py] [OPTIONS]\nmkrec / codegen  [FILE.py] [OPTIONS]\nrecorder         (Open Recorder Desktop App.)\nrecord           (If args: mkrec. Else: App.)\nmkpres           [FILE.py] [LANG]\nmkchart          [FILE.py] [LANG]\nprint            [FILE] [OPTIONS]\ntranslate        [SB_FILE.py] [LANG] [ACTION]\nconvert          [WEBDRIVER_UNITTEST_FILE.py]\nextract-objects  [SB_FILE.py]\ninject-objects   [SB_FILE.py] [OPTIONS]\nobjectify        [SB_FILE.py] [OPTIONS]\nrevert-objects   [SB_FILE.py] [OPTIONS]\nencrypt / obfuscate\n      decrypt / unobfuscate\n      download server  (Get Selenium Grid JAR file)\ngrid-hub         [start|stop] [OPTIONS]\ngrid-node        [start|stop] --hub=[HOST/IP]\n* (EXAMPLE: \"sbase get chromedriver\") *\n\n    Type \"sbase help [COMMAND]\" for specific command info.\n    For info on all commands, type: \"seleniumbase --help\".\n    Use \"pytest\" for running tests.\n
    get / install
    sbase get [DRIVER] [OPTIONS]\nsbase install [DRIVER] [OPTIONS]\n
    sbase get chromedriver\nsbase get geckodriver\nsbase get edgedriver\nsbase get chromedriver 114\nsbase get chromedriver 114.0.5735.90\nsbase get chromedriver -p\n

    (Drivers: chromedriver, geckodriver, edgedriver, iedriver, operadriver, uc_driver)

    (Options: A specific driver version or major version integer. If not set, the driver version matches the browser. -p / --path: Also copy to \"/usr/local/bin\".)

    Downloads the webdriver to seleniumbase/drivers/ (chromedriver is required for Chrome automation) (geckodriver is required for Firefox automation) (edgedriver is required for MS__Edge automation)

    methods
    sbase methods\n

    Displays common SeleniumBase Python methods.

    options
    sbase options\n

    Displays common pytest command-line options that are available when using SeleniumBase.

    --browser=BROWSER  (The web browser to use. Default is \"chrome\")\n--edge / --firefox / --safari  (Shortcut for browser selection.)\n--headless  (Run tests headlessly. Default mode on Linux OS.)\n--demo  (Slow down and visually see test actions as they occur.)\n--slow  (Slow down the automation. Faster than using Demo Mode.)\n--rs / --reuse-session  (Reuse browser session between tests.)\n--crumbs  (Clear all cookies between tests reusing a session.)\n--maximize  (Start tests with the web browser window maximized.)\n--dashboard  (Enable SeleniumBase\\'s Dashboard at dashboard.html)\n--incognito  (Enable Chromium\\'s Incognito mode.)\n--guest  (Enable Chromium\\'s Guest Mode.)\n--dark  (Enable Chromium\\'s Dark Mode.)\n--uc  (Use undetected-chromedriver to evade detection.)\n-m=MARKER  (Run tests with the specified pytest marker.)\n-n=NUM  (Multithread the tests using that many threads.)\n-v  (Verbose mode. Print the full names of each test run.)\n--html=report.html  (Create a detailed pytest-html report.)\n--collect-only / --co  (Only show discovered tests. No run.)\n--co -q  (Only show full names of discovered tests. No run.)\n-x  (Stop running tests after the first failure is reached.)\n--pdb  (Enter the Post Mortem Debug Mode after any test fails.)\n--trace  (Enter Debug Mode immediately after starting any test.)\n| Debug Mode Commands  >>>   help / h: List all commands. |\n|   n: Next line of method. s: Step through. c: Continue. |\n|  return / r: Run until method returns. j: Jump to line. |\n| where / w: Show stack spot. u: Up stack. d: Down stack. |\n| longlist / ll: See code. dir(): List namespace objects. |\n--help / -h  (Display list of all available pytest options.)\n--final-debug  (Enter Final Debug Mode after each test ends.)\n--recorder / --rec  (Save browser actions as Python scripts.)\n--rec-behave / --rec-gherkin  (Save actions as Gherkin code.)\n--rec-print  (Display recorded scripts when they are created.)\n--save-screenshot  (Save a screenshot at the end of each test.)\n--archive-logs  (Archive old log files instead of deleting them.)\n--check-js  (Check for JavaScript errors after page loads.)\n--start-page=URL  (The browser start page when tests begin.)\n--agent=STRING  (Modify the web browser\\'s User-Agent string.)\n--mobile  (Use Chromium\\'s mobile device emulator during tests.)\n--metrics=STRING  (Set mobile \"CSSWidth,CSSHeight,PixelRatio\".)\n--ad-block  (Block some types of display ads after page loads.)\n--settings-file=FILE  (Override default SeleniumBase settings.)\n--env=ENV  (Set the test env. Access with \"self.env\" in tests.)\n--data=DATA  (Extra test data. Access with \"self.data\" in tests.)\n--disable-csp  (Disable the Content Security Policy of websites.)\n--remote-debug  (Sync to Ch-R-Debugger chrome://inspect/#devices)\n--server=SERVER  (The Selenium Grid server/IP used for tests.)\n--port=PORT  (The Selenium Grid port used by the test server.)\n--proxy=SERVER:PORT  (Connect to a proxy server:port for tests.)\n--proxy=USER:PASS@SERVER:PORT  (Use authenticated proxy server.)\n\nFor the full list of command-line options, type: \"pytest --help\".\n
    behave-options
    sbase behave-options\n

    Displays common Behave command-line options that are available when using SeleniumBase.

    -D browser=BROWSER  (The web browser to use. Default is \"chrome\")\n-D headless  (Run tests headlessly. Default mode on Linux OS.)\n-D demo  (Slow down and visually see test actions as they occur.)\n-D slow  (Slow down the automation. Faster than using Demo Mode.)\n-D reuse-session / -D rs  (Reuse browser session between tests.)\n-D crumbs  (Clear all cookies between tests reusing a session.)\n-D maximize  (Start tests with the web browser window maximized.)\n-D dashboard  (Enable SeleniumBase\\'s Dashboard at dashboard.html)\n-D incognito  (Enable Chromium\\'s Incognito Mode.)\n-D guest  (Enable Chromium\\'s Guest Mode.)\n-D dark  (Enable Chromium\\'s Dark Mode.)\n-D uc  (Use undetected-chromedriver to evade detection.)\n--no-snippets / -q  (Quiet mode. Don\\'t print snippets.)\n--dry-run / -d  (Dry run. Only show discovered tests.)\n--stop  (Stop running tests after the first failure is reached.)\n-D pdb  (Enter the Post Mortem Debug Mode after any test fails.)\n| Debug Mode Commands  >>>   help / h: List all commands. |\n|   n: Next line of method. s: Step through. c: Continue. |\n|  return / r: Run until method returns. j: Jump to line. |\n| where / w: Show stack spot. u: Up stack. d: Down stack. |\n| longlist / ll: See code. dir(): List namespace objects. |\n-D recorder  (Record browser actions to generate test scripts.)\n-D rec-print  (Display recorded scripts when they are created.)\n-D save-screenshot  (Save a screenshot at the end of each test.)\n-D archive-logs  (Archive old log files instead of deleting them.)\n-D check-js  (Check for JavaScript errors after page loads.)\n-D start-page=URL  (The browser start page when tests begin.)\n-D agent=STRING  (Modify the web browser\\'s User-Agent string.)\n-D mobile  (Use Chromium\\'s mobile device emulator during tests.)\n-D metrics=STRING  (Set mobile \"CSSWidth,CSSHeight,PixelRatio\".)\n-D ad-block  (Block some types of display ads after page loads.)\n-D settings-file=FILE  (Override default SeleniumBase settings.)\n-D env=ENV  (Set the test env. Access with \"self.env\" in tests.)\n-D data=DATA  (Extra test data. Access with \"self.data\" in tests.)\n-D disable-csp  (Disable the Content Security Policy of websites.)\n-D remote-debug  (Sync to Ch-R-Debugger chrome://inspect/#devices)\n-D server=SERVER  (The Selenium Grid server/IP used for tests.)\n-D port=PORT  (The Selenium Grid port used by the test server.)\n-D proxy=SERVER:PORT  (Connect to a proxy server:port for tests.)\n-D proxy=USER:PASS@SERVER:PORT  (Use authenticated proxy server.)\n\nFor the full list of command-line options, type: \"behave --help\".\n
    gui / commander
    sbase gui [OPTIONAL PATH or TEST FILE]\nsbase commander [OPTIONAL PATH or TEST FILE]\n
    behave-gui
    sbase behave-gui [OPTIONAL PATH or TEST FILE]\nsbase gui-behave [OPTIONAL PATH or TEST FILE]\n
    sbase behave-gui\nsbase behave-gui -i=calculator\nsbase behave-gui features/\nsbase behave-gui features/calculator.feature\n

    Launches SeleniumBase Commander / GUI for Behave.

    caseplans
    sbase caseplans [OPTIONAL PATH or TEST FILE]\n
    sbase caseplans\nsbase caseplans -k agent\nsbase caseplans -m marker2\nsbase caseplans test_suite.py\nsbase caseplans offline_examples/\n

    Launches the SeleniumBase Case Plans Generator.

    mkdir
    sbase mkdir [DIRECTORY] [OPTIONS]\n
    sbase mkdir ui_tests\n

    -b / --basic (Only config files. No tests added.)

    Creates a new folder for running SBase scripts. The new folder contains default config files, sample tests for helping new users get started, and Python boilerplates for setting up customized test frameworks.

    ui_tests/\n\u251c\u2500\u2500 __init__.py\n\u251c\u2500\u2500 my_first_test.py\n\u251c\u2500\u2500 parameterized_test.py\n\u251c\u2500\u2500 pytest.ini\n\u251c\u2500\u2500 requirements.txt\n\u251c\u2500\u2500 setup.cfg\n\u251c\u2500\u2500 test_demo_site.py\n\u2514\u2500\u2500 boilerplates/\n    \u251c\u2500\u2500 __init__.py\n    \u251c\u2500\u2500 base_test_case.py\n    \u251c\u2500\u2500 boilerplate_test.py\n    \u251c\u2500\u2500 classic_obj_test.py\n    \u251c\u2500\u2500 page_objects.py\n    \u251c\u2500\u2500 sb_fixture_test.py\n    \u2514\u2500\u2500 samples/\n        \u251c\u2500\u2500 __init__.py\n        \u251c\u2500\u2500 google_objects.py\n        \u251c\u2500\u2500 google_test.py\n        \u251c\u2500\u2500 sb_swag_test.py\n        \u2514\u2500\u2500 swag_labs_test.py\n

    If running with the -b or --basic option:

    ui_tests/\n\u251c\u2500\u2500 __init__.py\n\u251c\u2500\u2500 pytest.ini\n\u251c\u2500\u2500 requirements.txt\n\u2514\u2500\u2500 setup.cfg\n
    mkfile
    sbase mkfile [FILE.py] [OPTIONS]\n
    sbase mkfile new_test.py\n

    -b / --basic (Basic boilerplate / single-line test) -r / --rec (adds Pdb+ breakpoint for Recorder Mode)

    --en / --English | --zh / --Chinese --nl / --Dutch | --fr / --French --it / --Italian | --ja / --Japanese --ko / --Korean | --pt / --Portuguese --ru / --Russian | --es / --Spanish

    --bc / --basecase (BaseCase class inheritance) --pf / --pytest-fixture (sb pytest fixture) --cf / --class-fixture (class + sb pytest fixture) --cm / --context-manager (SB context manager) --dc / --driver-context (DriverContext manager) --dm / --driver-manager (Driver manager)

    Creates a new SBase test file with boilerplate code. If the file already exists, an error is raised. By default, uses English with BaseCase inheritance, and creates a boilerplate with common SeleniumBase methods: \"open\", \"type\", \"click\", \"assert_element\", and \"assert_text\". If using the basic boilerplate option, only the \"open\" method is included. Only the BaseCase format supports Languages or Recorder Mode.

    mkrec / record / codegen
    sbase mkrec [FILE.py] [OPTIONS]\nsbase codegen [FILE.py] [OPTIONS]\n
    sbase mkrec new_test.py\nsbase mkrec new_test.py --url=seleniumbase.io\nsbase codegen new_test.py\nsbase codegen new_test.py --url=wikipedia.org\n

    --url=URL (Sets the initial start page URL.) --edge (Use Edge browser instead of Chrome.) --gui / --headed (Use headed mode on Linux.) --uc / --undetected (Use undetectable mode.) --overwrite (Overwrite file when it exists.) --behave (Also output Behave/Gherkin files.)

    Creates a new SeleniumBase test using the Recorder. If the filename already exists, an error is raised.

    recorder
    sbase recorder [OPTIONS]\n

    --uc / --undetected (Use undetectable mode.) --behave (Also output Behave/Gherkin files.)

    Launches the SeleniumBase Recorder Desktop App.

    mkpres
    sbase mkpres [FILE.py] [LANG]\n
    sbase mkpres new_presentation.py --en\n

    --en / --English | --zh / --Chinese --nl / --Dutch | --fr / --French --it / --Italian | --ja / --Japanese --ko / --Korean | --pt / --Portuguese --ru / --Russian | --es / --Spanish

    Creates a new presentation with 3 example slides. If the file already exists, an error is raised. By default, the slides are written in English, and use \"serif\" theme with \"slide\" transition. The slides can be used as a basic boilerplate.

    mkchart
    sbase mkchart [FILE.py] [LANG]\n
    sbase mkchart new_chart.py --en\n

    --en / --English | --zh / --Chinese --nl / --Dutch | --fr / --French --it / --Italian | --ja / --Japanese --ko / --Korean | --pt / --Portuguese --ru / --Russian | --es / --Spanish

    Creates a new SeleniumBase chart presentation. If the file already exists, an error is raised. By default, the slides are written in English, and use a \"sky\" theme with \"slide\" transition. The chart can be used as a basic boilerplate.

    print
    sbase print [FILE] [OPTIONS]\n

    -n (Add line Numbers to the rows)

    Prints the code/text of any file with syntax-highlighting.

    translate
    sbase translate [SB_FILE.py] [LANGUAGE] [ACTION]\n

    --en / --English | --zh / --Chinese --nl / --Dutch | --fr / --French --it / --Italian | --ja / --Japanese --ko / --Korean | --pt / --Portuguese --ru / --Russian | --es / --Spanish

    -p / --print (Print translation output to the screen) -o / --overwrite (Overwrite the file being translated) -c / --copy (Copy the translation to a new .py file)

    -n (include line Numbers when using the Print action)

    Translates a SeleniumBase Python file into the language specified. Method calls and \"import\" lines get swapped. Both a language and an action must be specified. The -p action can be paired with one other action. When running with -c (or --copy), the new file name will be the original name appended with an underscore plus the 2-letter language code of the new language. (Example: Translating \"test_1.py\" into Japanese with -c will create a new file called \"test_1_ja.py\".)

    extract-objects
    sbase extract-objects [SB_FILE.py]\n

    Creates page objects based on selectors found in a seleniumbase Python file and saves those objects to the \"page_objects.py\" file in the same folder as the tests.

    inject-objects
    sbase inject-objects [SB_FILE.py] [OPTIONS]\n

    -c, --comments (Add object selectors to the comments.)

    Takes the page objects found in the \"page_objects.py\" file and uses those to replace matching selectors in the selected seleniumbase Python file.

    objectify
    sbase objectify [SB_FILE.py] [OPTIONS]\n

    -c, --comments (Add object selectors to the comments.)

    A modified version of the file where the selectors have been replaced with variable names defined in \"page_objects.py\", supporting the Page Object Pattern. (This has the same outcome as combining extract-objects with inject-objects)

    revert-objects
    sbase revert-objects [SB_FILE.py] [OPTIONS]\n

    -c, --comments (Keep existing comments for the lines.)

    Reverts the changes made by seleniumbase objectify ... or seleniumbase inject-objects ... when run against a seleniumbase Python file. Objects will get replaced by selectors stored in the \"page_objects.py\" file.

    convert
    sbase convert [WEBDRIVER_UNITTEST_FILE.py]\n

    Converts a Selenium IDE exported WebDriver unittest file into a SeleniumBase file. Adds _SB to the new file name while keeping the original file intact. Works with Katalon Recorder scripts. See This ReadMe for details.

    encrypt / obfuscate

    sbase encrypt OR sbase obfuscate

    Runs the password encryption/obfuscation tool. (Where you can enter a password to encrypt/obfuscate.)

    decrypt / unobfuscate

    sbase decrypt OR sbase unobfuscate

    Runs the password decryption/unobfuscation tool. (Where you can enter an encrypted password to decrypt.)

    download
    sbase download server\n

    Downloads the Selenium Server JAR file for Grid usage. (That JAR file is required when using a Selenium Grid)

    grid-hub
    sbase grid-hub {start|stop|restart} [OPTIONS]\n

    -v, --verbose (Increases verbosity of logging output.) --timeout=TIMEOUT (Close idle browser windows after TIMEOUT seconds.)

    Controls the Selenium Grid Hub server, which allows for running tests on multiple machines in parallel to speed up test runs and reduce the total time of test suite execution. You can start, restart, or stop the Grid Hub server.

    grid-node
    sbase grid-node {start|stop|restart} [OPTIONS]\n

    --hub=HUB_IP (The Grid Hub IP Address to connect to.) (Default: 127.0.0.1) -v, --verbose (Increases verbosity of logging output.)

    Controls the Selenium Grid node, which serves as a worker machine for your Selenium Grid Hub server. You can start, restart, or stop the Grid node.

    "}, {"location": "seleniumbase/utilities/selenium_grid/ReadMe/", "title": "\ud83c\udf10 Selenium Grid", "text": "The Selenium Grid Hub:

    The Selenium Grid Hub lets you distribute tests to run in parallel across multiple node machines. Each node machine can then run its own allocation of tests. This allows you to run a large suite of tests very quickly.

    Running the Selenium Grid Hub:

    The following commands will work once you've installed seleniumbase.

    Downloading the Selenium Server JAR file:
    seleniumbase download server\n
    Grid Hub server controls:
    seleniumbase grid-hub {start|stop|restart} [OPTIONS]\n

    Options:

    Grid node server controls:
    seleniumbase grid-node {start|stop|restart} --hub=[HUB_IP] [OPTIONS]\n

    Options:

    When the Grid Hub Console is up and running, you'll be able to find it here: http://127.0.0.1:4444/grid/console

    Now you can run your tests on the Selenium Grid:

    pytest test_demo_site.py --server=IP_ADDRESS --port=4444\n

    You can also run your tests on someone else's Selenium Grid to avoid managing your own. Here are some Selenium Grids that you can use (and the run command format):

    pytest test_demo_site.py --server=USERNAME:KEY@hub.browserstack.com --port=80\n
    pytest test_demo_site.py --server=USERNAME:KEY@ondemand.us-east-1.saucelabs.com --port=443 --protocol=https\n
    pytest test_demo_site.py --server=USERNAME:KEY@demo.perfectomobile.com/nexperience/perfectomobile --port=443\n
    pytest test_demo_site.py --server=USERNAME:KEY@hub.testingbot.com --port=80\n
    pytest test_demo_site.py --server=USERNAME:KEY@hub.lambdatest.com --port=80\n
    pytest test_demo_site.py --server=USERNAME:KEY@hub.crossbrowsertesting.com --port=80\n

    To use a server on the https protocol, add --protocol=https: (SeleniumBase 1.65.2 and newer uses https automatically for --port=443.)

    pytest test_demo_site.py --protocol=https --server=IP_ADDRESS --port=PORT\n

    (For setting browser desired capabilities while running Selenium remotely, see the desired capabilities documentation and the sample files located in SeleniumBase/examples/capabilities)

    More info about the Selenium Grid Hub can be found here: "}]} \ No newline at end of file +{"config": {"lang": ["en"], "separator": "[\\s]+", "pipeline": ["stopWordFilter"]}, "docs": [{"location": "", "title": "\u2705 SeleniumBase README", "text": "SeleniumBase All-in-one Test Automation Framework For Python enthusiasts and enterprise developers

    \ud83d\ude80 Start | \ud83c\udff0 Features | \ud83d\udcda Examples | \ud83c\udf9b\ufe0f Options | \ud83c\udf20 Scripts | \ud83d\udcf1 Mobile \ud83d\udcd8 APIs | \ud83d\udd21 Formats | \ud83d\udcca Dashboard | \ud83d\udd34 Recorder | \ud83d\uddfe Locales | \ud83c\udf10 Grid \ud83c\udf96\ufe0f GUI | \ud83d\udcf0 TestPage | \ud83d\uddc2\ufe0f CasePlans | \ud83d\udd75\ufe0f Inspector | \ud83e\uddec Hybrid | \ud83d\udcbb Farm \ud83d\udc41\ufe0f How | \ud83d\ude9d Migrate | \u267b\ufe0f Templates | \ud83d\ude89 NodeGUI | \ud83d\udcf6 Charts | \ud83d\ude8e Tours \ud83e\udd16 CI/CD | \ud83d\udd79\ufe0f JSMgr | \ud83c\udf0f Translator | \ud83c\udf9e\ufe0f Presenter | \ud83d\udec2 Dialog | \ud83d\uddbc\ufe0f Visual

    Explore the README:

    Example: test_demo_site.py from ./examples/ (Uses --chrome by default)

    cd examples/\npytest test_demo_site.py\n

    Easy to type, click, select, toggle, drag-and-drop, etc.

    Example: test_coffee_cart.py from ./examples/

    cd examples/\npytest test_coffee_cart.py --demo\n

    (--demo mode slows down tests and highlights actions)

    from seleniumbase import BaseCase\nBaseCase.main(__name__, __file__)\n\nclass CoffeeCartTest(BaseCase):\n    def test_coffee_cart(self):\n        self.open(\"https://seleniumbase.io/coffee/\")\n        self.assert_title(\"Coffee Cart\")\n        self.click('div[data-sb=\"Cappuccino\"]')\n        self.click('div[data-sb=\"Flat-White\"]')\n        self.click('div[data-sb=\"Cafe-Latte\"]')\n        self.click('a[aria-label=\"Cart page\"]')\n        self.assert_exact_text(\"Total: $53.00\", \"button.pay\")\n        self.click(\"button.pay\")\n        self.type(\"input#name\", \"Selenium Coffee\")\n        self.type(\"input#email\", \"test@test.test\")\n        self.click(\"button#submit-payment\")\n        self.assert_text(\"Thanks for your purchase.\", \"#app .success\")\n

    (For more examples, see the SeleniumBase/examples/ folder.)

    \u25b6\ufe0f How is SeleniumBase different from raw Selenium? (click to expand)

    \ud83d\udca1 SeleniumBase is a Python framework for browser automation and testing. SeleniumBase uses Selenium/WebDriver APIs, and incorporates test-runners such as pytest, pynose, and behave to provide organized structure, test discovery, test execution, test state (eg. passed, failed, or skipped), and command-line options for changing default settings (such as choosing the browser to use). With raw Selenium, you would need to set up your own options-parser for configuring tests from the command-line.

    \ud83d\udca1 With raw Selenium, commands that use selectors need to specify the type of selector (eg. \"css selector\", \"button#myButton\"). 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 (but optionally you could).

    \ud83d\udca1 SeleniumBase methods often perform multiple actions in a single method call. For example, self.type(selector,text) does the following:1. Waits for the element to be visible.2. Waits for the element to be interactive.3. Clears the text field.4. Types in the new text.5. Presses Enter/Submit if the text ends in \"\\n\".With raw Selenium, those actions require multiple method calls.

    \ud83d\udca1 SeleniumBase uses default timeout values when not set: \u2705self.click(\"button\") With raw Selenium, methods would fail instantly (by default) if an element needed more time to load: \u274cself.driver.find_element(by=\"css selector\", value=\"button\").click() (Reliable code is better than unreliable code.)

    \ud83d\udca1 SeleniumBase lets you change the explicit timeout values of methods: \u2705self.click(\"button\",timeout=10) With raw Selenium, that requires more code: \u274cWebDriverWait(driver,10).until(EC.element_to_be_clickable(\"css selector\", \"button\")).click() (Simple code is better than complex code.)

    \ud83d\udca1 SeleniumBase gives you clean error output when a test fails. With raw Selenium, error messages can get very messy.

    \ud83d\udca1 SeleniumBase gives you the option to generate a dashboard and reports for tests. It also saves screenshots from failing tests to the ./latest_logs/ folder. Raw Selenium does not have these options out-of-the-box.

    \ud83d\udca1 SeleniumBase includes desktop GUI apps for running tests, such as SeleniumBase Commander for pytest and SeleniumBase Behave GUI for behave.

    \ud83d\udca1 SeleniumBase has its own Recorder / Test Generator that can create tests from manual browser actions. SeleniumBase also includes other useful tools and console scripts for getting things done quickly. (See the documentation for more details!)

    \u25b6\ufe0f Learn about different ways of writing tests (click to expand)

    \ud83d\udcd8\ud83d\udcdd An example test with the BaseCase class. Runs with pytest or pynose. (Learn more)

    from seleniumbase import BaseCase\nBaseCase.main(__name__, __file__)\n\nclass TestMFALogin(BaseCase):\n    def test_mfa_login(self):\n        self.open(\"https://seleniumbase.io/realworld/login\")\n        self.type(\"#username\", \"demo_user\")\n        self.type(\"#password\", \"secret_pass\")\n        self.enter_mfa_code(\"#totpcode\", \"GAXG2MTEOR3DMMDG\")  # 6-digit\n        self.assert_exact_text(\"Welcome!\", \"h1\")\n        self.assert_element(\"img#image1\")\n        self.click('a:contains(\"This Page\")')\n        self.save_screenshot_to_logs()\n

    \ud83d\udcd7\ud83d\udcdd An example test with the sb pytest fixture. Runs with pytest.

    def test_mfa_login(sb):\n    sb.open(\"https://seleniumbase.io/realworld/login\")\n    sb.type(\"#username\", \"demo_user\")\n    sb.type(\"#password\", \"secret_pass\")\n    sb.enter_mfa_code(\"#totpcode\", \"GAXG2MTEOR3DMMDG\")  # 6-digit\n    sb.assert_exact_text(\"Welcome!\", \"h1\")\n    sb.assert_element(\"img#image1\")\n    sb.click('a:contains(\"This Page\")')\n    sb.save_screenshot_to_logs()\n

    \ud83d\udcd9\ud83d\udcdd An example test with the SB Context Manager. Runs with pure python.

    from seleniumbase import SB\n\nwith SB() as sb:  # By default, browser=\"chrome\" if not set.\n    sb.open(\"https://seleniumbase.io/realworld/login\")\n    sb.type(\"#username\", \"demo_user\")\n    sb.type(\"#password\", \"secret_pass\")\n    sb.enter_mfa_code(\"#totpcode\", \"GAXG2MTEOR3DMMDG\")  # 6-digit\n    sb.assert_text(\"Welcome!\", \"h1\")\n    sb.highlight(\"img#image1\")  # A fancier assert_element() call\n    sb.click('a:contains(\"This Page\")')  # Use :contains() on any tag\n    sb.click_link(\"Sign out\")  # Link must be \"a\" tag. Not \"button\".\n    sb.assert_element('a:contains(\"Sign in\")')\n    sb.assert_exact_text(\"You have been signed out!\", \"#top_message\")\n

    \ud83d\udcd5\ud83d\udcdd An example test with behave-BDD Gherkin structure. Runs with behave. (Learn more)

    Feature: SeleniumBase scenarios for the RealWorld App\n\nScenario: Verify RealWorld App\n    Given Open \"seleniumbase.io/realworld/login\"\nWhen Type \"demo_user\" into \"#username\"\nAnd Type \"secret_pass\" into \"#password\"\nAnd Do MFA \"GAXG2MTEOR3DMMDG\" into \"#totpcode\"\nThen Assert exact text \"Welcome!\" in \"h1\"\nAnd Assert element \"img#image1\"\nAnd Click 'a:contains(\"This Page\")'\nAnd Save screenshot to logs\n

    Set up Python & Git:

    \ud83d\udd35 Add Python and Git to your System PATH.

    \ud83d\udd35 Using a Python virtual env is recommended.

    Install SeleniumBase:

    You can install seleniumbase from PyPI or GitHub:

    \ud83d\udd35 How to install seleniumbase from PyPI:

    pip install seleniumbase\n

    \ud83d\udd35 How to install seleniumbase from a GitHub clone:

    git clone https://github.com/seleniumbase/SeleniumBase.git\ncd SeleniumBase/\npip install -e .\n

    \ud83d\udd35 How to upgrade an existing install from a GitHub clone:

    git pull\npip install -e .\n

    \ud83d\udd35 Type seleniumbase or sbase to verify that SeleniumBase was installed successfully:

       ______     __           _                  ____                / ____/__  / /__  ____  (_)_  ______ ___   / _  \\____  ________ \\__ \\/ _ \\/ / _ \\/ __ \\/ / / / / __ `__ \\ / /_) / __ \\/ ___/ _ \\\n___/ /  __/ /  __/ / / / / /_/ / / / / / // /_) / (_/ /__  /  __/\n/____/\\___/_/\\___/_/ /_/_/\\__,_/_/ /_/ /_//_____/\\__,_/____/\\___/ \n------------------------------------------------------------------\n\n * USAGE: \"seleniumbase [COMMAND] [PARAMETERS]\"\n*    OR:        \"sbase [COMMAND] [PARAMETERS]\"\n\nCOMMANDS:\n      get / install    [DRIVER] [OPTIONS]\nmethods          (List common Python methods)\noptions          (List common pytest options)\nbehave-options   (List common behave options)\ngui / commander  [OPTIONAL PATH or TEST FILE]\nbehave-gui       (SBase Commander for Behave)\ncaseplans        [OPTIONAL PATH or TEST FILE]\nmkdir            [DIRECTORY] [OPTIONS]\nmkfile           [FILE.py] [OPTIONS]\nmkrec / codegen  [FILE.py] [OPTIONS]\nrecorder         (Open Recorder Desktop App.)\nrecord           (If args: mkrec. Else: App.)\nmkpres           [FILE.py] [LANG]\nmkchart          [FILE.py] [LANG]\nprint            [FILE] [OPTIONS]\ntranslate        [SB_FILE.py] [LANG] [ACTION]\nconvert          [WEBDRIVER_UNITTEST_FILE.py]\nextract-objects  [SB_FILE.py]\ninject-objects   [SB_FILE.py] [OPTIONS]\nobjectify        [SB_FILE.py] [OPTIONS]\nrevert-objects   [SB_FILE.py] [OPTIONS]\nencrypt / obfuscate\n      decrypt / unobfuscate\n      download server  (Get Selenium Grid JAR file)\ngrid-hub         [start|stop] [OPTIONS]\ngrid-node        [start|stop] --hub=[HOST/IP]\n* (EXAMPLE: \"sbase get chromedriver latest\") *\n\n    Type \"sbase help [COMMAND]\" for specific command info.\n    For info on all commands, type: \"seleniumbase --help\".\n    Use \"pytest\" for running tests.\n
    \ud83d\udd35 Downloading webdrivers:

    \u2705 SeleniumBase automatically downloads webdrivers as needed, such as chromedriver.

    \u25b6\ufe0f Here's output from a chromedriver download. (click to expand)
    *** chromedriver version for download = 114.0.5735.90 (Latest)\n\nDownloading chromedriver_mac_arm64.zip from:\nhttps://chromedriver.storage.googleapis.com/114.0.5735.90/chromedriver_mac_arm64.zip ...\nDownload Complete!\n\nExtracting ['chromedriver'] from chromedriver_mac_arm64.zip ...\nUnzip Complete!\n\nThe file [chromedriver] was saved to:\n/Users/michael/github/SeleniumBase/seleniumbase/drivers/chromedriver\n\nMaking [chromedriver 114.0.5735.90] executable ...\n[chromedriver 114.0.5735.90] is now ready for use!\n

    Basic Example / Usage:

    \ud83d\udd35 If you've cloned SeleniumBase, you can run tests from the examples/ folder.

    Here's my_first_test.py:

    cd examples/\npytest my_first_test.py\n

    (Uses --chrome by default.)

    SeleniumBase easily handles login, shopping, and checkout.

    Here's the code for my_first_test.py:

    from seleniumbase import BaseCase\nBaseCase.main(__name__, __file__)\n\nclass MyTestClass(BaseCase):\n    def test_swag_labs(self):\n        self.open(\"https://www.saucedemo.com\")\n        self.type(\"#user-name\", \"standard_user\")\n        self.type(\"#password\", \"secret_sauce\\n\")\n        self.assert_element(\"div.inventory_list\")\n        self.assert_exact_text(\"Products\", \"span.title\")\n        self.click('button[name*=\"backpack\"]')\n        self.click(\"#shopping_cart_container a\")\n        self.assert_exact_text(\"Your Cart\", \"span.title\")\n        self.assert_text(\"Backpack\", \"div.cart_item\")\n        self.click(\"button#checkout\")\n        self.type(\"#first-name\", \"SeleniumBase\")\n        self.type(\"#last-name\", \"Automation\")\n        self.type(\"#postal-code\", \"77123\")\n        self.click(\"input#continue\")\n        self.assert_text(\"Checkout: Overview\")\n        self.assert_text(\"Backpack\", \"div.cart_item\")\n        self.assert_text(\"29.99\", \"div.inventory_item_price\")\n        self.click(\"button#finish\")\n        self.assert_exact_text(\"Thank you for your order!\", \"h2\")\n        self.assert_element('img[alt=\"Pony Express\"]')\n        self.js_click(\"a#logout_sidebar_link\")\n        self.assert_element(\"div#login_button_container\")\n

    Here are some common SeleniumBase methods:
    self.open(url)  # Navigate the browser window to the URL.\nself.type(selector, text)  # Update the field with the text.\nself.click(selector)  # Click the element with the selector.\nself.click_link(link_text)  # Click the link containing text.\nself.go_back()  # Navigate back to the previous URL.\nself.select_option_by_text(dropdown_selector, option)\nself.hover_and_click(hover_selector, click_selector)\nself.drag_and_drop(drag_selector, drop_selector)\nself.get_text(selector)  # Get the text from the element.\nself.get_current_url()  # Get the URL of the current page.\nself.get_page_source()  # Get the HTML of the current page.\nself.get_attribute(selector, attribute)  # Get element attribute.\nself.get_title()  # Get the title of the current page.\nself.switch_to_frame(frame)  # Switch into the iframe container.\nself.switch_to_default_content()  # Leave the iframe container.\nself.open_new_window()  # Open a new window in the same browser.\nself.switch_to_window(window)  # Switch to the browser window.\nself.switch_to_default_window()  # Switch to the original window.\nself.get_new_driver(OPTIONS)  # Open a new driver with OPTIONS.\nself.switch_to_driver(driver)  # Switch to the browser driver.\nself.switch_to_default_driver()  # Switch to the original driver.\nself.wait_for_element(selector)  # Wait until element is visible.\nself.is_element_visible(selector)  # Return element visibility.\nself.is_text_visible(text, selector)  # Return text visibility.\nself.sleep(seconds)  # Do nothing for the given amount of time.\nself.save_screenshot(name)  # Save a screenshot in .png format.\nself.assert_element(selector)  # Verify the element is visible.\nself.assert_text(text, selector)  # Verify text in the element.\nself.assert_exact_text(text, selector)  # Verify text is exact.\nself.assert_title(title)  # Verify the title of the web page.\nself.assert_downloaded_file(file)  # Verify file was downloaded.\nself.assert_no_404_errors()  # Verify there are no broken links.\nself.assert_no_js_errors()  # Verify there are no JS errors.\n

    \ud83d\udd35 For the complete list of SeleniumBase methods, see: Method Summary

    Fun Facts / Learn More:

    \u2705 SeleniumBase automatically handles common WebDriver actions such as launching web browsers before tests, saving screenshots during failures, and closing web browsers after tests.

    \u2705 SeleniumBase lets you customize test runs from the command-line.

    \u2705 SeleniumBase uses simple syntax for commands. Example:

    self.type(\"input\", \"dogs\\n\")  # (The \"\\n\" presses ENTER)\n

    Most SeleniumBase scripts can be run with pytest, pynose, or pure python. 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 Syntax Formats) There's also a Gherkin test format that runs with behave.

    pytest coffee_cart_tests.py --rs\npytest test_sb_fixture.py --demo\npytest test_suite.py --rs --html=report.html --dashboard\n\npynose basic_test.py --mobile\npynose test_suite.py --headless --report --show-report\n\npython raw_sb.py\npython raw_test_scripts.py\n\nbehave realworld.feature\nbehave calculator.feature -D rs -D dashboard\n

    \u2705 pytest includes automatic test discovery. If you don't specify a specific file or folder to run, pytest will automatically search through all subdirectories for tests to run based on the following criteria:

    With a SeleniumBase 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.

    \u2705 You can do a pre-flight check to see which tests would get discovered by pytest before the actual run:

    pytest --co -q\n

    \u2705 You can be more specific when calling pytest or pynose on a file:

    pytest [FILE_NAME.py]::[CLASS_NAME]::[METHOD_NAME]\n\npynose [FILE_NAME.py]:[CLASS_NAME].[METHOD_NAME]\n

    \u2705 No More Flaky Tests! SeleniumBase methods automatically wait for page elements to finish loading before interacting with them (up to a timeout limit). This means you no longer need random time.sleep() statements in your scripts.

    \u2705 SeleniumBase supports all major browsers and operating systems:

    Browsers: Chrome, Edge, Firefox, and Safari.

    Systems: Linux/Ubuntu, macOS, and Windows.

    \u2705 SeleniumBase works on all popular CI/CD platforms:

    \u2705 SeleniumBase includes an automated/manual hybrid solution called MasterQA to speed up manual testing with automation while manual testers handle validation.

    \u2705 SeleniumBase supports running tests while offline (assuming webdrivers have previously been downloaded when online).

    \u2705 For a full list of SeleniumBase features, Click Here.

    Demo Mode / Debugging:

    \ud83d\udd35 Demo Mode helps you see what a test is doing. If a test is moving too fast for your eyes, run it in Demo Mode to pause the browser briefly between actions, highlight page elements being acted on, and display assertions:

    pytest my_first_test.py --demo\n

    \ud83d\udd35 time.sleep(seconds) can be used to make a test wait at a specific spot:

    import time; time.sleep(3)  # Do nothing for 3 seconds.\n

    \ud83d\udd35 Debug Mode with Python's built-in pdb library helps you debug tests:

    import pdb; pdb.set_trace()\nimport pytest; pytest.set_trace()\nbreakpoint()  # Shortcut for \"import pdb; pdb.set_trace()\"\n

    (pdb commands: n, c, s, u, d => next, continue, step, up, down)

    \ud83d\udd35 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:

    pytest test_fail.py --pdb\n

    \ud83d\udd35 To start tests in Debug Mode, add --trace as a pytest option:

    pytest test_coffee_cart.py --trace\n

    \ud83d\udd35 Command-line Options:

    \u2705 Here are some useful command-line options that come with pytest:

    -v  # Verbose mode. Prints the full name of each test and shows more details.\n-q  # Quiet mode. Print fewer details in the console output when running tests.\n-x  # Stop running the tests after the first failure is reached.\n--html=report.html  # Creates a detailed pytest-html report after tests finish.\n--co | --collect-only  # Show what tests would get run. (Without running them)\n--co -q  # (Both options together!) - Do a dry run with full test names shown.\n-n=NUM  # Multithread the tests using that many threads. (Speed up test runs!)\n-s  # See print statements. (Should be on by default with pytest.ini present.)\n--junit-xml=report.xml  # Creates a junit-xml report after tests finish.\n--pdb  # If a test fails, enter Post Mortem Debug Mode. (Don't use with CI!)\n--trace  # Enter Debug Mode at the beginning of each test. (Don't use with CI!)\n-m=MARKER  # Run tests with the specified pytest marker.\n

    \u2705 SeleniumBase provides additional pytest command-line options for tests:

    --browser=BROWSER  # (The web browser to use. Default: \"chrome\".)\n--chrome  # (Shortcut for \"--browser=chrome\". On by default.)\n--edge  # (Shortcut for \"--browser=edge\".)\n--firefox  # (Shortcut for \"--browser=firefox\".)\n--safari  # (Shortcut for \"--browser=safari\".)\n--settings-file=FILE  # (Override default SeleniumBase settings.)\n--env=ENV  # (Set the test env. Access with \"self.env\" in tests.)\n--account=STR  # (Set account. Access with \"self.account\" in tests.)\n--data=STRING  # (Extra test data. Access with \"self.data\" in tests.)\n--var1=STRING  # (Extra test data. Access with \"self.var1\" in tests.)\n--var2=STRING  # (Extra test data. Access with \"self.var2\" in tests.)\n--var3=STRING  # (Extra test data. Access with \"self.var3\" in tests.)\n--variables=DICT  # (Extra test data. Access with \"self.variables\".)\n--user-data-dir=DIR  # (Set the Chrome user data directory to use.)\n--protocol=PROTOCOL  # (The Selenium Grid protocol: http|https.)\n--server=SERVER  # (The Selenium Grid server/IP used for tests.)\n--port=PORT  # (The Selenium Grid port used by the test server.)\n--cap-file=FILE  # (The web browser's desired capabilities to use.)\n--cap-string=STRING  # (The web browser's desired capabilities to use.)\n--proxy=SERVER:PORT  # (Connect to a proxy server:port as tests are running)\n--proxy=USERNAME:PASSWORD@SERVER:PORT  # (Use an authenticated proxy server)\n--proxy-bypass-list=STRING # (\";\"-separated hosts to bypass, Eg \"*.foo.com\")\n--proxy-pac-url=URL  # (Connect to a proxy server using a PAC_URL.pac file.)\n--proxy-pac-url=USERNAME:PASSWORD@URL  # (Authenticated proxy with PAC URL.)\n--proxy-driver  # (If a driver download is needed, will use: --proxy=PROXY.)\n--multi-proxy  # (Allow multiple authenticated proxies when multi-threaded.)\n--agent=STRING  # (Modify the web browser's User-Agent string.)\n--mobile  # (Use the mobile device emulator while running tests.)\n--metrics=STRING  # (Set mobile metrics: \"CSSWidth,CSSHeight,PixelRatio\".)\n--chromium-arg=\"ARG=N,ARG2\"  # (Set Chromium args, \",\"-separated, no spaces.)\n--firefox-arg=\"ARG=N,ARG2\"  # (Set Firefox args, comma-separated, no spaces.)\n--firefox-pref=SET  # (Set a Firefox preference:value set, comma-separated.)\n--extension-zip=ZIP  # (Load a Chrome Extension .zip|.crx, comma-separated.)\n--extension-dir=DIR  # (Load a Chrome Extension directory, comma-separated.)\n--binary-location=PATH  # (Set path of the Chromium browser binary to use.)\n--driver-version=VER  # (Set the chromedriver or uc_driver version to use.)\n--sjw  # (Skip JS Waits for readyState to be \"complete\" or Angular to load.)\n--pls=PLS  # (Set pageLoadStrategy on Chrome: \"normal\", \"eager\", or \"none\".)\n--headless  # (Run tests in headless mode. The default arg on Linux OS.)\n--headless2  # (Use the new headless mode, which supports extensions.)\n--headed  # (Run tests in headed/GUI mode on Linux OS, where not default.)\n--xvfb  # (Run tests using the Xvfb virtual display server on Linux OS.)\n--locale=LOCALE_CODE  # (Set the Language Locale Code for the web browser.)\n--interval=SECONDS  # (The autoplay interval for presentations & tour steps)\n--start-page=URL  # (The starting URL for the web browser when tests begin.)\n--archive-logs  # (Archive existing log files instead of deleting them.)\n--archive-downloads  # (Archive old downloads instead of deleting them.)\n--time-limit=SECONDS  # (Safely fail any test that exceeds the time limit.)\n--slow  # (Slow down the automation. Faster than using Demo Mode.)\n--demo  # (Slow down and visually see test actions as they occur.)\n--demo-sleep=SECONDS  # (Set the wait time after Slow & Demo Mode actions.)\n--highlights=NUM  # (Number of highlight animations for Demo Mode actions.)\n--message-duration=SECONDS  # (The time length for Messenger alerts.)\n--check-js  # (Check for JavaScript errors after page loads.)\n--ad-block  # (Block some types of display ads from loading.)\n--block-images  # (Block images from loading during tests.)\n--do-not-track  # (Indicate to websites that you don't want to be tracked.)\n--verify-delay=SECONDS  # (The delay before MasterQA verification checks.)\n--recorder  # (Enables the Recorder for turning browser actions into code.)\n--rec-behave  # (Same as Recorder Mode, but also generates behave-gherkin.)\n--rec-sleep  # (If the Recorder is enabled, also records self.sleep calls.)\n--rec-print  # (If the Recorder is enabled, prints output after tests end.)\n--disable-js  # (Disable JavaScript on websites. Pages might break!)\n--disable-csp  # (Disable the Content Security Policy of websites.)\n--disable-ws  # (Disable Web Security on Chromium-based browsers.)\n--enable-ws  # (Enable Web Security on Chromium-based browsers.)\n--enable-sync  # (Enable \"Chrome Sync\" on websites.)\n--uc | --undetected  # (Use undetected-chromedriver to evade bot-detection.)\n--uc-cdp-events  # (Capture CDP events when running in \"--undetected\" mode.)\n--remote-debug  # (Sync to Chrome Remote Debugger chrome://inspect/#devices)\n--final-debug  # (Enter Debug Mode after each test ends. Don't use with CI!)\n--dashboard  # (Enable the SeleniumBase Dashboard. Saved at: dashboard.html)\n--dash-title=STRING  # (Set the title shown for the generated dashboard.)\n--enable-3d-apis  # (Enables WebGL and 3D APIs.)\n--swiftshader  # (Use Chrome's \"--use-gl=swiftshader\" feature.)\n--incognito  # (Enable Chrome's Incognito mode.)\n--guest  # (Enable Chrome's Guest mode.)\n--dark  # (Enable Chrome's Dark mode.)\n--devtools  # (Open Chrome's DevTools when the browser opens.)\n--rs | --reuse-session  # (Reuse browser session for all tests.)\n--rcs | --reuse-class-session  # (Reuse session for tests in class.)\n--crumbs  # (Delete all cookies between tests reusing a session.)\n--disable-beforeunload  # (Disable the \"beforeunload\" event on Chrome.)\n--window-size=WIDTH,HEIGHT  # (Set the browser's starting window size.)\n--maximize  # (Start tests with the browser window maximized.)\n--screenshot  # (Save a screenshot at the end of each test.)\n--no-screenshot  # (No screenshots saved unless tests directly ask it.)\n--visual-baseline  # (Set the visual baseline for Visual/Layout tests.)\n--wire  # (Use selenium-wire's webdriver for replacing selenium webdriver.)\n--external-pdf  # (Set Chromium \"plugins.always_open_pdf_externally\":True.)\n--timeout-multiplier=MULTIPLIER  # (Multiplies the default timeout values.)\n--list-fail-page  # (After each failing test, list the URL of the failure.)\n

    (See the full list of command-line option definitions here. For detailed examples of command-line options, see customizing_test_runs.md)

    \ud83d\udd35 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, 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.

    cd examples/\n\npytest test_suite.py --chrome\n\npytest test_suite.py --firefox\n

    An easy way to override seleniumbase/config/settings.py is by using a custom settings file. Here's the command-line option to add to tests: (See examples/custom_settings.py) --settings_file=custom_settings.py (Settings include default timeout values, a two-factor auth key, DB credentials, S3 credentials, and other important settings used by tests.)

    \ud83d\udd35 To pass additional data from the command-line to tests, add --data=\"ANY STRING\". Inside your tests, you can use self.data to access that.

    Directory Configuration:

    \ud83d\udd35 When running tests with pytest, you'll want a copy of pytest.ini in your root folders. When running tests with pynose, you'll want a copy of setup.cfg in your root folders. These files specify default configuration details for tests. Test folders should also include a blank init.py file to allow your test files to import other files from that folder.

    \ud83d\udd35 sbase mkdir DIR creates a folder with config files and sample tests:

    sbase mkdir ui_tests\n

    That new folder will have these files:

    ui_tests/\n\u251c\u2500\u2500 __init__.py\n\u251c\u2500\u2500 my_first_test.py\n\u251c\u2500\u2500 parameterized_test.py\n\u251c\u2500\u2500 pytest.ini\n\u251c\u2500\u2500 requirements.txt\n\u251c\u2500\u2500 setup.cfg\n\u251c\u2500\u2500 test_demo_site.py\n\u2514\u2500\u2500 boilerplates/\n    \u251c\u2500\u2500 __init__.py\n    \u251c\u2500\u2500 base_test_case.py\n    \u251c\u2500\u2500 boilerplate_test.py\n    \u251c\u2500\u2500 classic_obj_test.py\n    \u251c\u2500\u2500 page_objects.py\n    \u251c\u2500\u2500 sb_fixture_test.py\n    \u2514\u2500\u2500 samples/\n        \u251c\u2500\u2500 __init__.py\n        \u251c\u2500\u2500 google_objects.py\n        \u251c\u2500\u2500 google_test.py\n        \u251c\u2500\u2500 sb_swag_test.py\n        \u2514\u2500\u2500 swag_labs_test.py\n

    ProTip\u2122: You can also create a boilerplate folder without any sample tests in it by adding -b or --basic to the sbase mkdir command:

    sbase mkdir ui_tests --basic\n

    That new folder will have these files:

    ui_tests/\n\u251c\u2500\u2500 __init__.py\n\u251c\u2500\u2500 pytest.ini\n\u251c\u2500\u2500 requirements.txt\n\u2514\u2500\u2500 setup.cfg\n

    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).

    Log files from failed tests:

    Let's try an example of a test that fails:

    \"\"\" test_fail.py \"\"\"\nfrom seleniumbase import BaseCase\nBaseCase.main(__name__, __file__)\n\nclass MyTestClass(BaseCase):\n\n    def test_find_army_of_robots_on_xkcd_desert_island(self):\n        self.open(\"https://xkcd.com/731/\")\n        self.assert_element(\"div#ARMY_OF_ROBOTS\", timeout=1)  # This should fail\n

    You can run it from the examples/ folder like this:

    pytest test_fail.py\n

    \ud83d\udd35 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, 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.

    SeleniumBase Dashboard:

    \ud83d\udd35 The --dashboard option for pytest generates a SeleniumBase Dashboard located at dashboard.html, which updates automatically as tests run and produce results. Example:

    pytest --dashboard --rs --headless\n

    \ud83d\udd35 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:

    python -m http.server 1948\n

    \ud83d\udd35 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.)

    \ud83d\udd35 Here's a full example of what the SeleniumBase Dashboard may look like:

    pytest test_suite.py --dashboard --rs --headless\n

    Generating Test Reports: \ud83d\udd35 Pytest Reports:

    \u2705 Using --html=report.html gives you a fancy report of the name specified after your test suite completes.

    pytest test_suite.py --html=report.html\n

    \u2705 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.

    \u2705 Here's an example of an upgraded html report:

    pytest test_suite.py --dashboard --html=report.html\n

    If viewing pytest html reports in Jenkins, you may need to configure Jenkins settings for the html to render correctly. This is due to Jenkins CSP changes.

    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.

    pytest test_suite.py --junit-xml=report.xml\n
    \ud83d\udd35 pynose Reports:

    The --report option gives you a fancy report after your test suite completes.

    pynose test_suite.py --report\n

    (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.)

    \ud83d\udd35 Behave Dashboard & Reports: (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.)
    behave behave_bdd/features/ -D dashboard -D headless\n
    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.
    behave behave_bdd/features/ --junit -D rs -D headless\n
    \ud83d\udd35 Allure Reports: See: [https://docs.qameta.io/allure/](https://docs.qameta.io/allure/#_pytest) SeleniumBase no longer includes ``allure-pytest`` as part of installed dependencies. If you want to use it, install it first:
    pip install allure-pytest\n
    Now your tests can create Allure results files, which can be processed by Allure Reports.
    pytest test_suite.py --alluredir=allure_results\n
    -------- Using a Proxy Server: If you wish to use a proxy server for your browser tests (Chromium or Firefox), you can add ``--proxy=IP_ADDRESS:PORT`` as an argument on the command line.
    pytest proxy_test.py --proxy=IP_ADDRESS:PORT\n
    If the proxy server that you wish to use requires authentication, you can do the following (Chromium only):
    pytest proxy_test.py --proxy=USERNAME:PASSWORD@IP_ADDRESS:PORT\n
    SeleniumBase also supports SOCKS4 and SOCKS5 proxies:
    pytest proxy_test.py --proxy=\"socks4://IP_ADDRESS:PORT\"\n\npytest proxy_test.py --proxy=\"socks5://IP_ADDRESS:PORT\"\n
    To make things easier, you can add your frequently-used proxies to PROXY_LIST in [proxy_list.py](https://github.com/seleniumbase/SeleniumBase/blob/master/seleniumbase/config/proxy_list.py), and then use ``--proxy=KEY_FROM_PROXY_LIST`` to use the IP_ADDRESS:PORT of that key.
    pytest proxy_test.py --proxy=proxy1\n
    Changing the User-Agent: \ud83d\udd35 If you wish to change the User-Agent for your browser tests (Chromium and Firefox only), you can add ``--agent=\"USER AGENT STRING\"`` as an argument on the command-line.
    pytest user_agent_test.py --agent=\"Mozilla/5.0 (Nintendo 3DS; U; ; en) Version/1.7412.EU\"\n
    Handling Pop-Up / Pop Up Alerts: \ud83d\udd35 self.accept_alert() automatically waits for and accepts alert pop-ups. self.dismiss_alert() automatically waits for and dismisses alert pop-ups. On occasion, some methods like self.click(SELECTOR) might dismiss a pop-up on its own because they call JavaScript to make sure that the readyState of the page is complete before advancing. If you're trying to accept a pop-up that got dismissed this way, use this workaround: Call self.find_element(SELECTOR).click() instead, (which will let the pop-up remain on the screen), and then use self.accept_alert() to accept the pop-up (more on that here). If pop-ups are intermittent, wrap code in a try/except block. Building Guided Tours for Websites: \ud83d\udd35 Learn about SeleniumBase Interactive Walkthroughs (in the ``examples/tour_examples/`` folder). It's great for prototyping a website onboarding experience. -------- Production Environments & Integrations: \u25b6\ufe0f Here are some things you can do to set up a production environment for your testing. (click to expand) Here's an example of running tests with some additional features enabled:
    pytest [YOUR_TEST_FILE.py] --with-db-reporting --with-s3-logging\n
    Detailed Method Specifications and Examples: \ud83d\udd35 **Navigating to a web page: (and related commands)**
    self.open(\"https://xkcd.com/378/\")  # This method opens the specified page.\n\nself.go_back()  # This method navigates the browser to the previous page.\n\nself.go_forward()  # This method navigates the browser forward in history.\n\nself.refresh_page()  # This method reloads the current page.\n\nself.get_current_url()  # This method returns the current page URL.\n\nself.get_page_source()  # This method returns the current page source.\n
    ProTip\u2122: You can use the self.get_page_source() method with Python's find() command to parse through HTML to find something specific. (For more advanced parsing, see the BeautifulSoup example.)
    source = self.get_page_source()\nhead_open_tag = source.find('<head>')\nhead_close_tag = source.find('</head>', head_open_tag)\neverything_inside_head = source[head_open_tag+len('<head>'):head_close_tag]\n
    \ud83d\udd35 **Clicking:** To click an element on the page:
    self.click(\"div#my_id\")\n
    **ProTip\u2122:** 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. \ud83d\udd35 **Typing Text:** self.type(selector, text) # 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:
    self.type(\"input#id_value\", \"2012\")\n
    You can also use self.add_text() or the WebDriver .send_keys() command, but those won't clear the text box first if there's already text inside. \ud83d\udd35 **Getting the text from an element on a page:**
    text = self.get_text(\"header h2\")\n
    \ud83d\udd35 **Getting the attribute value from an element on a page:**
    attribute = self.get_attribute(\"#comic img\", \"title\")\n
    \ud83d\udd35 **Asserting existence of an element on a page within some number of seconds:**
    self.wait_for_element_present(\"div.my_class\", timeout=10)\n
    (NOTE: You can also use: ``self.assert_element_present(ELEMENT)``) \ud83d\udd35 **Asserting visibility of an element on a page within some number of seconds:**
    self.wait_for_element_visible(\"a.my_class\", timeout=5)\n
    (NOTE: The short versions of that are ``self.find_element(ELEMENT)`` and ``self.assert_element(ELEMENT)``. The ``find_element()`` version returns the element.) Since the line above returns the element, you can combine that with ``.click()`` as shown below:
    self.find_element(\"a.my_class\", timeout=5).click()\n\n# But you're better off using the following statement, which does the same thing\nself.click(\"a.my_class\")  # DO IT THIS WAY!\n
    **ProTip\u2122:** You can use dots to signify class names (Ex: ``div.class_name``) as a simplified version of ``div[class=\"class_name\"]`` within a CSS selector. You can also use ``*=`` to search for any partial value in a CSS selector as shown below:
    self.click('a[name*=\"partial_name\"]')\n
    \ud83d\udd35 **Asserting visibility of text inside an element on a page within some number of seconds:**
    self.assert_text(\"Make it so!\", \"div#trek div.picard div.quotes\")\nself.assert_text(\"Tea. Earl Grey. Hot.\", \"div#trek div.picard div.quotes\", timeout=3)\n
    (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.) \ud83d\udd35 **Asserting Anything:**
    self.assert_true(var1 == var2)\n\nself.assert_false(var1 == var2)\n\nself.assert_equal(var1, var2)\n
    \ud83d\udd35 **Useful Conditional Statements: (with creative examples)** \u2753 ``is_element_visible(selector):`` (visible on the page)
    if self.is_element_visible('div#warning'):\n    print(\"Red Alert: Something bad might be happening!\")\n
    \u2753 ``is_element_present(selector):`` (present in the HTML)
    if self.is_element_present('div#top_secret img.tracking_cookie'):\n    self.contact_cookie_monster()  # Not a real SeleniumBase method\nelse:\n    current_url = self.get_current_url()\n    self.contact_the_nsa(url=current_url, message=\"Dark Zone Found\")  # Not a real SeleniumBase method\n
    def is_there_a_cloaked_klingon_ship_on_this_page():\n    if self.is_element_present(\"div.ships div.klingon\"):\n        return not self.is_element_visible(\"div.ships div.klingon\")\n    return False\n
    \u2753 ``is_text_visible(text, selector):`` (text visible on element)
    if self.is_text_visible(\"You Shall Not Pass!\", \"h1\"):\n    self.open(\"https://www.youtube.com/watch?v=3xYXUeSmb-Y\")\n
    \u25b6\ufe0f Click for a longer example of is_text_visible():
    def get_mirror_universe_captain_picard_superbowl_ad(superbowl_year):\n    selector = \"div.superbowl_%s div.commercials div.transcript div.picard\" % superbowl_year\n    if self.is_text_visible(\"Yes, it was I who summoned you all here.\", selector):\n        return \"Picard Paramount+ Superbowl Ad 2020\"\n    elif self.is_text_visible(\"Commander, signal the following: Our Network is Secure!\"):\n        return \"Picard Mirror Universe iboss Superbowl Ad 2018\"\n    elif self.is_text_visible(\"For the Love of Marketing and Earl Grey Tea!\", selector):\n        return \"Picard Mirror Universe HubSpot Superbowl Ad 2015\"\n    elif self.is_text_visible(\"Delivery Drones... Engage\", selector):\n        return \"Picard Mirror Universe Amazon Superbowl Ad 2015\"\n    elif self.is_text_visible(\"Bing it on Screen!\", selector):\n        return \"Picard Mirror Universe Microsoft Superbowl Ad 2015\"\n    elif self.is_text_visible(\"OK Glass, Make it So!\", selector):\n        return \"Picard Mirror Universe Google Superbowl Ad 2015\"\n    elif self.is_text_visible(\"Number One, I've Never Seen Anything Like It.\", selector):\n        return \"Picard Mirror Universe Tesla Superbowl Ad 2015\"\n    elif self.is_text_visible(\"Let us make sure history never forgets the name ... Facebook\", selector):\n        return \"Picard Mirror Universe Facebook Superbowl Ad 2015\"\n    elif self.is_text_visible(\"\"\"With the first link, the chain is forged.\n                              The first speech censored, the first thought forbidden,\n                              the first freedom denied, chains us all irrevocably.\"\"\", selector):\n        return \"Picard Mirror Universe Wikimedia Superbowl Ad 2015\"\n    else:\n        raise Exception(\"Reports of my assimilation are greatly exaggerated.\")\n
    \u2753 ``is_link_text_visible(link_text):``
    if self.is_link_text_visible(\"Stop! Hammer time!\"):\n    self.click_link(\"Stop! Hammer time!\")\n
    \ud83d\udd35 Switching Tabs:

    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 about:blank URLs.)

    self.switch_to_window(1)  # This switches to the new tab (0 is the first one)\n
    \ud83d\udd35 How to handle iframes: \ud83d\udd35 iframes follow the same principle as new windows: You must first switch to the iframe if you want to perform actions in there:
    self.switch_to_frame(\"iframe\")\n# ... Now perform actions inside the iframe\nself.switch_to_parent_frame()  # Exit the current iframe\n
    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()``.)
    self.switch_to_frame('iframe[name=\"frame1\"]')\nself.switch_to_frame('iframe[name=\"frame2\"]')\n# ... Now perform actions inside the inner iframe\nself.switch_to_default_content()  # Back to the main page\n
    \ud83d\udd35 You can also use a context manager to act inside iframes:
    with self.frame_switch(\"iframe\"):\n    # ... Now perform actions while inside the code block\n# You have left the iframe\n
    This also works with nested iframes:
    with self.frame_switch('iframe[name=\"frame1\"]'):\n    with self.frame_switch('iframe[name=\"frame2\"]'):\n        # ... Now perform actions while inside the code block\n    # You are now back inside the first iframe\n# You have left all the iframes\n
    \ud83d\udd35 How to execute custom jQuery scripts:

    jQuery is a powerful JavaScript library that allows you to perform advanced actions in a web browser. If the web page you're on already has jQuery loaded, you can start executing jQuery scripts immediately. You'd know this because the web page would contain something like the following in the HTML:

    <script src=\"https://ajax.googleapis.com/ajax/libs/jquery/3.6.3/jquery.min.js\"></script>\n
    \ud83d\udd35 It's OK if you want to use jQuery on a page that doesn't have it loaded yet. To do so, run the following command first:
    self.activate_jquery()\n
    \u25b6\ufe0f Here are some examples of using jQuery in your scripts. (click to expand)
    self.execute_script(\"jQuery, window.scrollTo(0, 600)\")  # Scrolling the page\n\nself.execute_script(\"jQuery('#annoying-widget').hide()\")  # Hiding elements on a page\n\nself.execute_script(\"jQuery('#hidden-widget').show(0)\")  # Showing hidden elements on a page\n\nself.execute_script(\"jQuery('#annoying-button a').remove()\")  # Removing elements on a page\n\nself.execute_script(\"jQuery('%s').mouseover()\" % (mouse_over_item))  # Mouse-over elements on a page\n\nself.execute_script(\"jQuery('input#the_id').val('my_text')\")  # Fast text input on a page\n\nself.execute_script(\"jQuery('div#dropdown a.link').click()\")  # Click elements on a page\n\nself.execute_script(\"return jQuery('div#amazing')[0].text\")  # Returns the css \"text\" of the element given\n\nself.execute_script(\"return jQuery('textarea')[2].value\")  # Returns the css \"value\" of the 3rd textarea element on the page\n
    (Most of the above commands can be done directly with built-in SeleniumBase methods.) \ud83d\udd35 How to handle a restrictive CSP: \u2757 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. \ud83d\udd35 More JavaScript fun: \u25b6\ufe0f In this example, JavaScript creates a referral button on a page, which is then clicked. (click to expand)
    start_page = \"https://xkcd.com/465/\"\ndestination_page = \"https://github.com/seleniumbase/SeleniumBase\"\nself.open(start_page)\nreferral_link = '''<a class='analytics test' href='%s'>Free-Referral Button!</a>''' % destination_page\nself.execute_script('''document.body.innerHTML = \\\"%s\\\"''' % referral_link)\nself.click(\"a.analytics\")  # Clicks the generated button\n
    (Due to popular demand, this traffic generation example has been included in SeleniumBase with the self.generate_referral(start_page, end_page) and the self.generate_traffic(start_page, end_page, loops) methods.) \ud83d\udd35 How to use deferred asserts:

    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:

    from seleniumbase import BaseCase\nBaseCase.main(__name__, __file__)\n\nclass MyTestClass(BaseCase):\n    def test_deferred_asserts(self):\n        self.open('https://xkcd.com/993/')\n        self.wait_for_element('#comic')\n        self.deferred_assert_element('img[alt=\"Brand Identity\"]')\n        self.deferred_assert_element('img[alt=\"Rocket Ship\"]')  # Will Fail\n        self.deferred_assert_element('#comicmap')\n        self.deferred_assert_text('Fake Item', '#middleContainer')  # Will Fail\n        self.deferred_assert_text('Random', '#middleContainer')\n        self.deferred_assert_element('a[name=\"Super Fake !!!\"]')  # Will Fail\n        self.process_deferred_asserts()\n
    deferred_assert_element() and deferred_assert_text() will save any exceptions that would be raised. To flush out all the failed deferred asserts into a single exception, make sure to call self.process_deferred_asserts() at the end of your test method. If your test hits multiple pages, you can call self.process_deferred_asserts() before navigating to a new page so that the screenshot from your log files matches the URL where the deferred asserts were made. \ud83d\udd35 How to access raw WebDriver:

    If you need access to any commands that come with standard WebDriver, you can call them directly like this:

    self.driver.delete_all_cookies()\ncapabilities = self.driver.capabilities\nself.driver.find_elements(\"partial link text\", \"GitHub\")\n
    (In general, you'll want to use the SeleniumBase versions of methods when available.) \ud83d\udd35 How to retry failing tests automatically:

    You can use pytest --reruns=NUM to retry failing tests that many times. Add --reruns-delay=SECONDS to wait that many seconds between retries. Example:

    pytest --reruns=1 --reruns-delay=1\n

    You can use the @retry_on_exception() decorator to retry failing methods. (First import: from seleniumbase import decorators). To learn more about SeleniumBase decorators, click here.

    -------- > \"Catch bugs in QA before deploying code to Production!\"

    -------- Wrap-Up

    If you see something, say something!

    https://github.com/mdmintz

    --------

    "}, {"location": "examples/ReadMe/", "title": "\ud83d\udcda Running Example Tests", "text": ""}, {"location": "examples/ReadMe/#example-tests", "title": "Example Tests", "text": "

    (NOTE: Some example tests fail on purpose to demonstrate logging features.)

    Example tests with run commands to help you get started:

    Run an example test: (Default option: --chrome)

    pytest test_demo_site.py\n

    Run an example test in Firefox:

    pytest my_first_test.py --browser=firefox\n

    Run an example test in --demo mode: (highlight assertions)

    pytest test_swag_labs.py --demo\n

    Run test_coffee_cart.py to test the Coffee Cart app:

    pytest test_coffee_cart.py --demo\n

    Run a Wordle-solver example:

    pytest wordle_test.py\n

    Run an example test in --headless mode: (invisible browser)

    pytest my_first_test.py --headless\n

    Run an example test using Chrome's mobile device emulator: (default settings)

    pytest test_swag_labs.py --mobile\n

    Run an example test in --demo mode: (highlight assertions)

    pytest test_xkcd.py --demo\n

    Run a test suite with verbose output: (see more details)

    pytest test_suite.py -v\n

    Run a test suite using multiple parallel processes (-n=NUM):

    pytest test_suite.py -n=8\n

    Run a parameterized test: (Generates multiple tests from one)

    pytest parameterized_test.py -v\n

    Run a test suite and generate a SeleniumBase Dashboard:

    pytest test_suite.py --dashboard\n

    Run a test suite and generate a pytest report:

    pytest test_suite.py --html=report.html\n

    Run a failing test: (See the latest_logs/ folder for logs and screenshots)

    pytest test_fail.py\n

    Run a failing test that activates pdb debug mode on failure:

    pytest test_fail.py --pdb -s\n

    (pdb commands: n, c, s, u, d => next, continue, step, up, down)

    Run a test suite that demonstrates the use of pytest markers:

    pytest -m marker_test_suite -v\n

    Run a test suite that reuses the browser session between tests:

    pytest test_suite.py --rs\n

    Run an example test demonstrating the rate_limited Python decorator:

    pytest rate_limiting_test.py\n

    Run an example test that demonstrates how to upload a file to a website:

    pytest upload_file_test.py\n

    \ud83c\udf96\ufe0f SeleniumBase Commander is a GUI for pytest:

    sbase gui\n

    SeleniumBase tests can also be run with pynose:

    pynose my_first_test.py\n

    Run an example test suite and generate a pynose test report:

    pynose test_suite.py --report --show-report\n

    Run an example test using a pynose configuration file:

    pynose my_first_test.py --config=example_config.cfg\n

    For more advanced run commands, such as using a proxy server, see ../help_docs/customizing_test_runs.md

    If you just need to perform some quick website verification on various devices, you can use the SeleniumBase Device Farm. Just plug in a website URL, and it will display how the website looks on four different devices:

    To make things easier, here's a simple GUI program that allows you to run a few example tests by pressing a button:

    python gui_test_runner.py\n

    (The newer SeleniumBase Commander improves on that.)

    "}, {"location": "examples/behave_bdd/ReadMe/", "title": "\ud83d\udc1d Behave-BDD ReadMe", "text": ""}, {"location": "examples/behave_bdd/ReadMe/#behave-test-runner-for-seleniumbase", "title": "\ud83d\udc1d Behave test runner for SeleniumBase \ud83d\udc1d", "text": "

    \ud83d\udc1d (Utilizes the Behave BDD Python library. For more info, see the Behave tutorial and read about Behave's Gherkin model.)

    \ud83d\udc1d Behave examples with SeleniumBase: SeleniumBase/examples/behave_bdd

    > cd examples/behave_bdd/\n> behave features/realworld.feature -T -D dashboard -k\n\nDashboard: /Users/michael/github/SeleniumBase/examples/behave_bdd/dashboard.html\n********************************************************************************\nFeature: SeleniumBase scenarios for the RealWorld App # features/realworld.feature:1\n\nScenario: Verify RealWorld App (log in / sign out)  # features/realworld.feature:3\nGiven Open \"seleniumbase.io/realworld/login\"      # ../../sbase/steps.py:10\nAnd Clear Session Storage                         # ../../sbase/steps.py:669\nWhen Type \"demo_user\" into \"#username\"            # ../../sbase/steps.py:40\nAnd Type \"secret_pass\" into \"#password\"           # ../../sbase/steps.py:40\nAnd Do MFA \"GAXG2MTEOR3DMMDG\" into \"#totpcode\"    # ../../sbase/steps.py:322\nThen Assert exact text \"Welcome!\" in \"h1\"         # ../../sbase/steps.py:157\nAnd Highlight \"img#image1\"                        # ../../sbase/steps.py:184\nAnd Click 'a:contains(\"This Page\")'               # ../../sbase/steps.py:27\nAnd Save screenshot to logs                       # ../../sbase/steps.py:239\nWhen Click link \"Sign out\"                        # ../../sbase/steps.py:195\nThen Assert element 'a:contains(\"Sign in\")'       # ../../sbase/steps.py:120\nAnd Assert text \"You have been signed out!\"       # ../../sbase/steps.py:145\n\u2705 Scenario Passed!\n\n- Dashboard: /Users/michael/github/SeleniumBase/examples/behave_bdd/dashboard.html\n--- LogPath: /Users/michael/github/SeleniumBase/examples/behave_bdd/latest_logs/\n==================================================================================\n1 feature passed, 0 failed, 0 skipped\n1 scenario passed, 0 failed, 0 skipped\n12 steps passed, 0 failed, 0 skipped, 0 undefined\nTook 0m4.682s\n

    \ud83d\udc1d Another example, which uses higher-level Behave steps to simplify the .feature file:

    > cd examples/behave_bdd/\n> behave features/calculator.feature:61 -T -D dashboard -k\n\nDashboard: /Users/michael/github/SeleniumBase/examples/behave_bdd/dashboard.html\n********************************************************************************\nFeature: SeleniumBase scenarios for the Calculator App # features/calculator.feature:1\n\nBackground:   # features/calculator.feature:3\n\nScenario: 7.0 \u00d7 (3 + 3) = 42        # features/calculator.feature:49\nGiven Open the Calculator App     # features/steps/calculator.py:4\nWhen Press C                      # features/steps/calculator.py:9\nAnd Press 7                       # features/steps/calculator.py:79\nAnd Press .                       # features/steps/calculator.py:104\nAnd Press 0                       # features/steps/calculator.py:94\nAnd Press \u00d7                       # features/steps/calculator.py:29\nAnd Press (                       # features/steps/calculator.py:14\nAnd Press 3                       # features/steps/calculator.py:59\nAnd Press +                       # features/steps/calculator.py:39\nAnd Press 3                       # features/steps/calculator.py:59\nAnd Press )                       # features/steps/calculator.py:19\nThen Verify output is \"7.0\u00d7(3+3)\" # features/steps/calculator.py:135\nWhen Press =                      # features/steps/calculator.py:44\nThen Verify output is \"42\"        # features/steps/calculator.py:135\n\u2705 Scenario Passed!\n\n- Dashboard: /Users/michael/github/SeleniumBase/examples/behave_bdd/dashboard.html\n--- LogPath: /Users/michael/github/SeleniumBase/examples/behave_bdd/latest_logs/\n==================================================================================\n1 feature passed, 0 failed, 0 skipped\n1 scenario passed, 0 failed, 8 skipped\n14 steps passed, 0 failed, 60 skipped, 0 undefined\nTook 0m1.672s\n

    \ud83d\udc1d\u26aa With the Dashboard enabled, you'll get one of these:

    "}, {"location": "examples/behave_bdd/ReadMe/#behave-gherkin-files", "title": "\ud83d\udc1d Behave-Gherkin files", "text": "

    \ud83d\udc1d The *.feature files can use any step seen from:

    behave --steps-catalog\n

    \ud83d\udc1d SeleniumBase includes several pre-made Behave steps, which you can use by creating a Python file with the following line in your features/steps/ directory:

    from seleniumbase.behave import steps  # noqa\n

    \ud83d\udc1d Inside your features/environment.py file, you should have the following:

    from seleniumbase import BaseCase\nfrom seleniumbase.behave import behave_sb\nbehave_sb.set_base_class(BaseCase)  # Accepts a BaseCase subclass\nfrom seleniumbase.behave.behave_sb import before_all  # noqa\nfrom seleniumbase.behave.behave_sb import before_feature  # noqa\nfrom seleniumbase.behave.behave_sb import before_scenario  # noqa\nfrom seleniumbase.behave.behave_sb import before_step  # noqa\nfrom seleniumbase.behave.behave_sb import after_step  # noqa\nfrom seleniumbase.behave.behave_sb import after_scenario  # noqa\nfrom seleniumbase.behave.behave_sb import after_feature  # noqa\nfrom seleniumbase.behave.behave_sb import after_all  # noqa\n

    \ud83d\udc1d If you've already created a subclass of BaseCase with custom methods, you can swap BaseCase in with your own subclass, which will allow you to easily use your own custom methods in your Behave step definitions.

    \ud83d\udc1d Here's an example Python file in the features/steps/ folder:

    from behave import step\n\n\n@step(\"Open the Swag Labs Login Page\")\ndef go_to_swag_labs(context):\n    sb = context.sb\n    sb.open(\"https://www.saucedemo.com\")\n    sb.clear_local_storage()\n\n\n@step(\"Login to Swag Labs with {user}\")\ndef login_to_swag_labs(context, user):\n    sb = context.sb\n    sb.type(\"#user-name\", user)\n    sb.type(\"#password\", \"secret_sauce\\n\")\n\n\n@step(\"Verify that the current user is logged in\")\ndef verify_logged_in(context):\n    sb = context.sb\n    sb.assert_element(\"#header_container\")\n    sb.assert_element(\"#react-burger-menu-btn\")\n    sb.assert_element(\"#shopping_cart_container\")\n\n\n@step('Add \"{item}\" to cart')\ndef add_item_to_cart(context, item):\n    sb = context.sb\n    sb.click('div.inventory_item:contains(\"%s\") button[name*=\"add\"]' % item)\n

    \ud83d\udc1d A *.feature file could look like this:

    Feature: SeleniumBase scenarios for the Swag Labs App\n\nBackground:\n    Given Open the Swag Labs Login Page\n\nScenario: User can order a backpack from the store\n    When Login to Swag Labs with standard_user\nThen Verify that the current user is logged in\nAnd Save price of \"Backpack\" to <item_price>\nWhen Add \"Backpack\" to Cart\nThen Verify shopping cart badge shows 1 item(s)\nWhen Click on shopping cart icon\nAnd Click Checkout\nAnd Enter checkout info: First, Last, 12345\nAnd Click Continue\nThen Verify 1 \"Backpack\"(s) in cart\nAnd Verify cost of \"Backpack\" is <item_price>\nAnd Verify item total is $29.99\nAnd Verify tax amount is $2.40\nAnd Verify total cost is $32.39\nWhen Click Finish\nThen Verify order complete\nWhen Logout from Swag Labs\nThen Verify on Login page\n

    \ud83d\udc1d Here's another example of a *.feature file:

    Feature: SeleniumBase scenarios for the RealWorld App\n\nScenario: Verify RealWorld App (log in / sign out)\n    Given Open \"seleniumbase.io/realworld/login\"\nAnd Clear Session Storage\nWhen Type \"demo_user\" into \"#username\"\nAnd Type \"secret_pass\" into \"#password\"\nAnd Do MFA \"GAXG2MTEOR3DMMDG\" into \"#totpcode\"\nThen Assert text \"Welcome!\" in \"h1\"\nAnd Highlight element \"img#image1\"\nAnd Click 'a:contains(\"This Page\")'\nAnd Save screenshot to logs\nWhen Click link \"Sign out\"\nThen Assert element 'a:contains(\"Sign in\")'\nAnd Assert text \"You have been signed out!\"\n

    \ud83d\udc1d If there's a test failure, that's easy to spot:

    Feature: SeleniumBase scenarios for the Fail Page # features/fail_page.feature:1\n\nScenario: Fail test on purpose to see what happens  # features/fail_page.feature:3\nWhen Open the Fail Page                           # features/steps/fail_page.py:4\nThen Fail test on purpose                         # features/steps/fail_page.py:9\nAssertion Failed: This test fails on purpose!\n      Captured stdout:\n      >>> STEP FAILED:  (#2) Fail test on purpose\nClass / Feature:  SeleniumBase scenarios for the Fail Page\n      Test / Scenario:  Fail test on purpose to see what happens\n\n   \u274c Scenario Failed!\n

    \ud83d\udc1d\ud83c\udf96\ufe0f For convenience, the SeleniumBase Behave GUI lets you run behave scripts from a Desktop app.

    \ud83d\udc1d\ud83c\udf96\ufe0f To launch it, call sbase behave-gui or sbase gui-behave:

    sbase behave-gui\n* Starting the SeleniumBase Behave Commander GUI App...\n

    \ud83d\udc1d\ud83c\udf96\ufe0f You can customize the tests that show up there:

    sbase behave-gui  # all tests\nsbase behave-gui -i=calculator  # tests with \"calculator\" in the name\nsbase behave-gui features/  # tests located in the \"features/\" folder\nsbase behave-gui features/calculator.feature  # tests in that feature\n
    To learn more about SeleniumBase, check out the Docs Site:

    All the code is on GitHub:

    "}, {"location": "examples/chart_maker/ReadMe/", "title": "\ud83d\udcf6 Chart Maker", "text": ""}, {"location": "examples/chart_maker/ReadMe/#chartmaker", "title": "\ud83d\udcca ChartMaker \ud83d\udcf6 ChartMaker API", "text": "

    SeleniumBase ChartMaker lets you use Python to generate HTML charts.

    (Click to see a presentation with multiple charts)

    Here's how to run a simple pie chart presentation from GitHub => seleniumbase/SeleniumBase/examples/chart_maker:

    cd examples/chart_maker\npytest my_chart.py\n

    Here's the code for that pie chart presentation (GitHub => seleniumbase/SeleniumBase/examples/chart_maker/my_chart.py):

    from seleniumbase import BaseCase\nBaseCase.main(__name__, __file__)\n\nclass MyChartMakerClass(BaseCase):\n    def test_chart_maker(self):\n        self.create_presentation()\n        self.create_pie_chart(title=\"Automated Tests\")\n        self.add_data_point(\"Passed\", 7, color=\"#95d96f\")\n        self.add_data_point(\"Untested\", 2, color=\"#eaeaea\")\n        self.add_data_point(\"Failed\", 1, color=\"#f1888f\")\n        self.add_slide(\"<p>Pie Chart</p>\" + self.extract_chart())\n        self.begin_presentation(filename=\"my_chart.html\")\n

    Here's how to run an example presentation with multiple charts:

    cd examples/chart_maker\npytest chart_presentation.py\n

    Here are screenshots from the examples:

    Here's a line chart example:
    from seleniumbase import BaseCase\nBaseCase.main(__name__, __file__)\n\nclass MyChartMakerClass(BaseCase):\n    def test_chart_maker(self):\n        self.create_presentation()\n        self.create_line_chart(\n            title=\"Time Outside\", subtitle=\"Last Week\", unit=\"Minutes\")\n        self.add_data_point(\"Sun\", 5)\n        self.add_data_point(\"Mon\", 10)\n        self.add_data_point(\"Tue\", 20)\n        self.add_data_point(\"Wed\", 40)\n        self.add_data_point(\"Thu\", 80)\n        self.add_data_point(\"Fri\", 65)\n        self.add_data_point(\"Sat\", 50)\n        self.add_slide(\"<p>Line Chart</p>\" + self.extract_chart())\n        self.begin_presentation(filename=\"line_chart.html\", interval=8)\n

    This example is from test_line_chart.py, which you can run from the examples/chart_maker folder with the following command:

    pytest test_line_chart.py\n

    Because that presentation above has an interval set to 8, it will automatically advance to the next slide after 8 seconds. (Or exit if there are no more slides.)

    For a more advanced example (multiple charts in a presentation):
    from seleniumbase import BaseCase\nBaseCase.main(__name__, __file__)\n\nclass MyChartMakerClass(BaseCase):\n    def test_chart_maker_presentation(self):\n        self.create_presentation(theme=\"sky\")\n\n        self.create_pie_chart(title=\"Automated Tests\")\n        self.add_data_point(\"Passed\", 7, color=\"#95d96f\")\n        self.add_data_point(\"Untested\", 2, color=\"#eaeaea\")\n        self.add_data_point(\"Failed\", 1, color=\"#f1888f\")\n        self.add_slide(\"<p>Pie Chart</p>\" + self.extract_chart())\n\n        self.create_bar_chart(title=\"Language\")\n        self.add_data_point(\"Python\", 33, color=\"Orange\")\n        self.add_data_point(\"JavaScript\", 27, color=\"Teal\")\n        self.add_data_point(\"HTML + CSS\", 21, color=\"Purple\")\n        self.add_slide(\"<p>Bar Chart</p>\" + self.extract_chart())\n\n        self.create_column_chart(title=\"Colors\")\n        self.add_data_point(\"Red\", 10, color=\"Red\")\n        self.add_data_point(\"Green\", 25, color=\"Green\")\n        self.add_data_point(\"Blue\", 15, color=\"Blue\")\n        self.add_slide(\"<p>Column Chart</p>\" + self.extract_chart())\n\n        self.create_line_chart(title=\"Last Week's Data\")\n        self.add_data_point(\"Sun\", 5)\n        self.add_data_point(\"Mon\", 10)\n        self.add_data_point(\"Tue\", 20)\n        self.add_data_point(\"Wed\", 40)\n        self.add_data_point(\"Thu\", 80)\n        self.add_data_point(\"Fri\", 65)\n        self.add_data_point(\"Sat\", 50)\n        self.add_slide(\"<p>Line Chart</p>\" + self.extract_chart())\n\n        self.begin_presentation(filename=\"chart_presentation.html\")\n

    Here's how to run that example:

    cd examples/chart_maker\npytest chart_presentation.py\n

    (Press the Right Arrow to advance to the next slide in that chart presentation)

    (Click to see a live example of that presentation)

    Multi-Series charts can also be created. Try the available examples to learn more.

    self.create_pie_chart(\n    chart_name=None, title=None, subtitle=None,\n    data_name=None, unit=None, libs=True):\n\"\"\" Creates a JavaScript pie chart using \"HighCharts\".\n    @Params\n    chart_name - If creating multiple charts,\n                 use this to select which one.\n    title - The title displayed for the chart.\n    subtitle - The subtitle displayed for the chart.\n    data_name - The series name. Useful for multi-series charts.\n                If no data_name, will default to using \"Series 1\".\n    unit - The description label given to the chart's y-axis values.\n    libs - The option to include Chart libraries (JS and CSS files).\n           Should be set to True (default) for the first time creating\n           a chart on a web page. If creating multiple charts on the\n           same web page, you won't need to re-import the libraries\n           when creating additional charts.\n    labels - If True, displays labels on the chart for data points.\n    legend - If True, displays the data point legend on the chart.\n\"\"\"\n
    self.create_bar_chart(\n    chart_name=None, title=None, subtitle=None,\n    data_name=None, unit=None, libs=True):\n\"\"\" Creates a JavaScript bar chart using \"HighCharts\".\n    @Params\n    chart_name - If creating multiple charts,\n                 use this to select which one.\n    title - The title displayed for the chart.\n    subtitle - The subtitle displayed for the chart.\n    data_name - The series name. Useful for multi-series charts.\n                If no data_name, will default to using \"Series 1\".\n    unit - The description label given to the chart's y-axis values.\n    libs - The option to include Chart libraries (JS and CSS files).\n           Should be set to True (default) for the first time creating\n           a chart on a web page. If creating multiple charts on the\n           same web page, you won't need to re-import the libraries\n           when creating additional charts.\n    labels - If True, displays labels on the chart for data points.\n    legend - If True, displays the data point legend on the chart.\n\"\"\"\n
    self.create_column_chart(\n    chart_name=None, title=None, subtitle=None,\n    data_name=None, unit=None, libs=True):\n\"\"\" Creates a JavaScript column chart using \"HighCharts\".\n    @Params\n    chart_name - If creating multiple charts,\n                 use this to select which one.\n    title - The title displayed for the chart.\n    subtitle - The subtitle displayed for the chart.\n    data_name - The series name. Useful for multi-series charts.\n                If no data_name, will default to using \"Series 1\".\n    unit - The description label given to the chart's y-axis values.\n    libs - The option to include Chart libraries (JS and CSS files).\n           Should be set to True (default) for the first time creating\n           a chart on a web page. If creating multiple charts on the\n           same web page, you won't need to re-import the libraries\n           when creating additional charts.\n    labels - If True, displays labels on the chart for data points.\n    legend - If True, displays the data point legend on the chart.\n\"\"\"\n
    self.create_line_chart(\n    chart_name=None, title=None, subtitle=None,\n    data_name=None, unit=None, zero=False, libs=True):\n\"\"\" Creates a JavaScript line chart using \"HighCharts\".\n    @Params\n    chart_name - If creating multiple charts,\n                 use this to select which one.\n    title - The title displayed for the chart.\n    subtitle - The subtitle displayed for the chart.\n    data_name - The series name. Useful for multi-series charts.\n                If no data_name, will default to using \"Series 1\".\n    unit - The description label given to the chart's y-axis values.\n    zero - If True, the y-axis always starts at 0. (Default: False).\n    libs - The option to include Chart libraries (JS and CSS files).\n           Should be set to True (default) for the first time creating\n           a chart on a web page. If creating multiple charts on the\n           same web page, you won't need to re-import the libraries\n           when creating additional charts.\n    labels - If True, displays labels on the chart for data points.\n    legend - If True, displays the data point legend on the chart.\n\"\"\"\n
    self.create_area_chart(\n    chart_name=None, title=None, subtitle=None,\n    data_name=None, unit=None, zero=False, libs=True):\n\"\"\" Creates a JavaScript area chart using \"HighCharts\".\n    @Params\n    chart_name - If creating multiple charts,\n                 use this to select which one.\n    title - The title displayed for the chart.\n    subtitle - The subtitle displayed for the chart.\n    data_name - The series name. Useful for multi-series charts.\n                If no data_name, will default to using \"Series 1\".\n    unit - The description label given to the chart's y-axis values.\n    zero - If True, the y-axis always starts at 0. (Default: False).\n    libs - The option to include Chart libraries (JS and CSS files).\n           Should be set to True (default) for the first time creating\n           a chart on a web page. If creating multiple charts on the\n           same web page, you won't need to re-import the libraries\n           when creating additional charts.\n    labels - If True, displays labels on the chart for data points.\n    legend - If True, displays the data point legend on the chart.\n\"\"\"\n

    If creating multiple charts at the same time, you can pass the chart_name parameter to distinguish between different charts.

    Adding a data point to a chart:
    self.add_data_point(label, value, color=None, chart_name=None):\n\"\"\" Add a data point to a SeleniumBase-generated chart.\n    @Params\n    label - The label name for the data point.\n    value - The numeric value of the data point.\n    color - The HTML color of the data point.\n            Can be an RGB color. Eg: \"#55ACDC\".\n            Can also be a named color. Eg: \"Teal\".\n    chart_name - If creating multiple charts,\n                 use this to select which one.\n\"\"\"\n
    Adding a new data series to an existing chart:
    self.add_series_to_chart(self, data_name=None, chart_name=None):\n\"\"\" Add a new data series to an existing chart.\n    This allows charts to have multiple data sets.\n    @Params\n    data_name - Set the series name. Useful for multi-series charts.\n    chart_name - If creating multiple charts,\n                 use this to select which one.\n\"\"\"\n
    Saving a chart to a file:
    self.save_chart(chart_name=None, filename=None):\n\"\"\" Saves a SeleniumBase-generated chart to a file for later use.\n    @Params\n    chart_name - If creating multiple charts at the same time,\n                 use this to select the one you wish to use.\n    filename - The name of the HTML file that you wish to\n               save the chart to. (filename must end in \".html\")\n\"\"\"\n

    The full HTML of the chart is saved to the saved_charts/ folder.

    Extracting the HTML of a chart:
    self.extract_chart(chart_name=None):\n\"\"\" Extracts the HTML from a SeleniumBase-generated chart.\n    @Params\n    chart_name - If creating multiple charts at the same time,\n                 use this to select the one you wish to use.\n\"\"\"\n
    Displaying a chart in the browser window:
    self.display_chart(chart_name=None, filename=None):\n\"\"\" Displays a SeleniumBase-generated chart in the browser window.\n    @Params\n    chart_name - If creating multiple charts at the same time,\n                 use this to select the one you wish to use.\n    filename - The name of the HTML file that you wish to\n               save the chart to. (filename must end in \".html\")\n    interval - The delay time for auto-advancing charts. (in seconds)\n               If set to 0 (default), auto-advancing is disabled.\n\"\"\"\n

    All methods have the optional chart_name argument, which is only needed when storing multiple charts at the same time.

    "}, {"location": "examples/dialog_boxes/ReadMe/", "title": "\ud83d\udec2 Dialog Boxes", "text": "Dialog Boxes \ud83d\udec2

    SeleniumBase Dialog Boxes let your users provide input in the middle of automation scripts.

    \u2195\ufe0f (Example: dialog_box_tour.py) \u2195\ufe0f

    Here's how to run that example:
    cd examples/dialog_boxes\npytest test_dialog_boxes.py\n
    Here's a code snippet from that:
    self.open(\"https://xkcd.com/1920/\")\nskip_button = [\"SKIP\", \"red\"]  # Can be a [text, color] list or tuple.\nbuttons = [\"Fencing\", \"Football\", \"Metaball\", \"Go/Chess\", skip_button]\nmessage = \"Choose a sport:\"\nchoice = self.get_jqc_button_input(message, buttons)\nif choice == \"Fencing\":\n    self.open(\"https://xkcd.com/1424/\")\n
    Here's a simple form with only buttons as input:
    choice = self.get_jqc_button_input(\"Ready?\", [\"YES\", \"NO\"])\nprint(choice)  # This prints \"YES\" or \"NO\"\n\n# You may want to customize the color of buttons\nbuttons = [(\"YES\", \"green\"), (\"NO\", \"red\")]\nchoice = self.get_jqc_button_input(\"Ready?\", buttons)\n
    Here's a simple form with an input field:
    text = self.get_jqc_text_input(\"Enter text:\", [\"Search\"])\nprint(text)  # This prints the text entered\n
    This form has an input field and buttons:
    message = \"Type your name and choose a language:\"\nbuttons = [\"Python\", \"JavaScript\"]\ntext, choice = self.get_jqc_form_inputs(message, buttons)\nprint(\"Your name is: %s\" % text)\nprint(\"You picked %s!\" % choice)\n
    You can customize options if you want:
    # Themes: bootstrap, modern, material, supervan, light, dark, seamless\noptions = [(\"theme\", \"modern\"), (\"width\", \"50%\")]\nself.get_jqc_text_input(\"You Won!\", [\"OK\"], options)\n
    Default options can be set with set_jqc_theme():
    self.set_jqc_theme(\"light\", color=\"green\", width=\"38%\")\n\n# To reset jqc theme settings to factory defaults\nself.reset_jqc_theme()\n
    All methods for Dialog Boxes:
    self.get_jqc_button_input(message, buttons, options=None)\n\nself.get_jqc_text_input(message, button=None, options=None)\n\nself.get_jqc_form_inputs(message, buttons, options=None)\n\nself.set_jqc_theme(theme, color=None, width=None)\n\nself.reset_jqc_theme()\n\nself.activate_jquery_confirm()  # Automatic for jqc methods\n
    Detailed method summaries for Dialog Boxes:
    self.get_jqc_button_input(message, buttons, options=None)\n\"\"\"\nPop up a jquery-confirm box and return the text of the button clicked.\nIf running in headless mode, the last button text is returned.\n@Params\nmessage: The message to display in the jquery-confirm dialog.\nbuttons: A list of tuples for text and color.\n    Example: [(\"Yes!\", \"green\"), (\"No!\", \"red\")]\n    Available colors: blue, green, red, orange, purple, default, dark.\n    A simple text string also works: \"My Button\". (Uses default color.)\noptions: A list of tuples for options to set.\n    Example: [(\"theme\", \"bootstrap\"), (\"width\", \"450px\")]\n    Available theme options: bootstrap, modern, material, supervan,\n                             light, dark, and seamless.\n    Available colors: (For the BORDER color, NOT the button color.)\n        \"blue\", \"default\", \"green\", \"red\", \"purple\", \"orange\", \"dark\".\n    Example option for changing the border color: (\"color\", \"default\")\n    Width can be set using percent or pixels. Eg: \"36.0%\", \"450px\".\n\"\"\"\n\nself.get_jqc_text_input(message, button=None, options=None)\n\"\"\"\nPop up a jquery-confirm box and return the text submitted by the input.\nIf running in headless mode, the text returned is \"\" by default.\n@Params\nmessage: The message to display in the jquery-confirm dialog.\nbutton: A 2-item list or tuple for text and color. Or just the text.\n    Example: [\"Submit\", \"blue\"] -> (default button if not specified)\n    Available colors: blue, green, red, orange, purple, default, dark.\n    A simple text string also works: \"My Button\". (Uses default color.)\noptions: A list of tuples for options to set.\n    Example: [(\"theme\", \"bootstrap\"), (\"width\", \"450px\")]\n    Available theme options: bootstrap, modern, material, supervan,\n                             light, dark, and seamless.\n    Available colors: (For the BORDER color, NOT the button color.)\n        \"blue\", \"default\", \"green\", \"red\", \"purple\", \"orange\", \"dark\".\n    Example option for changing the border color: (\"color\", \"default\")\n    Width can be set using percent or pixels. Eg: \"36.0%\", \"450px\".\n\"\"\"\n\nself.get_jqc_form_inputs(message, buttons, options=None)\n\"\"\"\nPop up a jquery-confirm box and return the input/button texts as tuple.\nIf running in headless mode, returns the (\"\", buttons[-1][0]) tuple.\n@Params\nmessage: The message to display in the jquery-confirm dialog.\nbuttons: A list of tuples for text and color.\n    Example: [(\"Yes!\", \"green\"), (\"No!\", \"red\")]\n    Available colors: blue, green, red, orange, purple, default, dark.\n    A simple text string also works: \"My Button\". (Uses default color.)\noptions: A list of tuples for options to set.\n    Example: [(\"theme\", \"bootstrap\"), (\"width\", \"450px\")]\n    Available theme options: bootstrap, modern, material, supervan,\n                             light, dark, and seamless.\n    Available colors: (For the BORDER color, NOT the button color.)\n        \"blue\", \"default\", \"green\", \"red\", \"purple\", \"orange\", \"dark\".\n    Example option for changing the border color: (\"color\", \"default\")\n    Width can be set using percent or pixels. Eg: \"36.0%\", \"450px\".\n\"\"\"\n\nself.set_jqc_theme(theme, color=None, width=None)\n\"\"\" Sets the default jquery-confirm theme and width (optional).\nAvailable themes: \"bootstrap\", \"modern\", \"material\", \"supervan\",\n                  \"light\", \"dark\", and \"seamless\".\nAvailable colors: (This sets the BORDER color, NOT the button color.)\n    \"blue\", \"default\", \"green\", \"red\", \"purple\", \"orange\", \"dark\".\nWidth can be set using percent or pixels. Eg: \"36.0%\", \"450px\".\n\"\"\"\n\nself.reset_jqc_theme()\n\"\"\" Resets the jqc theme settings to factory defaults. \"\"\"\n\nself.activate_jquery_confirm()  # Automatic for jqc methods\n\"\"\" See https://craftpip.github.io/jquery-confirm/ for usage. \"\"\"\n
    \u2705 \ud83d\udec2 Automated/Manual Hybrid Mode (MasterQA)

    MasterQA uses SeleniumBase Dialog Boxes to speed up manual testing by having automation perform all the browser actions while the manual tester handles validation. See the MasterQA GitHub page for examples.

    "}, {"location": "examples/example_logs/ReadMe/", "title": "\ud83d\udcca Dashboard / Reports", "text": ""}, {"location": "examples/example_logs/ReadMe/#logs-the-dashboard-and-reports", "title": "Logs, The Dashboard, and Reports", "text": "

    \ud83d\udd35 During test failures, logs and screenshots from the most recent test run will get saved to the latest_logs/ folder. If --archive-logs is specified (or if ARCHIVE_EXISTING_LOGS is set to True in settings.py), test logs will also get archived to the archived_logs/ folder. Otherwise, the log files will be cleaned out when the next test run begins (by default).

    pytest test_fail.py\n

    (Log files in SeleniumBase/examples/example_logs were generated when test_fail.py ran and failed.)

    Examples of expected log files generated during failures:

    In addition to log files, you can also generate dashboards and test reports.

    The SeleniumBase Dashboard:

    \ud83d\udd35 The --dashboard option for pytest generates a SeleniumBase Dashboard located at dashboard.html, which updates automatically as tests run and produce results. Example:

    pytest --dashboard --rs --headless\n

    \ud83d\udd35 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:

    python -m http.server 1948\n

    \ud83d\udd35 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.)

    \ud83d\udd35 Here's a full example of what the SeleniumBase Dashboard may look like:

    pytest test_suite.py --dashboard --rs --headless\n

    Pytest Reports:

    \ud83d\udd35 Using --html=report.html gives you a fancy report of the name specified after your test suite completes.

    pytest test_suite.py --html=report.html\n

    \ud83d\udd35 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.

    \ud83d\udd35 Here's an example of an upgraded html report:

    pytest test_suite.py --dashboard --html=report.html\n

    If viewing pytest-html reports in Jenkins, you may need to configure Jenkins settings for the HTML to render correctly. This is due to Jenkins CSP changes. That setting can be changed from Manage Jenkins > Script Console by running:

    System.setProperty(\"hudson.model.DirectoryBrowserSupport.CSP\", \"\")\n

    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.

    pytest test_suite.py --junit-xml=report.xml\n
    pynose Test Reports:

    The pynose --report option gives you a fancy report after your tests complete.

    pynose test_suite.py --report\n

    (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.)

    \ud83d\udc1d\u26aa Behave Dashboard & Reports:

    (The behave_bdd/ folder can be found in the examples/ folder.)

    behave behave_bdd/features/ -D dashboard -D headless\n

    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.

    behave behave_bdd/features/ --junit -D rs -D headless\n
    "}, {"location": "examples/master_qa/ReadMe/", "title": "\ud83d\udec2 MasterQA Mode", "text": "MasterQA combines automation with manual verification steps.

    Here's code from basic_masterqa_test_0.py:

    from seleniumbase import MasterQA\n\nclass MasterQATests(MasterQA):\n    def test_masterqa(self):\n        self.open(\"https://xkcd.com/1700/\")\n        self.verify(\"Do you see a webcomic?\")\n        self.open(\"https://seleniumbase.io/demo_page\")\n        self.highlight('table')\n        self.verify(\"Do you see elements in a table?\")\n        self.open(\"https://seleniumbase.io/devices/\")\n        self.highlight(\"div.mockup-wrapper\")\n        self.verify(\"Do you see 4 computer devices?\")\n

    After each automation checkpoint, a pop-up window will ask the user questions for each verification command.

    When the test run completes, as seen from this longer example, you'll reach the results page that appears after answering all the verification questions. (Failed verifications generate links to screenshots and log files.)

    You may have noticed the Incomplete Test Runs row on the results page. If the value for that is not zero, it means that one of the automated steps failed. This could happen if you tell your script to perform an action on an element that doesn't exist. Now that we're mixing automation with manual QA, it's good to tell apart the failures from each. The results_table CSV file contains a spreadsheet with the details of each failure (if any) for both manual and automated steps.

    How to run the example tests from scratch:

    git clone https://github.com/seleniumbase/SeleniumBase.git\ncd SeleniumBase\npip install .\ncd examples/master_qa\npytest basic_masterqa_test_0.py\npytest masterqa_test_1.py\n

    At the end of your test run, you'll receive a report with results, screenshots, and log files. Close the Results Page window when you're done.

    Check out masterqa_test_1.py to learn how to write your own MasterQA tests:

    You'll notice that tests are written the same way as regular SeleniumBase tests, with the key difference being a different import: from seleniumbase import MasterQA rather than from seleniumbase import BaseCase. Now your Python test class will import MasterQA instead of BaseCase.

    To add a manual verification step, use self.verify() in the code after each part of your test that needs a manual verification step. If you want to include a custom question, add text inside that call (in quotes). Example:

    self.verify()\n\nself.verify(\"Can you find the moon?\")\n

    MasterQA is powered by SeleniumBase, the most advanced open-source automation framework on the Planet.

    "}, {"location": "examples/presenter/ReadMe/", "title": "\ud83c\udf9e\ufe0f Presentation Maker", "text": ""}, {"location": "examples/presenter/ReadMe/#presenter", "title": "\ud83d\udcd1 Presenter \ud83c\udf9e\ufe0f", "text": "

    SeleniumBase Presenter (slide-maker) lets you use Python to generate HTML presentations.

    Here's a sample presentation:

    (Click on the image/GIF for the actual presentation)

    (Here's the code for that presentation)

    Slides can include HTML, code, images, and iframes.

    Here's how to run the example presentation:

    cd examples/presenter\npytest my_presentation.py\n

    Here's a presentation with a chart:

    (Click on the image/GIF for the actual presentation)

    (Here's the code for that presentation)

    Here's how to run that example:

    cd examples/presenter\npytest core_presentation.py\n
    Creating a new presentation:
    self.create_presentation(name=None, theme=\"serif\", transition=\"default\")\n\"\"\" Creates a Reveal-JS presentation that you can add slides to.\n    @Params\n    name - If creating multiple presentations at the same time,\n           use this to specify the name of the current presentation.\n    theme - Set a theme with a unique style for the presentation.\n            Valid themes: \"serif\" (default), \"sky\", \"white\", \"black\",\n                          \"simple\", \"league\", \"moon\", \"night\",\n                          \"beige\", \"blood\", and \"solarized\".\n    transition - Set a transition between slides.\n                 Valid transitions: \"none\" (default), \"slide\", \"fade\",\n                                    \"zoom\", \"convex\", and \"concave\".\n\"\"\"\n

    If creating multiple presentations at the same time, you can pass the name parameter to distinguish between different presentations. Notes are disabled by default. You can enable notes by specifying: show_notes=True

    Adding a slide to a presentation:
    self.add_slide(content=None, image=None, code=None, iframe=None,\n               content2=None, notes=None, transition=None, name=None)\n\"\"\" Allows the user to add slides to a presentation.\n    @Params\n    content - The HTML content to display on the presentation slide.\n    image - Attach an image (from a URL link) to the slide.\n    code - Attach code of any programming language to the slide.\n           Language-detection will be used to add syntax formatting.\n    iframe - Attach an iFrame (from a URL link) to the slide.\n    content2 - HTML content to display after adding an image or code.\n    notes - Additional notes to include with the slide.\n            ONLY SEEN if show_notes is set for the presentation.\n    transition - Set a transition between slides. (overrides previous)\n                 Valid transitions: \"none\" (default), \"slide\", \"fade\",\n                                    \"zoom\", \"convex\", and \"concave\".\n    name - If creating multiple presentations at the same time,\n           use this to select the presentation to add slides to.\n\"\"\"\n
    Running a presentation:
    self.begin_presentation(\n    filename=\"my_presentation.html\", show_notes=False, interval=0)\n\"\"\" Begin a Reveal-JS Presentation in the web browser.\n    @Params\n    name - If creating multiple presentations at the same time,\n           use this to select the one you wish to add slides to.\n    filename - The name of the HTML file that you wish to\n               save the presentation to. (filename must end in \".html\")\n    show_notes - When set to True, the Notes feature becomes enabled,\n                 which allows presenters to see notes next to slides.\n    interval - The delay time between autoplaying slides. (in seconds)\n               If set to 0 (default), autoplay is disabled.\n\"\"\"\n

    Before the presentation is run, the full HTML is saved to the saved_presentations/ folder.

    All methods have the optional name argument, which is only needed if you're creating multiple presentations at once.

    Here's an example of using SeleniumBase Presenter:
    from seleniumbase import BaseCase\nBaseCase.main(__name__, __file__)\n\nclass MyPresenterClass(BaseCase):\n    def test_presenter(self):\n        self.create_presentation(theme=\"serif\")\n        self.add_slide(\n            '<h1>Welcome</h1><br />\\n'\n            '<h3>Press the <b>Right Arrow</b></h3>')\n        self.add_slide(\n            '<h3>SeleniumBase Presenter</h3><br />\\n'\n            '<img width=\"240\" src=\"https://seleniumbase.io/img/logo3a.png\" />'\n            '<span style=\"margin:144px;\" />'\n            '<img src=\"https://seleniumbase.io/other/python_3d_logo.png\" />'\n            '<br /><br />\\n<h4>Create presentations with <b>Python</b></h4>')\n        self.add_slide(\n            '<h3>Make slides using <b>HTML</b>:</h3><br />\\n'\n            '<table style=\"padding:10px;border:4px solid black;font-size:50;\">'\n            '\\n<tr style=\"background-color:CDFFFF;\">\\n'\n            '<th>Row ABC</th><th>Row XYZ</th></tr>\\n'\n            '<tr style=\"background-color:DCFDDC;\">'\n            '<td>Value ONE</td><td>Value TWO</td></tr>\\n'\n            '<tr style=\"background-color:DFDFFB;\">\\n'\n            '<td>Value THREE</td><td>Value FOUR</td></tr>\\n'\n            '</table><br />\\n<h4>(HTML <b>table</b> example)</h4>')\n        self.add_slide(\n            '<h3>Keyboard Shortcuts:</h3>\\n'\n            '<table style=\"padding:10px;border:4px solid black;font-size:30;'\n            'background-color:FFFFDD;\">\\n'\n            '<tr><th>Key</th><th>Action</th></tr>\\n'\n            '<tr><td><b>=></b></td><td>Next Slide (N also works)</td></tr>\\n'\n            '<tr><td><b><=</b></td><td>Previous Slide (P also works)</td></tr>'\n            '\\n<tr><td>F</td><td>Full Screen Mode</td></tr>\\n'\n            '<tr><td>O</td><td>Overview Mode Toggle</td></tr>\\n'\n            '<tr><td>esc</td><td>Exit Full Screen / Overview Mode</td></tr>\\n'\n            '<tr><td><b>.</b></td><td>Pause/Resume Toggle</td></tr>\\n'\n            '<tr><td>space</td><td>Next Slide (alternative)</td></tr></table>')\n        self.add_slide(\n            '<h3>Add <b>images</b> to slides:</h3>',\n            image=\"https://seleniumbase.github.io/other/seagulls.jpg\")\n        self.add_slide(\n            '<h3>Add <b>code</b> to slides:</h3>',\n            code=(\n                'from seleniumbase import BaseCase\\n\\n'\n                'class MyTestClass(BaseCase):\\n\\n'\n                '    def test_basics(self):\\n'\n                '        self.open(\"https://store.xkcd.com/search\")\\n'\n                '        self.type(\\'input[name=\"q\"]\\', \"xkcd book\\\\n\")\\n'\n                '        self.assert_text(\"xkcd: volume 0\", \"h3\")\\n'\n                '        self.open(\"https://xkcd.com/353/\")\\n'\n                '        self.assert_title(\"xkcd: Python\")\\n'\n                '        self.assert_element(\\'img[alt=\"Python\"]\\')\\n'\n                '        self.click(\\'a[rel=\"license\"]\\')\\n'\n                '        self.assert_text(\"free to copy and reuse\")\\n'\n                '        self.go_back()\\n'\n                '        self.click_link(\"About\")\\n'\n                '        self.assert_exact_text(\"xkcd.com\", \"h2\")'))\n        self.add_slide(\n            \"<h3>Highlight <b>code</b> in slides:</h3>\",\n            code=(\n                'from seleniumbase import BaseCase\\n\\n'\n                '<mark>class MyTestClass(BaseCase):</mark>\\n\\n'\n                '    def test_basics(self):\\n'\n                '        self.open(\"https://store.xkcd.com/search\")\\n'\n                '        self.type(\\'input[name=\"q\"]\\', \"xkcd book\\\\n\")\\n'\n                '        self.assert_text(\"xkcd: volume 0\", \"h3\")'))\n        self.add_slide(\n            '<h3>Add <b>iFrames</b> to slides:</h3>',\n            iframe=\"https://seleniumbase.io/demo_page\")\n        self.add_slide(\n            '<h3>Getting started is <b>easy</b>:</h3>',\n            code=(\n                'from seleniumbase import BaseCase\\n\\n'\n                'class MyPresenterClass(BaseCase):\\n\\n'\n                '    def test_presenter(self):\\n'\n                '        self.create_presentation(theme=\"serif\")\\n'\n                '        self.add_slide(\"Welcome to Presenter!\")\\n'\n                '        self.add_slide(\\n'\n                '            \"Add code to slides:\",\\n'\n                '            code=(\\n'\n                '                \"from seleniumbase import BaseCase\\\\n\\\\n\"\\n'\n                '                \"class MyPresenterClass(BaseCase):\\\\n\\\\n\"\\n'\n                '                \"    def test_presenter(self):\\\\n\"\\n'\n                '                \"        self.create_presentation()\\\\n\"))\\n'\n                '        self.begin_presentation(\\n'\n                '            filename=\"demo.html\", show_notes=True)'))\n        self.add_slide(\n            '<h3>Include <b>notes</b> with slides:</h3><br />',\n            code=('self.add_slide(\"[Your HTML goes here]\",\\n'\n                  '               code=\"[Your software code goes here]\",\\n'\n                  '               content2=\"[Additional HTML goes here]\",\\n'\n                  '               notes=\"[Attached speaker notes go here]\"\\n'\n                  '                     \"[Note A! -- Note B! -- Note C! ]\")'),\n            notes='<h2><ul><li>Note A!<li>Note B!<li>Note C!<li>Note D!</h2>',\n            content2=\"<h4>(Notes can include HTML tags)</h4>\")\n        self.add_slide(\n            '<h3>Multiple <b>themes</b> available:</h3>',\n            code=(\n                'self.create_presentation(theme=\"serif\")\\n\\n'\n                'self.create_presentation(theme=\"sky\")\\n\\n'\n                'self.create_presentation(theme=\"simple\")\\n\\n'\n                'self.create_presentation(theme=\"white\")\\n\\n'\n                'self.create_presentation(theme=\"moon\")\\n\\n'\n                'self.create_presentation(theme=\"black\")\\n\\n'\n                'self.create_presentation(theme=\"night\")\\n\\n'\n                'self.create_presentation(theme=\"beige\")\\n\\n'\n                'self.create_presentation(theme=\"league\")'))\n        self.add_slide(\n            '<h2><b>The End</b></h2>',\n            image=\"https://seleniumbase.github.io/img/sb_logo_10.png\")\n        self.begin_presentation(\n            filename=\"presenter.html\", show_notes=True, interval=0)\n

    That example is from my_presentation.py, which you can run from the examples/presenter folder with the following command:

    pytest my_presentation.py\n
    Saving a presentation:

    If you want to save the presentation you created as an HTML file, use:

    self.save_presentation(filename=\"my_presentation.html\", show_notes=True)\n

    Presentations automatically get saved when calling:

    self.begin_presentation(show_notes=True)\n
    "}, {"location": "examples/tour_examples/ReadMe/", "title": "\ud83d\ude8e Tour Maker", "text": ""}, {"location": "examples/tour_examples/ReadMe/#interactive-product-tours", "title": "Interactive Product Tours \ud83d\ude8e", "text": "

    Increase SaaS Product Adoption by 10x or more.

    IntroJS, Bootstrap Tour, DriverJS, Shepherd, and Hopscotch.

    A tour demo: (with autoplay)

    SeleniumBase maps_introjs_tour.py

    cd examples/tour_examples\npytest maps_introjs_tour.py --interval=1\n

    Here's a longer version:

    SeleniumBase google_tour.py

    cd examples/tour_examples\npytest google_tour.py\n

    (From GitHub => SeleniumBase/examples/tour_examples)

    "}, {"location": "examples/tour_examples/ReadMe/#creating-a-new-tour", "title": "Creating a new tour", "text": ""}, {"location": "examples/tour_examples/ReadMe/#to-create-a-tour-utilizing-the-shepherd-library-use-one-of-the-following", "title": "To create a tour utilizing the Shepherd Library, use one of the following", "text": "

    self.create_shepherd_tour()

    OR

    self.create_tour(theme=\"shepherd\")

    You can pass a custom theme to change the look & feel of Shepherd tours. Valid themes for Shepherd Tours are dark, light / arrows, default, square, and square-dark.

    "}, {"location": "examples/tour_examples/ReadMe/#to-create-a-tour-utilizing-the-bootstrap-tour-library-use-one-of-the-following", "title": "To create a tour utilizing the Bootstrap Tour Library, use one of the following", "text": "

    self.create_bootstrap_tour()

    OR

    self.create_tour(theme=\"bootstrap\")

    "}, {"location": "examples/tour_examples/ReadMe/#to-create-a-tour-utilizing-the-introjs-library-use-one-of-the-following", "title": "To create a tour utilizing the IntroJS Library, use one of the following", "text": "

    self.create_introjs_tour()

    OR

    self.create_tour(theme=\"introjs\")

    "}, {"location": "examples/tour_examples/ReadMe/#to-create-a-tour-utilizing-the-driverjs-library-use-one-of-the-following", "title": "To create a tour utilizing the DriverJS Library, use one of the following", "text": "

    self.create_driverjs_tour()

    OR

    self.create_tour(theme=\"driverjs\")

    "}, {"location": "examples/tour_examples/ReadMe/#to-create-a-tour-utilizing-the-hopscotch-library-use-one-of-the-following", "title": "To create a tour utilizing the Hopscotch Library, use one of the following", "text": "

    self.create_hopscotch_tour()

    OR

    self.create_tour(theme=\"hopscotch\")

    "}, {"location": "examples/tour_examples/ReadMe/#adding-a-step-to-a-tour", "title": "Adding a step to a tour", "text": ""}, {"location": "examples/tour_examples/ReadMe/#to-add-a-tour-step-use-the-following", "title": "To add a tour step, use the following", "text": "

    self.add_tour_step(message, css_selector, title, alignment, theme)

    With the self.add_tour_step() method, you must first pass a message to display. You can then specify a web element to attach to (by using CSS selectors). If no element is specified, the tour step will tether to the top of the screen by default. You can also add an optional title above the message to display with the tour step, as well as change the theme for that step (Shepherd tours only), and even specify the alignment (which is the side of the element that you want the tour message to tether to).

    "}, {"location": "examples/tour_examples/ReadMe/#playing-a-tour", "title": "Playing a tour", "text": "

    You can play a tour by calling:

    self.play_tour(interval)

    If you specify an interval (optional), the tour will automatically walk through each step after that many seconds have passed.

    All methods have the optional name argument, which is only needed if you're creating multiple tours at once. Then, when you're adding a step or playing a tour, SeleniumBase knows which tour you're referring too. You can avoid using the name arg for multiple tours if you play a tour before creating a new one.

    "}, {"location": "examples/tour_examples/ReadMe/#heres-how-the-code-looks", "title": "Here's how the code looks", "text": "
    from seleniumbase import BaseCase\nBaseCase.main(__name__, __file__)\n\nclass MyTourClass(BaseCase):\n\n    def test_google_tour(self):\n        self.open('https://google.com/ncr')\n        self.wait_for_element('input[title=\"Search\"]')\n        self.hide_elements(\"iframe\")\n\n        self.create_tour(theme=\"dark\")\n        self.add_tour_step(\"Welcome to Google!\", title=\"SeleniumBase Tours\")\n        self.add_tour_step(\"Type in your query here.\", '[title=\"Search\"]')\n        self.play_tour()\n\n        self.highlight_type('input[title=\"Search\"]', \"Google\")\n        self.wait_for_element('[role=\"listbox\"]')  # Wait for autocomplete\n\n        self.create_tour(theme=\"light\")\n        self.add_tour_step(\"Then click to search.\", '[value=\"Google Search\"]')\n        self.add_tour_step(\"Or press [ENTER] after entry.\", '[title=\"Search\"]')\n        self.play_tour()\n
    "}, {"location": "examples/tour_examples/ReadMe/#that-code-is-from-google_tourpy-which-you-can-run-from-the-tour_examples-folder-with-the-following-command", "title": "That code is from google_tour.py, which you can run from the tour_examples/ folder with the following command", "text": "
    pytest google_tour.py\n
    "}, {"location": "examples/tour_examples/ReadMe/#exporting-a-tour", "title": "Exporting a Tour", "text": "

    If you want to save the tour you created as a JavaScript file, use:

    self.export_tour()

    OR

    self.export_tour(name=None, filename=\"my_tour.js\")

    (name is optional unless you gave custom names to your tours when you created them. filename is the name of the file to save the JavaScript to.) Once you've exported your tour, you can use it outside of SeleniumBase. You can even copy the tour's JavaScript code to the Console of your web browser to play the tour from there (you need to be on the correct web page for it to work).

    "}, {"location": "examples/visual_testing/ReadMe/", "title": "\ud83d\uddbc\ufe0f Visual Testing", "text": ""}, {"location": "examples/visual_testing/ReadMe/#automated-visual-regression-testing", "title": "Automated Visual Regression Testing", "text": "

    Automated Visual Regression Testing can help you detect when the layout of a web page has changed. Instead of comparing pixels from screenshots, layout differences can be detected by comparing HTML tags and attributes with a baseline. If a change is detected, it could mean that something broke, the web page was redesigned, or dynamic content changed.

    To handle automated visual testing, SeleniumBase uses the self.check_window() method, which can set visual baselines for comparison and then compare the latest versions of web pages to the existing baseline.

    The first time a test calls self.check_window() with a unique name parameter, the visual baseline is set, which means a folder is created with the following files:

  • page_url.txt -> The URL of the current window
  • baseline.png -> The baseline screenshot (PNG)
  • tags_level1.txt -> HTML tags from the window
  • tags_level2.txt -> HTML tags + attribute names
  • tags_level3.txt -> HTML tags + attribute names+values
  • After the first time self.check_window() is called, later calls will compare the HTML tags and attributes of the latest window to the ones from the first call (or to the ones from the call when the baseline was last reset). Additionally, a latest.png screenshot is saved in the same folder, which can help you determine if/when the existing baseline needs to be reset.

    Here's an example call:

    self.check_window(name=\"first_test)\", level=3)\n

    On the first run (or if the baseline is being set/reset) the \"level\" doesn't matter because that's only used for comparing the current layout to the existing baseline.

    Here's how the level system works:

  • level=0 -> DRY RUN ONLY - Will perform a comparison to the baseline, and print out any differences that are found, but won't fail the test even if differences exist.
  • level=1 -> HTML tags are compared to tags_level1.txt
  • level=2 -> HTML tags and attribute names are compared to tags_level2.txt
  • level=3 -> HTML tags and attribute names+values are compared to tags_level3.txt
  • As shown, Level-3 is the most strict, Level-1 is the least strict. If the comparisons from the latest window to the existing baseline don't match, the current test will fail, except for Level-0 checks, which print Level-3 results without failing the test.

    You can reset the visual baseline on the command line by adding the following parameter at runtime:

    --visual_baseline\n

    As long as --visual_baseline is used on the command line while running tests, the self.check_window() method cannot fail because it will rebuild the visual baseline rather than comparing the html tags of the latest run to the existing baseline. If there are any expected layout changes to a website that you're testing, you'll need to reset the baseline to prevent unnecessary failures.

    self.check_window() will fail with \"Page Domain Mismatch Failure\" if the domain of the current URL doesn't match the domain of the baseline URL.

    If you want to use self.check_window() to compare a web page to a later version of itself in the same test, add the baseline=True parameter to your first self.check_window() call to use that as the baseline. (This only makes sense if you're calling self.check_window() more than once with the same \"name\" parameter in the same test.)

    Automated Visual Testing with self.check_window() is not very effective for websites that have dynamic content because that changes the layout and structure of web pages. For those pages, you're much better off using regular SeleniumBase functional testing, unless you can remove the dynamic content before performing the comparison, (such as by using self.ad_block() to remove dynamic ad content on a web page).

    Example usage of self.check_window() with different levels:

        self.check_window(name=\"testing\", level=0)\n    self.check_window(name=\"xkcd_home\", level=1)\n    self.check_window(name=\"github_page\", level=2)\n    self.check_window(name=\"wikipedia_page\", level=3)\n\n    self.check_window(name=\"helloworld\", baseline=True)\n    ### Do something that may change the web page\n    self.check_window(name=\"helloworld\", level=3)\n

    Here's an example where clicking a button makes a hidden element visible:

    from seleniumbase import BaseCase\nBaseCase.main(__name__, __file__)\n\nclass VisualLayoutTest(BaseCase):\n    def test_applitools_layout_change_failure(self):\n        self.open('https://applitools.com/helloworld?diff1')\n        print('\\nCreating baseline in \"visual_baseline\" folder.')\n        self.check_window(name=\"helloworld\", baseline=True)\n        # Click a button that changes the text of an element\n        self.click('a[href=\"?diff1\"]')\n        # Click a button that makes a hidden element visible\n        self.click(\"button\")\n        self.check_window(name=\"helloworld\", level=3)\n

    Here's the output of that: (Text changes do not impact visual comparisons)

    AssertionError:\nFirst differing element 39:\n['div', [['class', ['section', 'hidden-section', 'image-section']]]]\n['div', [['class', ['section', 'image-section']]]]\n\n-  ['div', [['class', ['section', 'hidden-section', 'image-section']]]],\n?                                ------------------\n+  ['div', [['class', ['section', 'image-section']]]],\n*\n*** Exception: <Level 3> Visual Diff Failure:\n* HTML tag attribute values don't match the baseline!\n

    Here's an example where a button is removed from a web page:

    from seleniumbase import BaseCase\nBaseCase.main(__name__, __file__)\n\nclass VisualLayoutTest(BaseCase):\n    def test_python_home_layout_change_failure(self):\n        self.open('https://python.org/')\n        print('\\nCreating baseline in \"visual_baseline\" folder.')\n        self.check_window(name=\"python_home\", baseline=True)\n        # Remove the \"Donate\" button\n        self.remove_element('a.donate-button')\n        self.check_window(name=\"python_home\", level=3)\n

    Here's the output of that:

    AssertionError:\nFirst differing element 33:\n['a', [['class', ['donate-button']], ['href', '/psf/donations/']]]\n['div', [['class', ['options-bar']]]]\n\n-  ['a', [['class', ['donate-button']], ['href', '/psf/donations/']]],\n-     'display: list-item; opacity: 0.995722;']]],\n?                         -------------------\n+     'display: list-item;']]],\n*\n*** Exception: <Level 3> Visual Diff Failure:\n* HTML tag attribute values don't match the baseline!\n

    Here's the side_by_side.html file for that, (from the ./latest_logs/ folder), which shows a visual comparison of the two screenshots as a result of the missing \"Donate\" button:

    Here's another example, where a web site logo is resized:

    from seleniumbase import BaseCase\nBaseCase.main(__name__, __file__)\n\nclass VisualLayoutTest(BaseCase):\n    def test_xkcd_layout_change_failure(self):\n        self.open('https://xkcd.com/554/')\n        print('\\nCreating baseline in \"visual_baseline\" folder.')\n        self.check_window(name=\"xkcd_554\", baseline=True)\n        # Change height: (83 -> 130) , Change width: (185 -> 120)\n        self.set_attribute('[alt=\"xkcd.com logo\"]', \"height\", \"130\")\n        self.set_attribute('[alt=\"xkcd.com logo\"]', \"width\", \"120\")\n        self.check_window(name=\"xkcd_554\", level=3)\n

    Here's the output of that:

    AssertionError:\nFirst differing element 22:\n['img[30 chars]['height', '83'], ['src', '/s/0b7742.png'], ['width', '185']]]\n['img[30 chars]['height', '130'], ['src', '/s/0b7742.png'], ['width', '120']]]\n\n-    ['height', '83'],\n?                ^\n+    ['height', '130'],\n?                ^ +\n-    ['width', '185']]],\n?                ^^\n+    ['width', '120']]],\n?                ^^\n*\n*** Exception: <Level 3> Visual Diff Failure:\n* HTML tag attribute values don't match the baseline!\n

    To run the example (from examples/visual_testing/) with a pytest HTML Report, use:

    pytest test_layout_fail.py --html=report.html\n

    Here's what the pytest HTML Report looks like:

    In conclusion, open source automated visual testing tools are being built directly into test frameworks, and this trend is growing. Just like many years ago when free Wi-Fi at coffee shops replaced Internet cafes that charged money for Internet access, open source tools for visual testing will replace their paid counterparts in time. You'll remember this next time you're sipping your Starbucks\u00ae Pumpkin Spice Latte with your free Internet access, instead of paying for Internet at cybercafes.

    "}, {"location": "help_docs/ReadMe/", "title": "\ud83d\udcd1 Table of Contents", "text": ""}, {"location": "help_docs/ReadMe/#help-docs", "title": "Help Docs", "text": "

    \ud83d\ude80 Start | \ud83d\udcca Dashboard \ud83c\udff0 Features | \ud83c\udf9b\ufe0f Options \ud83d\udcda Examples | \ud83d\udcf1 Emulator \ud83c\udf20 Console Scripts | \ud83c\udf10 Grid \ud83d\udcd8 Methods / APIs | \ud83d\ude8e Tours \ud83d\udd21 Syntax Formats | \ud83e\udd16 CI/CD \u267b\ufe0f Boilerplates | \ud83d\uddfe Locale Codes \ud83d\udd79\ufe0f JS Manager | \ud83d\uddbc\ufe0f Visual Testing \ud83c\udf0f Translator | \ud83d\udec2 Dialog Boxes \ud83d\udd34 Recorder | \ud83d\ude9d Migrate \ud83c\udf9e\ufe0f Slides | \ud83d\udcf6 Charts

    Table of Contents (seleniumbase.io) Features List Command Line Tutorial Usage Examples Demo Page for Tests How SeleniumBase Works Installing Python, Pip, & Git Python Virtual Env Tutorial SeleniumBase Installation Webdriver Installation Verify Webdriver Works Console Scripts Tutorial The Dashboard Recorder Mode pytest Commander Syntax Formats Behave BDD Behave Commander Mobile Device Testing Method Summary (API Ref) Case Plans Language Translations Language Locale Codes JS Package Manager Tour Examples Presentation Maker Chart Maker Handling iframes MySQL Installation Overview Using the Selenium Grid Browser Desired Capabilities Safari Driver Detailed Info Seeing Hidden Files on macOS Case Studies Demo Pages / Web Examples Demo Page (Test Page) MFA Login (Test Page) TinyMCE (Test Page) Error Page (Test Page) Drag-&-Drop (Test Page) Device Farm (Virtual) HTML Playground Page SeleniumBase in iframe Page with broken links Shadow DOM/Root W3Schools iframes W3Schools file upload W3Schools doubleclick W3Schools drag & drop W3Schools checkboxes W3Schools radio buttons Presentations Presenter Demo Core Presentation Chart Maker Demo Python Virtual Envs GitHub Pages (seleniumbase.dev) Features List Command Line Tutorial Usage Examples How SeleniumBase Works Installing Python, Pip, & Git Python Virtual Env Tutorial SeleniumBase Installation Webdriver Installation Verify Webdriver Works Console Scripts Tutorial The Dashboard Recorder Mode pytest Commander Syntax Formats Behave BDD Behave Commander Mobile Device Testing Method Summary (API Ref) Case Plans Language Translations Language Locale Codes JS Package Manager Tour Examples Presentation Maker Chart Maker Handling iframes MySQL Installation Overview Using the Selenium Grid Browser Desired Capabilities Safari Driver Detailed Info Seeing Hidden Files on macOS Case Studies

    "}, {"location": "help_docs/behave_gui/", "title": "\ud83d\udc1d Behave-BDD GUI App", "text": ""}, {"location": "help_docs/behave_gui/#seleniumbase-behave-gui-commander", "title": "SeleniumBase Behave GUI / Commander \ud83d\udc1d\ud83c\udf96\ufe0f", "text": "

    \ud83d\udc1d\ud83c\udf96\ufe0f The SeleniumBase Behave GUI lets you run behave scripts from a Desktop GUI.

    \ud83d\udc1d\ud83c\udf96\ufe0f To launch it, call sbase behave-gui or sbase gui-behave:

    > sbase behave-gui\n* Starting the SeleniumBase Behave Commander GUI App...\n

    \ud83d\udc1d\ud83c\udf96\ufe0f SeleniumBase Behave GUI loads the same tests that are found by:

    behave -d\n

    \ud83d\udc1d\ud83c\udf96\ufe0f You can customize which tests are loaded by passing additional args:

    sbase behave-gui [OPTIONAL PATH or TEST FILE]\n

    \ud83d\udc1d\ud83c\udf96\ufe0f Here are examples of customizing test collection:

    sbase behave-gui  # all tests\nsbase behave-gui -i=calculator  # tests with \"calculator\" in the name\nsbase behave-gui features/  # tests located in the \"features/\" folder\nsbase behave-gui features/calculator.feature  # tests in that feature\n

    \ud83d\udc1d\ud83c\udf96\ufe0f Once launched, you can further customize which tests to run and what settings to use. There are various controls for changing settings, modes, and other \"behave\" command line options that are specific to SeleniumBase. You can also set additional options that don't have a visible toggle. When you're ready to run the selected tests with the specified options, click on the Run Selected Tests button.

    \ud83d\udc1d\u26aa With the Dashboard enabled, you'll get one of these:

    To learn more about SeleniumBase, check out the Docs Site:

    All the code is on GitHub:

    "}, {"location": "help_docs/case_plans/", "title": "\ud83d\uddc2\ufe0f Case Plans", "text": ""}, {"location": "help_docs/case_plans/#seleniumbase-case-plans", "title": "SeleniumBase Case Plans \ud83d\uddc2\ufe0fSummary of existing Case Plans", "text": "

    \ud83d\uddc2\ufe0f SeleniumBase Case Plans is Test Case Management Software that uses Markdown tables for displaying test plans directly in GitHub (and other source code management systems that support Markdown format).

    \ud83d\uddc2\ufe0f The case_summary.md file is generated from individual Case Plans that exist in the case_plans/ folders of your repository. (See the example below to learn how the Case Summary file may look.)

    Example of a case_summary.md file:

    \ud83d\udd35 8 Case Plans with customized tables \u2b55 2 Case Plans using boilerplate code \ud83d\udea7 1 Case Plan that is missing a table \ud83d\udd0e (Click rows to expand) \ud83d\udd0d \ud83d\udd35 basic_test.py::MyTestClass::test_basics | # | Step Description | Expected Result | | - | ---------------- | --------------- | | 1 | Log in to https://www.saucedemo.com with ``standard_user``. | Login was successful. | | 2 | Click on the ``Backpack`` ``ADD TO CART`` button. | The button text changed to ``REMOVE``. | | 3 | Click on the cart icon. | The ``Backpack`` is seen in the cart. | | 4 | Remove the ``Backpack`` from the cart. | The ``Backpack`` is no longer in the cart. | | 5 | Log out from the website. | Logout was successful. | \ud83d\udd35 list_assert_test.py::MyTestClass::test_assert_list_of_elements | # | Step Description | Expected Result | | - | ---------------- | --------------- | | 1 | Open https://seleniumbase.io/demo_page. | | | 2 | Use ``self.assert_elements_present(\"head\", \"style\", \"script\")`` to verify that multiple elements are present in the HTML. | The assertion is successful. | | 3 | Use ``self.assert_elements(\"h1\", \"h2\", \"h3\")`` to verify that multiple elements are visible. | The assertion is successful. | | 4 | Use ``self.assert_elements([\"#myDropdown\", \"#myButton\", \"#svgRect\"])`` to verify that multiple elements are visible. | The assertion is successful. | \u2b55 locale_code_test.py::LocaleCodeTests::test_locale_code | # | Step Description | Expected Result | | - | ---------------- | --------------- | | 1 | Perform Action 1 | Verify Action 1 | | 2 | Perform Action 2 | Verify Action 2 | \ud83d\udd35 my_first_test.py::MyTestClass::test_swag_labs | # | Step Description | Expected Result | | - | ---------------- | --------------- | | 1 | Log in to https://www.saucedemo.com with ``standard_user``. | Login was successful. | | 2 | Click on the ``Backpack`` ``ADD TO CART`` button. | The button text changed to ``REMOVE``. | | 3 | Click on the cart icon. | The ``Backpack`` is seen in the cart. | | 4 | Click on the ``CHECKOUT`` button. Enter user details and click ``CONTINUE``. | The ``Backpack`` is seen in the cart on the ``CHECKOUT: OVERVIEW`` page. | | 5 | Click on the ``FINISH`` button. | There is a ``Thank You`` message and a ``Pony Express`` delivery logo. | | 6 | Log out from the website. | Logout was successful. | \u2b55 proxy_test.py::ProxyTests::test_proxy | # | Step Description | Expected Result | | - | ---------------- | --------------- | | 1 | Perform Action 1 | Verify Action 1 | | 2 | Perform Action 2 | Verify Action 2 | \ud83d\udd35 shadow_root_test.py::ShadowRootTest::test_shadow_root | # | Step Description | Expected Result | | - | ---------------- | --------------- | | 1 | Open https://seleniumbase.io/other/shadow_dom. Click each tab and verify the text contained within the Shadow Root sections. | Tab 1 text: ``Content Panel 1`` Tab 2 text: ``Content Panel 2`` Tab 3 text: ``Content Panel 3`` |

    \ud83d\udea7 test_agent.py::UserAgentTests::test_user_agent

    \ud83d\udd35 test_calculator.py::CalculatorTests::test_6_times_7_plus_12_equals_54 | # | Step Description | Expected Result | | - | ---------------- | --------------- | | 1 | Open https://seleniumbase.io/apps/calculator. Perform the following calculation: ``6 \u00d7 7 + 12`` | The output is ``54`` after pressing ``=`` | \ud83d\udd35 test_demo_site.py::DemoSiteTests::test_demo_site | # | Step Description | Expected Result | | - | ---------------- | --------------- | | 1 | Open https://seleniumbase.io/demo_page | | | 2 | Assert the title of the current web page. Assert that a given element is visible on the page. Assert that a text substring appears in an element's text. | The assertions were successful. | | 3 | Type text into various text fields and then verify. | The assertions were successful. | | 4 | Verify that a hover dropdown link changes page text. | The assertion was successful. | | 5 | Verify that a button click changes text on the page. | The assertion was successful. | | 6 | Verify that an SVG element is located on the page. | The assertion was successful. | | 7 | Verify that a slider control updates a progress bar. | The assertion was successful. | | 8 | Verify that a \"select\" option updates a meter bar. | The assertion was successful. | | 9 | Assert an element located inside an iFrame. | The assertion was successful. | | 10 | Assert text located inside an iFrame. | The assertion was successful. | | 11 | Verify that clicking a radio button selects it. | The assertion was successful. | | 12 | Verify that clicking an empty checkbox makes it selected. | The assertion was successful. | | 13 | Verify clicking on multiple elements with one call. | The assertions were successful. | | 14 | Verify that clicking an iFrame checkbox selects it. | The assertions were successful. | | 15 | Verify that Drag and Drop works. | The assertion was successful. | | 16 | Assert link text. | The assertion was successful. | | 17 | Verify clicking on link text. | The action was successful. | | 18 | Assert exact text in an element. | The assertion was successful. | | 19 | Highlight a page element. | The action was successful. | | 20 | Verify that Demo Mode works. | The assertion was successful. | \ud83d\udd35 test_login.py::SwagLabsLoginTests::test_swag_labs_login | # | Step Description | Expected Result | | - | ---------------- | --------------- | | 1 | Log in to https://www.saucedemo.com with ``standard_user``. | Login was successful. | | 2 | Log out from the website. | Logout was successful. | \ud83d\udd35 test_mfa_login.py::TestMFALogin::test_mfa_login | # | Step Description | Expected Result | | - | ---------------- | --------------- | | 1 | Open https://seleniumbase.io/realworld/login Enter credentials and Sign In. | Sign In was successful. | | 2 | Click the ``This Page`` button. Save a screenshot to the logs. | | | 3 | Click to Sign Out | Sign Out was successful. |

    \ud83d\uddc2\ufe0f Before you can generate a case_summary.md file that includes your existing Case Plans, first you'll need to select which existing tests you want to create boilerplate Case Plans from. For that, you can use the SeleniumBase Case Plans GUI:

    sbase caseplans\n

    \ud83d\uddc2\ufe0f Once you are running the Case Plans GUI, select the existing tests that need Case Plans, and then click: Generate boilerplate Case Plans for selected tests missing them. For each selected test that didn't already have a Case Plan file, one will be generated. Each new Case Plan file starts with default boilerplate code with a Markdown table. Eg:

    ``proxy_test.py::ProxyTests::test_proxy``\n---\n| # | Step Description | Expected Result |\n| - | ---------------- | --------------- |\n| 1 | Perform Action 1 | Verify Action 1 |\n| 2 | Perform Action 2 | Verify Action 2 |\n

    \ud83d\uddc2\ufe0f When rendered as a Markdown table, the result looks like this:

    "}, {"location": "help_docs/case_plans/#proxy_testpyproxyteststest_proxy", "title": "proxy_test.py::ProxyTests::test_proxy", "text": "# Step Description Expected Result 1 Perform Action 1 Verify Action 1 2 Perform Action 2 Verify Action 2

    \ud83d\uddc2\ufe0f Markdown tables are flexible, but must be constructed correctly to be displayed. For a Markdown table to render, it's important that you place pipes (|), dashes (-), and spaces in the correct locations. If you want a line break in a step, use <br />. If you want an empty step, put a space between pipes, eg: | |.

    \ud83d\uddc2\ufe0f Here's an example of a Case Plan for my_first_test.py:

    "}, {"location": "help_docs/case_plans/#my_first_testpymytestclasstest_swag_labs", "title": "my_first_test.py::MyTestClass::test_swag_labs", "text": "# Step Description Expected Result 1 Log in to https://www.saucedemo.com with standard_user. Login was successful. 2 Click on the Backpack ADD TO CART button. The button text changed to REMOVE. 3 Click on the cart icon. The Backpack is seen in the cart. 4 Click on the CHECKOUT button. Enter user details and click CONTINUE. The Backpack is seen in the cart on the CHECKOUT: OVERVIEW page. 5 Click on the FINISH button. There is a Thank you message. 6 Log out from the website. Logout was successful.

    \ud83d\uddc2\ufe0f After you've created some Case Plans, you can use the Generate Summary of existing Case Plans button in the Case Plans GUI to generate the Case Plans Summary file.

    \ud83d\uddc2\ufe0f The generated Case Plans summary file, case_summary.md, gets created in the same location where the Case Plans GUI was launched. This is NOT the same location where individual Case Plan boilerplates are generated, which is in the case_plans/ folders. The case_plans/ folders are generated where individual tests live, which means that if you have your tests in multiple folders, then you could also have multiple case_plans/ folders. A case_summary.md file may look like this when rendered:

    \ud83d\uddc2\ufe0f When calling sbase caseplans, you can provide additional arguments to limit the tests that appear in the list. The same discovery rules apply as when using pytest. Eg:

    sbase caseplans\nsbase caseplans -k agent\nsbase caseplans -m marker2\nsbase caseplans test_suite.py\nsbase caseplans offline_examples/\n
    To learn more about SeleniumBase, check out the Docs Site:

    All the code is on GitHub:

    "}, {"location": "help_docs/commander/", "title": "\ud83c\udf96\ufe0f GUI / Commander", "text": ""}, {"location": "help_docs/commander/#seleniumbase-commander", "title": "SeleniumBase Commander \ud83c\udf96\ufe0f", "text": "

    \ud83c\udf96\ufe0f SeleniumBase Commander lets you run pytest scripts from a Desktop GUI.

    \ud83c\udf96\ufe0f To launch it, call sbase commander or sbase gui:

    sbase gui\n* Starting the SeleniumBase Commander Desktop App...\n

    \ud83c\udf96\ufe0f SeleniumBase Commander loads the same tests that are found by:

    pytest --co -q\n

    \ud83c\udf96\ufe0f You can customize which tests are loaded by passing additional args:

    sbase commander [OPTIONAL PATH or TEST FILE]\nsbase gui [OPTIONAL PATH or TEST FILE]\n

    \ud83c\udf96\ufe0f Here are examples of customizing test collection:

    sbase gui\nsbase gui -k agent\nsbase gui -m marker2\nsbase gui test_suite.py\nsbase gui offline_examples/\n

    \ud83c\udf96\ufe0f Once launched, you can further customize which tests to run and what settings to use. There are various controls for changing settings, modes, and other pytest command line options that are specific to SeleniumBase. You can also set additional options that don't have a visible toggle. When you're ready to run the selected tests with the specified options, click on the Run Selected Tests button.

    Other SeleniumBase Commanders:

    To learn more about SeleniumBase, check out the Docs Site:

    All the code is on GitHub:

    "}, {"location": "help_docs/customizing_test_runs/", "title": "\ud83c\udf9b\ufe0f Command Line Options", "text": ""}, {"location": "help_docs/customizing_test_runs/#pytest-options-for-seleniumbase", "title": "pytest options for SeleniumBase", "text": "

    \ud83c\udf9b\ufe0f SeleniumBase's pytest plugin lets you customize test runs from the CLI (Command-Line Interface), which adds options for setting/enabling the browser type, Dashboard Mode, Demo Mode, Headless Mode, Mobile Mode, Multi-threading Mode, Recorder Mode, reuse-session mode, proxy config, user agent config, browser extensions, html-report mode, and more.

    \ud83c\udf9b\ufe0f Here are some examples of configuring tests, which can be run from the examples/ folder:

    # Run a test in Chrome (default browser)\npytest my_first_test.py\n\n# Run a test in Firefox\npytest test_swag_labs.py --firefox\n\n# Run a test in Demo Mode (highlight assertions)\npytest test_demo_site.py --demo\n\n# Run a test in Headless Mode (invisible browser)\npytest test_demo_site.py --headless\n\n# Run tests multi-threaded using [n] threads\npytest test_suite.py -n4\n\n# Reuse the browser session for all tests (\"--reuse-session\")\npytest test_suite.py --rs\n\n# Reuse the browser session, but erase cookies between tests\npytest test_suite.py --rs --crumbs\n\n# Create a real-time dashboard for test results\npytest test_suite.py --dashboard\n\n# Create a pytest html report after tests are done\npytest test_suite.py --html=report.html\n\n# Activate Debug Mode on failures (\"c\" to continue)\npytest test_fail.py --pdb -s\n\n# Rerun failing tests more times\npytest test_suite.py --reruns=1\n\n# Activate Debug Mode as the test begins (\"n\": next. \"c\": continue)\npytest test_null.py --trace -s\n\n# Activate Recorder/Debug Mode as the test begins (\"c\" to continue)\npytest test_null.py --recorder --trace -s\n\n# Pass extra data into tests (retrieve by calling self.data)\npytest my_first_test.py --data=\"ABC,DEF\"\n\n# Run tests on a local Selenium Grid\npytest test_suite.py --server=\"127.0.0.1\"\n\n# Run tests on a remote Selenium Grid\npytest test_suite.py --server=IP_ADDRESS --port=4444\n\n# Run tests on a remote Selenium Grid with authentication\npytest test_suite.py --server=USERNAME:KEY@IP_ADDRESS --port=80\n\n# Run tests through a proxy server\npytest proxy_test.py --proxy=IP_ADDRESS:PORT\n\n# Run tests through a proxy server with authentication\npytest proxy_test.py --proxy=USERNAME:PASSWORD@IP_ADDRESS:PORT\n\n# Run tests while setting the web browser's User Agent\npytest user_agent_test.py --agent=\"USER-AGENT-STRING\"\n\n# Run tests using Chrome's mobile device emulator (default settings)\npytest test_swag_labs.py --mobile\n\n# Run mobile tests specifying CSS Width, CSS Height, and Pixel-Ratio\npytest test_swag_labs.py --mobile --metrics=\"360,640,2\"\n\n# Run a test with an option to evade bot-detection services\npytest verify_undetected.py --uc\n\n# Run tests while changing SeleniumBase default settings\npytest my_first_test.py --settings-file=custom_settings.py\n

    \ud83c\udf9b\ufe0f You can interchange pytest with nosetests for most tests, but using pytest is recommended. (chrome is the default browser if not specified.)

    \ud83c\udf9b\ufe0f If you're using pytest for running tests outside of the SeleniumBase repo, you'll want a copy of pytest.ini at the base of the new folder structure. If using nosetests, the same applies for setup.cfg.

    \ud83c\udf9b\ufe0f Here are some useful command-line options that come with pytest:

    -v  # Verbose mode. Prints the full name of each test and shows more details.\n-q  # Quiet mode. Print fewer details in the console output when running tests.\n-x  # Stop running the tests after the first failure is reached.\n--html=report.html  # Creates a detailed pytest-html report after tests finish.\n--co | --collect-only  # Show what tests would get run. (Without running them)\n--co -q  # (Both options together!) - Do a dry run with full test names shown.\n-n=NUM  # Multithread the tests using that many threads. (Speed up test runs!)\n-s  # See print statements. (Should be on by default with pytest.ini present.)\n--junit-xml=report.xml  # Creates a junit-xml report after tests finish.\n--pdb  # If a test fails, enter Post Mortem Debug Mode. (Don't use with CI!)\n--trace  # Enter Debug Mode at the beginning of each test. (Don't use with CI!)\n-m=MARKER  # Run tests with the specified pytest marker.\n

    \ud83c\udf9b\ufe0f SeleniumBase provides additional pytest command-line options for tests:

    --browser=BROWSER  # (The web browser to use. Default: \"chrome\".)\n--chrome  # (Shortcut for \"--browser=chrome\". On by default.)\n--edge  # (Shortcut for \"--browser=edge\".)\n--firefox  # (Shortcut for \"--browser=firefox\".)\n--safari  # (Shortcut for \"--browser=safari\".)\n--settings-file=FILE  # (Override default SeleniumBase settings.)\n--env=ENV  # (Set the test env. Access with \"self.env\" in tests.)\n--account=STR  # (Set account. Access with \"self.account\" in tests.)\n--data=STRING  # (Extra test data. Access with \"self.data\" in tests.)\n--var1=STRING  # (Extra test data. Access with \"self.var1\" in tests.)\n--var2=STRING  # (Extra test data. Access with \"self.var2\" in tests.)\n--var3=STRING  # (Extra test data. Access with \"self.var3\" in tests.)\n--variables=DICT  # (Extra test data. Access with \"self.variables\".)\n--user-data-dir=DIR  # (Set the Chrome user data directory to use.)\n--protocol=PROTOCOL  # (The Selenium Grid protocol: http|https.)\n--server=SERVER  # (The Selenium Grid server/IP used for tests.)\n--port=PORT  # (The Selenium Grid port used by the test server.)\n--cap-file=FILE  # (The web browser's desired capabilities to use.)\n--cap-string=STRING  # (The web browser's desired capabilities to use.)\n--proxy=SERVER:PORT  # (Connect to a proxy server:port as tests are running)\n--proxy=USERNAME:PASSWORD@SERVER:PORT  # (Use an authenticated proxy server)\n--proxy-bypass-list=STRING # (\";\"-separated hosts to bypass, Eg \"*.foo.com\")\n--proxy-pac-url=URL  # (Connect to a proxy server using a PAC_URL.pac file.)\n--proxy-pac-url=USERNAME:PASSWORD@URL  # (Authenticated proxy with PAC URL.)\n--proxy-driver  # (If a driver download is needed, will use: --proxy=PROXY.)\n--multi-proxy  # (Allow multiple authenticated proxies when multi-threaded.)\n--agent=STRING  # (Modify the web browser's User-Agent string.)\n--mobile  # (Use the mobile device emulator while running tests.)\n--metrics=STRING  # (Set mobile metrics: \"CSSWidth,CSSHeight,PixelRatio\".)\n--chromium-arg=\"ARG=N,ARG2\"  # (Set Chromium args, \",\"-separated, no spaces.)\n--firefox-arg=\"ARG=N,ARG2\"  # (Set Firefox args, comma-separated, no spaces.)\n--firefox-pref=SET  # (Set a Firefox preference:value set, comma-separated.)\n--extension-zip=ZIP  # (Load a Chrome Extension .zip|.crx, comma-separated.)\n--extension-dir=DIR  # (Load a Chrome Extension directory, comma-separated.)\n--binary-location=PATH  # (Set path of the Chromium browser binary to use.)\n--driver-version=VER  # (Set the chromedriver or uc_driver version to use.)\n--sjw  # (Skip JS Waits for readyState to be \"complete\" or Angular to load.)\n--pls=PLS  # (Set pageLoadStrategy on Chrome: \"normal\", \"eager\", or \"none\".)\n--headless  # (Run tests in headless mode. The default arg on Linux OS.)\n--headless2  # (Use the new headless mode, which supports extensions.)\n--headed  # (Run tests in headed/GUI mode on Linux OS, where not default.)\n--xvfb  # (Run tests using the Xvfb virtual display server on Linux OS.)\n--locale=LOCALE_CODE  # (Set the Language Locale Code for the web browser.)\n--interval=SECONDS  # (The autoplay interval for presentations & tour steps)\n--start-page=URL  # (The starting URL for the web browser when tests begin.)\n--archive-logs  # (Archive existing log files instead of deleting them.)\n--archive-downloads  # (Archive old downloads instead of deleting them.)\n--time-limit=SECONDS  # (Safely fail any test that exceeds the time limit.)\n--slow  # (Slow down the automation. Faster than using Demo Mode.)\n--demo  # (Slow down and visually see test actions as they occur.)\n--demo-sleep=SECONDS  # (Set the wait time after Slow & Demo Mode actions.)\n--highlights=NUM  # (Number of highlight animations for Demo Mode actions.)\n--message-duration=SECONDS  # (The time length for Messenger alerts.)\n--check-js  # (Check for JavaScript errors after page loads.)\n--ad-block  # (Block some types of display ads from loading.)\n--block-images  # (Block images from loading during tests.)\n--do-not-track  # (Indicate to websites that you don't want to be tracked.)\n--verify-delay=SECONDS  # (The delay before MasterQA verification checks.)\n--recorder  # (Enables the Recorder for turning browser actions into code.)\n--rec-behave  # (Same as Recorder Mode, but also generates behave-gherkin.)\n--rec-sleep  # (If the Recorder is enabled, also records self.sleep calls.)\n--rec-print  # (If the Recorder is enabled, prints output after tests end.)\n--disable-js  # (Disable JavaScript on websites. Pages might break!)\n--disable-csp  # (Disable the Content Security Policy of websites.)\n--disable-ws  # (Disable Web Security on Chromium-based browsers.)\n--enable-ws  # (Enable Web Security on Chromium-based browsers.)\n--enable-sync  # (Enable \"Chrome Sync\" on websites.)\n--uc | --undetected  # (Use undetected-chromedriver to evade bot-detection.)\n--uc-cdp-events  # (Capture CDP events when running in \"--undetected\" mode.)\n--remote-debug  # (Sync to Chrome Remote Debugger chrome://inspect/#devices)\n--final-debug  # (Enter Debug Mode after each test ends. Don't use with CI!)\n--dashboard  # (Enable the SeleniumBase Dashboard. Saved at: dashboard.html)\n--dash-title=STRING  # (Set the title shown for the generated dashboard.)\n--enable-3d-apis  # (Enables WebGL and 3D APIs.)\n--swiftshader  # (Use Chrome's \"--use-gl=swiftshader\" feature.)\n--incognito  # (Enable Chrome's Incognito mode.)\n--guest  # (Enable Chrome's Guest mode.)\n--dark  # (Enable Chrome's Dark mode.)\n--devtools  # (Open Chrome's DevTools when the browser opens.)\n--rs | --reuse-session  # (Reuse browser session for all tests.)\n--rcs | --reuse-class-session  # (Reuse session for tests in class.)\n--crumbs  # (Delete all cookies between tests reusing a session.)\n--disable-beforeunload  # (Disable the \"beforeunload\" event on Chrome.)\n--window-size=WIDTH,HEIGHT  # (Set the browser's starting window size.)\n--maximize  # (Start tests with the browser window maximized.)\n--screenshot  # (Save a screenshot at the end of each test.)\n--no-screenshot  # (No screenshots saved unless tests directly ask it.)\n--visual-baseline  # (Set the visual baseline for Visual/Layout tests.)\n--wire  # (Use selenium-wire's webdriver for replacing selenium webdriver.)\n--external-pdf  # (Set Chromium \"plugins.always_open_pdf_externally\":True.)\n--timeout-multiplier=MULTIPLIER  # (Multiplies the default timeout values.)\n--list-fail-page  # (After each failing test, list the URL of the failure.)\n

    (For more details, see the full list of command-line options here.)

    \ud83c\udf9b\ufe0f You can also view a list of popular pytest options for SeleniumBase by typing:

    seleniumbase options\n

    Or the short form:

    sbase options\n
    Example tests using Logging:

    To see logging abilities, you can run a test suite that includes tests that fail on purpose:

    pytest test_suite.py\n

    \ud83d\udd35 During test failures, logs and screenshots from the most recent test run will get saved to the latest_logs/ folder. If --archive-logs is specified (or if ARCHIVE_EXISTING_LOGS is set to True in settings.py), test logs will also get archived to the archived_logs/ folder. Otherwise, the log files will be cleaned out when the next test run begins (by default).

    Demo Mode:

    \ud83d\udd35 If any test is moving too fast for your eyes to see what's going on, you can run it in Demo Mode by adding --demo on the command line, which pauses the browser briefly between actions, highlights page elements being acted on, and lets you know what test assertions are happening in real time:

    pytest my_first_test.py --demo\n

    \ud83d\udd35 You can override the default wait time by either updating settings.py or by using --demo-sleep=NUM when using Demo Mode. (NOTE: If you use --demo-sleep=NUM without using --demo, nothing will happen.)

    pytest my_first_test.py --demo --demo-sleep=1.2\n
    Passing additional data to tests:

    If you want to pass additional data from the command line to your tests, you can use --data=STRING. Now inside your tests, you can use self.data to access that.

    Running tests multithreaded:

    To run pytest with multiple processes, add -n=NUM, -n NUM, or -nNUM on the command line, where NUM is the number of CPUs you want to use.

    pytest -n=8\npytest -n 8\npytest -n8\n
    How to retry failing tests automatically:

    You can use pytest --reruns=NUM to retry failing tests that many times. Add --reruns-delay=SECONDS to wait that many seconds between retries. Example:

    pytest --reruns=1 --reruns-delay=1\n
    Debugging tests:

    \ud83d\udd35 You can use the following calls in your scripts to help you debug issues:

    import time; time.sleep(5)  # Makes the test wait and do nothing for 5 seconds.\nimport pdb; pdb.set_trace()  # Debug Mode. n: next, c: continue, s: step, u: up, d: down.\nimport pytest; pytest.set_trace()  # Debug Mode. n: next, c: continue, s: step, u: up, d: down.\n

    \ud83d\udd35 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:

    pytest test_fail.py --pdb\n

    \ud83d\udd35 To start tests in Debug Mode, add --trace as a pytest option:

    pytest test_coffee_cart.py --trace\n

    (pdb commands: n, c, s, u, d => next, continue, step, up, down).

    Combinations of options:

    \ud83c\udf9b\ufe0f There are times when you'll want to combine various command-line options for added effect. For instance, the multi-process option, -n8, can be customized by adding: --dist=loadscope or --dist=loadfile to it. There's more info on that here: pytest-xdist:

    \u25b6\ufe0f -n8 --dist=loadgroup (click to expand)
    @pytest.mark.xdist_group(name=\"group1\")\ndef test_1():\n    pass\n\nclass Test:\n    @pytest.mark.xdist_group(\"group1\")\n    def test_2():\n        pass\n

    This makes test_1 and Test::test_2 run in the same worker. Tests without the xdist_group mark are distributed normally.

    \ud83c\udf9b\ufe0f You might also want to combine multiple options at once. For example:

    pytest --headless -n8 --dashboard --html=report.html -v --rs --crumbs\n

    The above not only runs tests in parallel processes, but it also tells tests in the same process to share the same browser session, runs the tests in headless mode, displays the full name of each test on a separate line, creates a realtime dashboard of the test results, and creates a full report after all tests complete.

    The SeleniumBase Dashboard:

    \ud83d\udd35 The --dashboard option for pytest generates a SeleniumBase Dashboard located at dashboard.html, which updates automatically as tests run and produce results. Example:

    pytest --dashboard --rs --headless\n

    \ud83d\udd35 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:

    python -m http.server 1948\n

    \ud83d\udd35 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.)

    \ud83d\udd35 Here's a full example of what the SeleniumBase Dashboard may look like:

    pytest test_suite.py --dashboard --rs --headless\n

    Pytest Reports:

    \ud83d\udd35 Using --html=report.html gives you a fancy report of the name specified after your test suite completes.

    pytest test_suite.py --html=report.html\n

    \ud83d\udd35 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.

    \ud83d\udd35 Here's an example of an upgraded html report:

    pytest test_suite.py --dashboard --html=report.html\n

    If viewing pytest html reports in Jenkins, you may need to configure Jenkins settings for the html to render correctly. This is due to Jenkins CSP changes.

    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.

    pytest test_suite.py --junit-xml=report.xml\n
    Nosetest Reports:

    The --report option gives you a fancy report after your test suite completes.

    nosetests test_suite.py --report\n

    (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.)

    Language Locale Codes

    You can specify a Language Locale Code to customize web pages on supported websites. With SeleniumBase, you can change the web browser's Locale on the command line by doing this:

    pytest --locale=CODE  # Example: --locale=ru\n

    Visit \ud83d\uddfe Locales for a full list of codes.

    Customizing default settings:

    \ud83c\udf9b\ufe0f An easy way to override seleniumbase/config/settings.py is by using a custom settings file. Here's the command-line option to add to tests: (See examples/custom_settings.py)

    pytest --settings-file=custom_settings.py\n

    (Settings include default timeout values, a two-factor auth key, DB credentials, S3 credentials, and other important settings used by tests.)

    Running tests on a remote Selenium Grid:

    \ud83c\udf10 SeleniumBase lets you run tests on remote Selenium Grids such as BrowserStack's Selenium Grid, LambdaTest's Selenium Grid, Sauce Labs's Selenium Grid, other Grids, and even your own Grid:

    \ud83c\udf10 For setting browser desired capabilities while running Selenium remotely, see the ReadMe located here: https://github.com/seleniumbase/SeleniumBase/tree/master/examples/capabilities

    Here's how to connect to a BrowserStack Selenium Grid server for running tests:

    pytest test_demo_site.py --server=USERNAME:KEY@hub.browserstack.com --port=80\n

    Here's how to connect to a Sauce Labs Selenium Grid server for running tests:

    pytest test_demo_site.py --server=USERNAME:KEY@ondemand.us-east-1.saucelabs.com --port=443 --protocol=https\n

    Here's how to connect to a Perfecto Selenium Grid server for running tests:

    pytest test_demo_site.py --server=USERNAME:KEY@demo.perfectomobile.com/nexperience/perfectomobile --port=443\n

    Here's how to connect to a TestingBot Selenium Grid server for running tests:

    pytest test_demo_site.py --server=USERNAME:KEY@hub.testingbot.com --port=80\n

    Here's how to connect to a LambdaTest Selenium Grid server for running tests:

    pytest test_demo_site.py --server=USERNAME:KEY@hub.lambdatest.com --port=80\n

    Here's how to connect to a CrossBrowserTesting Selenium Grid server for running tests:

    pytest test_demo_site.py --server=USERNAME:KEY@hub.crossbrowsertesting.com --port=80\n

    \ud83c\udf10 Or you can create your own Selenium Grid for test distribution. (See this ReadMe for details)

    \ud83c\udf10 To use a server on the https protocol, add --protocol=https: (Now automatic if the port is 443.)

    pytest test_demo_site.py --protocol=https --server=IP_ADDRESS --port=PORT\n
    Using a Proxy Server:

    \ud83c\udf10 If you wish to use a proxy server for your browser tests (Chromium or Firefox), you can add --proxy=IP_ADDRESS:PORT as an argument on the command line.

    pytest proxy_test.py --proxy=IP_ADDRESS:PORT\n

    \ud83c\udf10 If the proxy server that you wish to use requires authentication, you can do the following (Chromium only):

    pytest proxy_test.py --proxy=USERNAME:PASSWORD@IP_ADDRESS:PORT\n

    \ud83c\udf10 SeleniumBase also supports SOCKS4 and SOCKS5 proxies:

    pytest proxy_test.py --proxy=\"socks4://IP_ADDRESS:PORT\"\n\npytest proxy_test.py --proxy=\"socks5://IP_ADDRESS:PORT\"\n

    To make things easier, you can add your frequently-used proxies to PROXY_LIST in proxy_list.py, and then use --proxy=KEY_FROM_PROXY_LIST to use the IP_ADDRESS:PORT of that key.

    pytest proxy_test.py --proxy=proxy1\n
    Changing the User-Agent:

    \ud83d\udd24 If you wish to change the User-Agent for your browser tests (Chrome and Firefox only), you can add --agent=\"USER-AGENT-STRING\" as an argument on the command line.

    pytest user_agent_test.py --agent=\"Mozilla/5.0 (Nintendo 3DS; U; ; en) Version/1.7412.EU\"\n
    Mobile Device Testing:

    \ud83d\udcf1 Use --mobile to quickly run your tests using Chrome's mobile device emulator with default values for device metrics (CSS Width, CSS Height, Pixel-Ratio) and a default value set for the user agent. To configure the mobile device metrics, use --metrics=\"CSS_Width,CSS_Height,Pixel_Ratio\" to set those values. You'll also be able to set the user agent with --agent=\"USER-AGENT-STRING\" (a default user agent will be used if not specified). To find real values for device metrics, see this GitHub Gist. For a list of available user agent strings, check out this page.

    # Run tests using Chrome's mobile device emulator (default settings)\npytest test_swag_labs.py --mobile\n\n# Run mobile tests specifying CSS Width, CSS Height, and Pixel-Ratio\npytest test_swag_labs.py --mobile --metrics=\"411,731,3\"\n\n# Run mobile tests specifying the user agent\npytest test_swag_labs.py --mobile --agent=\"Mozilla/5.0 (Linux; Android 9; Pixel 3 XL)\"\n

    "}, {"location": "help_docs/demo_mode/", "title": "\ud83c\udfa6 Demo Mode", "text": ""}, {"location": "help_docs/demo_mode/#demo-mode", "title": "Demo Mode \ud83c\udfa6", "text": "

    \ud83d\udd35 Demo Mode helps you see what a test is doing.

    \ud83c\udfc7\ud83d\udca8 \ud83d\udc40 If a test runs too fast for your eyes, use Demo Mode to slow it down, highlight actions, and display assertions. Example usage:

    pytest my_first_test.py --demo\n

    Here's how to run test_swag_labs.py from examples/ in Demo Mode:

    pytest test_swag_labs.py --demo\n

    Here's an example that only uses the highlight() method for highlighting browser actions:

    (test_error_page.py from examples/)

    pytest test_error_page.py\n

    Here's an example of a mobile test in Demo Mode:

    "}, {"location": "help_docs/desired_capabilities/", "title": "\ud83d\udcc3 Desired Capabilities", "text": ""}, {"location": "help_docs/desired_capabilities/#using-desired-capabilities", "title": "Using Desired Capabilities", "text": "

    You can specify browser capabilities when running SeleniumBase tests on a remote Selenium Grid server such as BrowserStack, LambdaTest, or Sauce Labs.

    Sample run commands may look like this when run from the SeleniumBase/examples/ folder: (The browser is now specified in the capabilities file.)

    pytest test_demo_site.py --browser=remote --server=USERNAME:KEY@hub.browserstack.com --port=80 --cap_file=capabilities/sample_cap_file_BS.py\n
    pytest test_demo_site.py --browser=remote --server=USERNAME:KEY@https://@hub.lambdatest.com --port=80 --protocol=https --cap_file=capabilities/sample_cap_file_LT.py\n
    pytest test_demo_site.py --browser=remote --server=USERNAME:KEY@ondemand.us-east-1.saucelabs.com --port=443 --protocol=https --cap_file=capabilities/sample_cap_file_SL.py\n

    (Parameters: --browser=remote, --server=SERVER, --port=PORT, and --cap_file=CAP_FILE.py)

    Here's an example desired capabilities file for BrowserStack:

    desired_cap = {\n    \"os\" : \"Windows\",\n    \"os_version\" : \"11\",\n    \"browser\" : \"Chrome\",\n    \"browser_version\" : \"101.0\",\n    \"browserstack.local\" : \"false\",\n    \"browserstack.debug\" : \"true\",\n    \"browserstack.selenium_version\" : \"4.1.2\",\n}\n

    Here's an example desired capabilities file for LambdaTest:

    capabilities = {\n    \"build\" : \"your build name\",\n    \"name\" : \"your test name\",\n    \"platform\" : \"Windows 11\",\n    \"browserName\" : \"Chrome\",\n    \"version\" : \"101.0\",\n    \"timezone\" : \"UTC+05:30\",\n    \"geoLocation\" : \"IN\",\n}\n

    Here's an example desired capabilities file for Sauce Labs:

    capabilities = {\n    \"browserName\": \"chrome\",\n    \"browserVersion\": \"latest\",\n    \"platformName\": \"macOS 10.14\",\n    \"sauce:options\": {},\n}\n

    (Note that the browser is now being specified in the capabilities file, rather than with --browser=BROWSER when using a remote Selenium Grid. If using a local Selenium Grid, specify the browser, eg: --browser=chrome or --browser=firefox.)

    You can generate specific desired capabilities using: Parsing desired capabilities:

    SeleniumBase has a desired capabilities parser that can capture all lines from the specified file in the following formats:

    'KEY': 'VALUE'\n'KEY': True\n'KEY': False\ncaps['KEY'] = \"VALUE\"\ncaps['KEY'] = True\ncaps['KEY'] = False\n

    (Each pair must be on a separate line. You can interchange single and double quotes.)

    You can also swap --browser=remote with an actual browser, eg --browser=chrome, which will combine the default SeleniumBase desired capabilities with those that were specified in the capabilities file when using --cap_file=FILE.py. Capabilities will override other parameters, so if you set the browser to one thing and the capabilities browser to another, SeleniumBase will use the capabilities browser as the browser.

    You'll need default SeleniumBase capabilities for: * Using a proxy server (not the same as a Selenium Grid server) * Downloading files to a desired folder * Disabling some warnings on Chrome * Overriding a website's Content Security Policy on Chrome * Other possible reasons

    You can also set browser desired capabilities from a command line string: Example:

    pytest test_swag_labs.py --cap-string='{\"browserName\":\"chrome\",\"name\":\"test1\"}' --server=\"127.0.0.1\" --browser=remote\n

    (Enclose cap-string in single quotes. Enclose parameter keys in double quotes.)

    If you pass \"*\" into the \"name\" field of --cap-string, the name will become the test identifier. Example:

    pytest my_first_test.py --cap-string='{\"browserName\":\"chrome\",\"name\":\"*\"}' --server=\"127.0.0.1\" --browser=chrome\n

    Example name: \"my_first_test.MyTestClass.test_basics\"

    Using a local Selenium Grid

    If using a local Selenium Grid with SeleniumBase, start up the Grid Hub and nodes first:

    sbase grid-hub start\nsbase grid-node start\n

    (The Selenium Server JAR file will be automatically downloaded for first-time Grid users. You'll also need Java installed to start up the Grid.)

    "}, {"location": "help_docs/features_list/", "title": "\ud83c\udff0 List of Features", "text": ""}, {"location": "help_docs/features_list/#seleniumbase-features", "title": "SeleniumBase Features: \ud83c\udff0", "text": ""}, {"location": "help_docs/handling_iframes/", "title": "\ud83d\uddbc\ufe0f How to handle iframes", "text": ""}, {"location": "help_docs/handling_iframes/#how-to-handle-iframes", "title": "How to handle iframes", "text": "

    \ud83d\uddbc\ufe0f iframes follow the same principle as new windows: You must first switch to the iframe if you want to perform actions in there:

    self.switch_to_frame(\"iframe\")\n# ... Now perform actions inside the iframe\nself.switch_to_parent_frame()  # Exit the current iframe\n

    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().)

    self.switch_to_frame('iframe[name=\"frame1\"]')\nself.switch_to_frame('iframe[name=\"frame2\"]')\n# ... Now perform actions inside the inner iframe\nself.switch_to_default_content()  # Back to the main page\n

    \ud83d\uddbc\ufe0f You can also use a context manager to act inside iframes:

    with self.frame_switch(\"iframe\"):\n    # ... Now perform actions while inside the code block\n# You have left the iframe\n

    This also works with nested iframes:

    with self.frame_switch('iframe[name=\"frame1\"]'):\n    with self.frame_switch('iframe[name=\"frame2\"]'):\n        # ... Now perform actions while inside the code block\n    # You are now back inside the first iframe\n# You have left all the iframes\n

    \ud83d\uddbc\ufe0f In special cases, you may want to set the page to the content of an iframe:

    self.set_content_to_frame(\"iframe\")\n

    To back out of one call of that, use:

    self.set_content_to_parent()\n

    To back out of all nested calls of that, use:

    self.set_content_to_default()\n

    \ud83d\uddbc\ufe0f See examples/iframe_tests.py for tests that use all available iframe commands.

    "}, {"location": "help_docs/happy_customers/", "title": "\ud83d\udccb Case Studies", "text": ""}, {"location": "help_docs/happy_customers/#businesses-who-have-used-seleniumbase", "title": "Businesses who have used SeleniumBase", "text": ""}, {"location": "help_docs/happy_customers/#case-study", "title": "Case Study", "text": "

    HubSpot:

    In addition to using SeleniumBase for testing the UI of their content management system, HubSpot used SeleniumBase to automate the migration of website pages from their old CMS to their new one, which saved them over one million USD and a significant amount of time.

    Learn how HubSpot uses SeleniumBase for website testing by reading: Automated Testing with Selenium

    For more reading about automation at HubSpot, see: The Classic \"QA Team\" is Obsolete

    "}, {"location": "help_docs/happy_customers/#how-is-this-list-generated", "title": "How is this list generated?", "text": "

    Most of these rows come from LinkedIn search results of profile descriptions, where employees mentioned that they have used SeleniumBase at their company. These details may also be found in other public networks and social media sites, such as GitHub (where organizations could have public repos that use SeleniumBase).

    "}, {"location": "help_docs/hidden_files_info/", "title": "\ud83d\udc65 macOS Hidden Files", "text": ""}, {"location": "help_docs/hidden_files_info/#showing-hidden-files-on-macos", "title": "Showing hidden files on macOS", "text": "

    Depending on your macOS settings, some files may be hidden from view in your Finder window, such as .gitignore.

    Press the \u201cCommand\u201d + \u201cShift\u201d + \u201c.\u201d (period) keys at the same time.

    (The hidden files will show up as translucent in the folder. If you want to obscure the files again, press the same \u201cCommand\u201d + \u201cShift\u201d + \u201c.\u201d (period) combination.)

    defaults write com.apple.finder AppleShowAllFiles -bool true\n

    More info on that can be found here:

    "}, {"location": "help_docs/how_it_works/", "title": "\ud83d\udc41\ufe0f How it Works", "text": ""}, {"location": "help_docs/how_it_works/#how-seleniumbase-works", "title": "How SeleniumBase Works \ud83d\udc41\ufe0f", "text": "

    \ud83d\udc41\ufe0f\ud83d\udd0e At the core, SeleniumBase works by extending pytest as a direct plugin. SeleniumBase automatically spins up web browsers for tests (using Selenium WebDriver), and then gives those tests access to the SeleniumBase libraries through the BaseCase class. Tests are also given access to SeleniumBase command-line options and SeleniumBase methods, which provide additional functionality.

    \ud83d\udc41\ufe0f\ud83d\udd0e pytest uses a feature called test discovery to automatically find and run Python methods that start with test_ when those methods are located in Python files that start with test_ or end with _test.py.

    \ud83d\udc41\ufe0f\ud83d\udd0e The most common way of using SeleniumBase is by importing BaseCase:

    from seleniumbase import BaseCase\n

    \ud83d\udc41\ufe0f\ud83d\udd0e This line activates pytest when a file is called directly with python:

    BaseCase.main(__name__, __file__)\n

    \ud83d\udc41\ufe0f\ud83d\udd0e Classes can inherit BaseCase to gain SeleniumBase functionality:

    class MyTestClass(BaseCase):\n

    \ud83d\udc41\ufe0f\ud83d\udd0e Test methods inside BaseCase classes become SeleniumBase tests: (These tests automatically launch a web browser before starting, and quit the web browser after ending. Default settings can be changed via command-line options.)

        def test_abc(self):\n

    \ud83d\udc41\ufe0f\ud83d\udd0e SeleniumBase APIs can be called from tests via self:

            self.open(\"https://example.com\")\n

    \ud83d\udc41\ufe0f\ud83d\udd0e Here's what a full test might look like:

    from seleniumbase import BaseCase\nBaseCase.main(__name__, __file__)\n\nclass TestMFALogin(BaseCase):\n    def test_mfa_login(self):\n        self.open(\"https://seleniumbase.io/realworld/login\")\n        self.type(\"#username\", \"demo_user\")\n        self.type(\"#password\", \"secret_pass\")\n        self.enter_mfa_code(\"#totpcode\", \"GAXG2MTEOR3DMMDG\")  # 6-digit\n        self.assert_text(\"Welcome!\", \"h1\")\n        self.highlight(\"img#image1\")  # A fancier assert_element() call\n        self.click('a:contains(\"This Page\")')  # Use :contains() on any tag\n        self.save_screenshot_to_logs()  # (\"./latest_logs\" folder for test)\n        self.click_link(\"Sign out\")  # Link must be \"a\" tag. Not \"button\".\n        self.assert_element('a:contains(\"Sign in\")')\n        self.assert_exact_text(\"You have been signed out!\", \"#top_message\")\n

    (See the example, test_mfa_login.py, for reference.)

    \ud83d\udc41\ufe0f\ud83d\udd0e Here are some examples of running tests with pytest:

    pytest test_mfa_login.py\npytest --headless -n8 --dashboard --html=report.html -v --rs --crumbs\npytest -m marker2\npytest -k agent\npytest offline_examples/\n

    (See Syntax_Formats for more ways of structuring SeleniumBase tests.)

    "}, {"location": "help_docs/how_it_works/#no-more-flaky-tests", "title": "\u2705 No More Flaky Tests!", "text": "

    SeleniumBase methods automatically wait for page elements to finish loading before interacting with them (up to a timeout limit). This means you no longer need random time.sleep() statements in your scripts.

    There are three layers of protection that provide reliability for tests using SeleniumBase:

    If you want to speed up your tests and you think the third level of protection is enough by itself, you can use command-line options to remove the first, the second, or both of those first two levels of protection:

    "}, {"location": "help_docs/html_inspector/", "title": "\ud83d\udd75\ufe0f The HTML Inspector", "text": ""}, {"location": "help_docs/html_inspector/#the-html-inspector", "title": "The HTML Inspector \ud83d\udd75\ufe0f", "text": "

    \ud83d\udd75\ufe0f HTML Inspector provides useful info about a web page.

    \ud83d\udd75\ufe0f (Based on: github.com/philipwalton/html-inspector)

    \ud83d\udd75\ufe0f Example: examples/test_inspect_html.py (Chromium-only)

    from seleniumbase import BaseCase\nBaseCase.main(__name__, __file__)\n\nclass HtmlInspectorTests(BaseCase):\n    def test_html_inspector(self):\n        self.open(\"https://xkcd.com/1144/\")\n        self.inspect_html()\n
    pytest test_inspect_html.py\n============== test session starts ==============\n\n* HTML Inspection Results: https://xkcd.com/1144/\n\u26a0\ufe0f  'property' is not a valid attribute of the <meta> element.\n\u26a0\ufe0f  Do not use <div> or <span> elements without any attributes.\n\u26a0\ufe0f  'srcset' is not a valid attribute of the <img> element.\n\u26a0\ufe0f  The 'border' attribute is no longer valid on the <img> element.\n\u26a0\ufe0f  The <center> element is obsolete.\n\u26a0\ufe0f  The id 'comicLinks' appears more than once in the document.\n* (See the Console output for details!)\n
    "}, {"location": "help_docs/install/", "title": "\ud83c\udfc4 Install SeleniumBase", "text": ""}, {"location": "help_docs/install/#seleniumbase-installation", "title": "SeleniumBase Installation", "text": "If installing seleniumbase directly from PyPI, (the Python Package Index), use:
    pip install seleniumbase\n
    To upgrade an existing seleniumbase install from PyPI:
    pip install -U seleniumbase\n
    If installing seleniumbase from a Git clone, use:
    git clone https://github.com/seleniumbase/SeleniumBase.git\ncd SeleniumBase/\npip install .\n
    For a development mode install in editable mode, use:
    git clone https://github.com/seleniumbase/SeleniumBase.git\ncd SeleniumBase/\npip install -e .\n
    To upgrade an existing seleniumbase install from GitHub:
    git pull  # To pull the latest version\npip install -e .  # Or \"pip install .\"\n
    If installing seleniumbase from a GitHub branch, use:
    pip install git+https://github.com/seleniumbase/SeleniumBase.git@master#egg=seleniumbase\n
    pip install can be customized:

    (If you're not using a virtual environment, you may need to add --user to your pip command if you're seeing errors during installation.)

    "}, {"location": "help_docs/install_python_pip_git/", "title": "\ud83d\udc09 Get Python, pip, & git", "text": ""}, {"location": "help_docs/install_python_pip_git/#installation-instructions-for-git-python-and-pip", "title": "Installation instructions for Git, Python, and pip", "text": ""}, {"location": "help_docs/install_python_pip_git/#git", "title": "Git", "text": "

    You can download Git from here.

    (A Git GUI tool like SourceTree or GitHub Desktop can help you with Git commands.)

    (You can also download SeleniumBase from GitHub without using git-related commands.)

    "}, {"location": "help_docs/install_python_pip_git/#python", "title": "Python", "text": "

    You can download Python from https://www.python.org/downloads/ if it's not already preinstalled on your machine.

    "}, {"location": "help_docs/install_python_pip_git/#pip", "title": "pip", "text": "

    pip already comes with Python! (It lets you install packages, such as seleniumbase.)

    \u26a0\ufe0f If something went wrong with your pip installation, try this:

    python -m ensurepip --default-pip\n

    If your existing version of pip is old, upgrade to the latest version:

    python -m pip install --upgrade pip setuptools\n

    On CentOS 7 and some versions of Linux, you may need to install pip with yum:

    yum -y update\nyum -y install python-pip\n

    If you're having any trouble getting pip, you can GET PIP HERE.

    When done, make sure the location of pip is on your path, which is $PATH for macOS/Linux. (On Windows, it's the System Variables Path within System Environment Variables.)

    You can also get pip (or fix pip) by using:

    curl https://bootstrap.pypa.io/get-pip.py | python\n

    Keep Pip and Setuptools up-to-date:

    python -m pip install -U pip setuptools\n
    "}, {"location": "help_docs/js_package_manager/", "title": "\ud83d\udd79\ufe0f Package Manager", "text": ""}, {"location": "help_docs/js_package_manager/#js-package-manager-and-code-generators", "title": "JS Package Manager and Code Generators", "text": "\ud83d\udd79\ufe0f SeleniumBase lets you load JavaScript packages from any CDN link into any website via Python.

    \ud83c\udfa8 The following SeleniumBase solutions utilize this feature:

    \ud83c\udfa6 (Demo Mode)

    \ud83d\ude8e (Website Tours)

    \ud83c\udf9e\ufe0f (Presentation Maker)

    \ud83d\udcca (Chart Maker / Dashboard)

    \ud83d\udec2 (Dialog Boxes / MasterQA)

    \ud83d\uddfa\ufe0f Here's an example of loading a website-tour library into the browser for a Google Maps tour:

    \ud83d\uddfa\ufe0f This example is from maps_introjs_tour.py. (The --interval=1 makes the tour go automatically to the next step after 1 second.)

    cd examples/tour_examples\npytest maps_introjs_tour.py --interval=1\n

    \ud83d\udd79\ufe0f SeleniumBase includes powerful JS code generators for converting Python into JavaScript for using the supported JS packages. A few lines of Python in your tests might generate hundreds of lines of JavaScript.

    \ud83d\uddfa\ufe0f Here is some tour code in Python from maps_introjs_tour.py that expands into a lot of JavaScript.

    self.open(\"https://www.google.com/maps/@42.3591234,-71.0915634,15z\")\nself.create_tour(theme=\"introjs\")\nself.add_tour_step(\"Welcome to Google Maps!\", title=\"SeleniumBase Tours\")\nself.add_tour_step(\"Enter Location\", \"#searchboxinput\", title=\"Search Box\")\nself.add_tour_step(\"See it\", \"#searchbox-searchbutton\", alignment=\"bottom\")\nself.add_tour_step(\"Thanks for using Tours!\", title=\"End of Guided Tour\")\nself.export_tour(filename=\"maps_introjs_tour.js\")\nself.play_tour()\n

    \ud83d\udd79\ufe0f For existing features, SeleniumBase already takes care of loading all the necessary JS and CSS files into the web browser. To load other packages, here are a few useful methods that you should know about:

    self.add_js_link(js_link)\n

    \ud83d\udd79\ufe0f This example loads the IntroJS JavaScript library:

    self.add_js_link(\"https://cdnjs.cloudflare.com/ajax/libs/intro.js/2.9.3/intro.min.js\")\n
    \ud83d\udd79\ufe0f You can load any JS package this way as long as you know the URL.

    \ud83d\udd79\ufe0f If you're wondering how SeleniumBase does this, here's the full Python code from js_utils.py, which uses WebDriver's execute_script() method for making JS calls after escaping quotes with backslashes as needed:

    def add_js_link(driver, js_link):\n    script_to_add_js = (\n\"\"\"function injectJS(link) {\n              var body = document.getElementsByTagName(\"body\")[0];\n              var script = document.createElement(\"script\");\n              script.src = link;\n              script.defer;\n              script.type=\"text/javascript\";\n              script.crossorigin = \"anonymous\";\n              script.onload = function() { null };\n              body.appendChild(script);\n           }\n           injectJS(\"%s\");\"\"\")\n    js_link = escape_quotes_if_needed(js_link)\n    driver.execute_script(script_to_add_js % js_link)\n

    \ud83d\udd79\ufe0f Now that you've loaded JavaScript into the browser, you may also want to load some CSS to go along with it:

    self.add_css_link(css_link)\n

    \ud83d\udd79\ufe0f Here's code that loads the IntroJS CSS:

    self.add_css_link(\"https://cdnjs.cloudflare.com/ajax/libs/intro.js/2.9.3/introjs.css\")\n

    \ud83d\udd79\ufe0f And here's the Python WebDriver code that makes this possible:

    def add_css_link(driver, css_link):\n    script_to_add_css = (\n\"\"\"function injectCSS(css) {\n              var head = document.getElementsByTagName(\"head\")[0];\n              var link = document.createElement(\"link\");\n              link.rel = \"stylesheet\";\n              link.type = \"text/css\";\n              link.href = css;\n              link.crossorigin = \"anonymous\";\n              head.appendChild(link);\n           }\n           injectCSS(\"%s\");\"\"\")\n    css_link = escape_quotes_if_needed(css_link)\n    driver.execute_script(script_to_add_css % css_link)\n
    \ud83d\udd79\ufe0f Website tours are just one of the many uses of the JS Package Manager.

    \ud83d\udec2 The following example shows the JqueryConfirm package loaded into a website for creating fancy dialog boxes:

    \u2195\ufe0f (Example: dialog_box_tour.py) \u2195\ufe0f

    Here's how to run that example:
    cd examples/dialog_boxes\npytest test_dialog_boxes.py\n

    (Example from the Dialog Boxes ReadMe)

    \ud83d\udd79\ufe0f Since packages are loaded directly from a CDN link, you won't need other package managers like NPM, Bower, or Yarn to get the packages that you need into the websites that you want.

    To learn more about SeleniumBase, check out the Docs Site:

    All the code is on GitHub:

    "}, {"location": "help_docs/locale_codes/", "title": "\ud83d\uddfe Locale Codes", "text": ""}, {"location": "help_docs/locale_codes/#language-locale-codes", "title": "Language Locale Codes", "text": "

    You can specify a Language Locale Code to customize web pages on supported websites. With SeleniumBase, you can change the web browser's Locale on the command line by doing this:

    pytest --locale=CODE  # Example: --locale=ru\n
    List of Language Locale Codes: LanguageCode Afrikaansaf Amharicam Arabicar Arabic (Egypt)ar_eg Arabic (Saudi Arabia)ar_sa Basqueeu Belarusianbe Bengalibn Bulgarianbg Catalanca Chinesezh Chinese (China Mainland)zh_cn Chinese (Hong Kong)zh_hk Chinese (Taiwan)zh_tw Croatianhr Czechcs Danishda Dutchnl Englishen English (United States)en_us English (Australia)en_au English (Canada)en_ca English (United Kingdom)en_gb English (Ireland)en_ie English (India)en_in English (Singapore)en_sg English (South Africa)en_za Estonianet Farsifa Filipinofil Finnishfi Frenchfr French (Canada)fr_ca French (Switzerland)fr_ch Galiciangl Germande German (Austria)de_at Greekel Gujaratigu Hebrewhe Hindihi Hungarianhu Icelandicis Indonesianid Italianit Japaneseja Kannadakn Koreanko Laolo Latvianlv Lingalaln Lithuanianlt Malayms Malayalamml Marathimr Norwegianno Polishpl Portuguesept Portuguese (Brazil)pt_br Portuguese (Portugal)pt_pt Romanianro Russianru Serbiansr Slovaksk Sloveniansl Spanishes Spanish (Latin America)es_419 Spanish (Argentina)es_ar Spanish (Chile)es_cl Spanish (Colombia)es_co Spanish (Costa Rica)es_cr Spanish (Dominican Rep.)es_do Spanish (Ecuador)es_ec Spanish (El Salvador)es_sv Spanish (Guatemala)es_gt Spanish (Honduras)es_hn Spanish (Mexico)es_mx Spanish (Nicaragua)es_ni Spanish (Panama)es_pa Spanish (Peru)es_pe Spanish (Puerto Rico)es_pr Spanish (Paraguay)es_py Spanish (United States)es_us Spanish (Uruguay)es_uy Spanish (Venezuela)es_ve Swahilisw Swedishsv Swiss Germangsw Tagalogtl Tamilta Telugute Thaith Turkishtr Ukrainianuk Urduur Vietnamesevi Zuluzu"}, {"location": "help_docs/method_summary/", "title": "\ud83d\udcd8 API Reference", "text": ""}, {"location": "help_docs/method_summary/#seleniumbase-methods-api-reference", "title": "SeleniumBase Methods (API Reference)\ud83d\udd35 Examples", "text": "

    Here's a list of SeleniumBase method definitions, which are defined in base_case.py

    For backwards compatibility, older versions of method names have remained to keep older scripts working. (E.g: wait_for_element_visible was shortened to wait_for_element and then to find_element.)

    self.open(url)\n# Duplicates: self.open_url(url), self.visit(url), visit_url(url),\n#             self.goto(url), self.go_to(url)\n\nself.get(url)\n# If the url parameter is a URL: Perform self.open(url)\n# Otherwise: return self.get_element(URL_AS_A_SELECTOR)\n\nself.click(selector, by=\"css selector\", timeout=None, delay=0, scroll=True)\n\nself.slow_click(selector, by=\"css selector\", timeout=None)\n\nself.double_click(selector, by=\"css selector\", timeout=None)\n\nself.context_click(selector, by=\"css selector\", timeout=None)\n# Duplicates\n# self.right_click(selector, by=\"css selector\", timeout=None)\n\nself.click_chain(selectors_list, by=\"css selector\", timeout=None, spacing=0)\n\nself.type(selector, text, by=\"css selector\", timeout=None)\n# Duplicates\n# self.update_text(selector, text, by=\"css selector\", timeout=None)\n# self.input(selector, text, by=\"css selector\", timeout=None)\n# self.fill(selector, text, by=\"css selector\", timeout=None)\n# self.write(selector, text, by=\"css selector\", timeout=None)\n\nself.send_keys(selector, text, by=\"css selector\", timeout=None)\n# Duplicates\n# self.add_text(selector, text, by=\"css selector\", timeout=None)\n\nself.submit(selector, by=\"css selector\")\n\nself.clear(selector, by=\"css selector\", timeout=None)\n\nself.focus(selector, by=\"css selector\", timeout=None)\n\nself.refresh()\n# Duplicates: self.refresh_page(), self.reload_page(), self.reload()\n\nself.get_current_url()\n\nself.get_origin()\n\nself.get_page_source()\n\nself.get_title()\n# Duplicates: self.get_page_title()\n\nself.get_user_agent()\n\nself.get_locale_code()\n\nself.go_back()\n\nself.go_forward()\n\nself.open_start_page()\n\nself.open_if_not_url(url)\n\nself.is_element_present(selector, by=\"css selector\")\n\nself.is_element_visible(selector, by=\"css selector\")\n\nself.is_element_clickable(selector, by=\"css selector\")\n\nself.is_element_enabled(selector, by=\"css selector\")\n\nself.is_text_visible(text, selector=\"html\", by=\"css selector\")\n\nself.is_exact_text_visible(text, selector=\"html\", by=\"css selector\")\n\nself.is_non_empty_text_visible(selector=\"html\", by=\"css selector\")\n\nself.is_attribute_present(selector, attribute, value=None, by=\"css selector\")\n\nself.is_link_text_visible(link_text)\n\nself.is_partial_link_text_visible(partial_link_text)\n\nself.is_link_text_present(link_text)\n\nself.is_partial_link_text_present(link_text)\n\nself.get_link_attribute(link_text, attribute, hard_fail=True)\n# Duplicates\n# self.get_link_text_attribute(link_text, attribute, hard_fail=True)\n\nself.get_partial_link_text_attribute(link_text, attribute, hard_fail=True)\n\nself.click_link(link_text, timeout=None)\n# Duplicates\n# self.click_link_text(link_text, timeout=None)\n\nself.click_partial_link(partial_link_text, timeout=None)\n# Duplicates\n# self.click_partial_link_text(partial_link_text, timeout=None)\n\nself.get_text(selector, by=\"css selector\", timeout=None)\n\nself.get_attribute(selector, attribute, by=\"css selector\", timeout=None, hard_fail=True)\n\nself.set_attribute(selector, attribute, value, by=\"css selector\", timeout=None, scroll=False)\n\nself.set_attributes(selector, attribute, value, by=\"css selector\")\n# Duplicates\n# self.set_attribute_all(selector, attribute, value, by=\"css selector\")\n\nself.remove_attribute(selector, attribute, by=\"css selector\", timeout=None)\n\nself.remove_attributes(selector, attribute, by=\"css selector\")\n\nself.get_property(selector, property, by=\"css selector\", timeout=None)\n\nself.get_text_content(selector, by=\"css selector\", timeout=None)\n\nself.get_property_value(selector, property, by=\"css selector\", timeout=None)\n\nself.get_image_url(selector, by=\"css selector\", timeout=None)\n\nself.find_elements(selector, by=\"css selector\", limit=0)\n\nself.find_visible_elements(selector, by=\"css selector\", limit=0)\n\nself.click_visible_elements(selector, by=\"css selector\", limit=0, timeout=None)\n\nself.click_nth_visible_element(selector, number, by=\"css selector\", timeout=None)\n\nself.click_if_visible(selector, by=\"css selector\", timeout=0)\n\nself.click_active_element()\n\nself.click_with_offset(\n    selector, x, y, by=\"css selector\", mark=None, timeout=None, center=None)\n\nself.double_click_with_offset(\n    selector, x, y, by=\"css selector\", mark=None, timeout=None, center=None)\n\nself.is_checked(selector, by=\"css selector\", timeout=None)\n# Duplicates\n# self.is_selected(selector, by=\"css selector\", timeout=None)\n\nself.check_if_unchecked(selector, by=\"css selector\")\n# Duplicates\n# self.select_if_unselected(selector, by=\"css selector\")\n\nself.uncheck_if_checked(selector, by=\"css selector\")\n# Duplicates\n# self.unselect_if_selected(selector, by=\"css selector\")\n\nself.is_element_in_an_iframe(selector, by=\"css selector\")\n\nself.switch_to_frame_of_element(selector, by=\"css selector\")\n\nself.hover(selector, by=\"css selector\", timeout=None)\n# Duplicates\n# self.hover_on_element(selector, by=\"css selector\", timeout=None)\n# self.hover_over_element(selector, by=\"css selector\", timeout=None)\n\nself.hover_and_click(\n    hover_selector, click_selector,\n    hover_by=\"css selector\", click_by=\"css selector\",\n    timeout=None)\n\nself.hover_and_double_click(\n    hover_selector, click_selector,\n    hover_by=\"css selector\", click_by=\"css selector\",\n    timeout=None)\n\nself.drag_and_drop(\n    drag_selector, drop_selector,\n    drag_by=\"css selector\", drop_by=\"css selector\",\n    timeout=None, jquery=False)\n\nself.drag_and_drop_with_offset(\n    selector, x, y, by=\"css selector\", timeout=None)\n\nself.select_option_by_text(\n    dropdown_selector, option, dropdown_by=\"css selector\", timeout=None)\n\nself.select_option_by_index(\n    dropdown_selector, option, dropdown_by=\"css selector\", timeout=None)\n\nself.select_option_by_value(\n    dropdown_selector, option, dropdown_by=\"css selector\", timeout=None)\n\nself.get_select_options(\n    dropdown_selector, attribute=\"text\", by=\"css selector\", timeout=None)\n\nself.load_html_string(html_string, new_page=True)\n\nself.set_content(html_string, new_page=False)\n\nself.load_html_file(html_file, new_page=True)\n\nself.open_html_file(html_file)\n\nself.execute_script(script, *args, **kwargs)\n\nself.execute_cdp_cmd(script, *args, **kwargs)\n\nself.execute_async_script(script, timeout=None)\n\nself.safe_execute_script(script, *args, **kwargs)\n\nself.set_window_rect(x, y, width, height)\n\nself.set_window_size(width, height)\n\nself.maximize_window()\n\nself.switch_to_frame(frame, timeout=None)\n\nself.switch_to_default_content()\n\nself.switch_to_parent_frame()\n\nwith self.frame_switch(frame, timeout=None):\n    # Indented Code Block for Context Manager (Must use \"with\")\n\nself.set_content_to_frame(frame, timeout=None)\n\nself.set_content_to_default(nested=False)\n# Duplicates: self.set_content_to_default_content(nested=False)\n\nself.set_content_to_parent()\n# Duplicates: self.set_content_to_parent_frame()\n\nself.open_new_window(switch_to=True)\n# Duplicates: self.open_new_tab(switch_to=True)\n\nself.switch_to_window(window, timeout=None)\n# Duplicates: self.switch_to_tab(tab, timeout=None)\n\nself.switch_to_default_window()\n# Duplicates: self.switch_to_default_tab()\n\nself.switch_to_newest_window()\n# Duplicates: self.switch_to_newest_tab()\n\nself.get_new_driver(\n    browser=None,\n    headless=None,\n    locale_code=None,\n    protocol=None,\n    servername=None,\n    port=None,\n    proxy=None,\n    proxy_bypass_list=None,\n    proxy_pac_url=None,\n    multi_proxy=None,\n    agent=None,\n    switch_to=True,\n    cap_file=None,\n    cap_string=None,\n    recorder_ext=None,\n    disable_js=None,\n    disable_csp=None,\n    enable_ws=None,\n    enable_sync=None,\n    use_auto_ext=None,\n    undetectable=None,\n    uc_cdp_events=None,\n    uc_subprocess=None,\n    no_sandbox=None,\n    disable_gpu=None,\n    headless2=None,\n    incognito=None,\n    guest_mode=None,\n    devtools=None,\n    remote_debug=None,\n    enable_3d_apis=None,\n    swiftshader=None,\n    ad_block_on=None,\n    block_images=None,\n    do_not_track=None,\n    chromium_arg=None,\n    firefox_arg=None,\n    firefox_pref=None,\n    user_data_dir=None,\n    extension_zip=None,\n    extension_dir=None,\n    binary_location=None,\n    page_load_strategy=None,\n    use_wire=None,\n    external_pdf=None,\n    is_mobile=None,\n    d_width=None,\n    d_height=None,\n    d_p_r=None,\n)\n\nself.switch_to_driver(driver)\n\nself.switch_to_default_driver()\n\nself.save_screenshot(name, folder=None, selector=None, by=\"css selector\")\n\nself.save_screenshot_to_logs(name=None, selector=None, by=\"css selector\")\n\nself.save_data_to_logs(data, file_name=None)\n\nself.append_data_to_logs(data, file_name=None)\n\nself.save_page_source(name, folder=None)\n\nself.save_cookies(name=\"cookies.txt\")\n\nself.load_cookies(name=\"cookies.txt\")\n\nself.delete_all_cookies()\n# Duplicates: self.clear_all_cookies()\n\nself.delete_saved_cookies(name=\"cookies.txt\")\n\nself.wait_for_ready_state_complete(timeout=None)\n\nself.wait_for_angularjs(timeout=None)\n\nself.sleep(seconds)\n# Duplicates: self.wait(seconds)\n\nself.install_addon(xpi_file)\n\nself.activate_jquery()\n\nself.activate_demo_mode()\n\nself.deactivate_demo_mode()\n\nself.activate_design_mode()\n\nself.deactivate_design_mode()\n\nself.activate_recorder()\n\nself.save_recorded_actions()\n\nself.bring_active_window_to_front()\n\nself.bring_to_front(selector, by=\"css selector\")\n\nself.highlight_click(selector, by=\"css selector\", loops=3, scroll=True)\n\nself.highlight_type(selector, text, by=\"css selector\", loops=3, scroll=True)\n# Duplicates\n# self.highlight_update_text(selector, text, by=\"css selector\", loops=3, scroll=True)\n\nself.highlight(selector, by=\"css selector\", loops=4, scroll=True)\n\nself.press_up_arrow(selector=\"html\", times=1, by=\"css selector\")\n\nself.press_down_arrow(selector=\"html\", times=1, by=\"css selector\")\n\nself.press_left_arrow(selector=\"html\", times=1, by=\"css selector\")\n\nself.press_right_arrow(selector=\"html\", times=1, by=\"css selector\")\n\nself.scroll_to(selector, by=\"css selector\", timeout=None)\n# Duplicates: self.scroll_to_element(selector, by=\"css selector\")\n\nself.slow_scroll_to(selector, by=\"css selector\", timeout=None)\n# Duplicates: self.slow_scroll_to_element(selector, by=\"css selector\")\n\nself.scroll_into_view(selector, by=\"css selector\", timeout=None)\n\nself.scroll_to_top()\n\nself.scroll_to_bottom()\n\nself.click_xpath(xpath)\n\nself.js_click(selector, by=\"css selector\", all_matches=False, scroll=True)\n\nself.js_click_if_present(selector, by=\"css selector\", timeout=0)\n\nself.js_click_if_visible(selector, by=\"css selector\", timeout=0)\n\nself.js_click_all(selector, by=\"css selector\")\n\nself.jquery_click(selector, by=\"css selector\")\n\nself.jquery_click_all(selector, by=\"css selector\")\n\nself.hide_element(selector, by=\"css selector\")\n\nself.hide_elements(selector, by=\"css selector\")\n\nself.show_element(selector, by=\"css selector\")\n\nself.show_elements(selector, by=\"css selector\")\n\nself.remove_element(selector, by=\"css selector\")\n\nself.remove_elements(selector, by=\"css selector\")\n\nself.ad_block()\n# Duplicates: self.block_ads()\n\nself.show_file_choosers()\n\nself.disable_beforeunload()\n\nself.get_domain_url(url)\n\nself.get_beautiful_soup(source=None)\n\nself.get_unique_links()\n\nself.get_link_status_code(link, allow_redirects=False, timeout=5, verify=False)\n\nself.assert_link_status_code_is_not_404(link)\n\nself.assert_no_404_errors(multithreaded=True, timeout=None)\n# Duplicates\n# self.assert_no_broken_links(multithreaded=True, timeout=None)\n\nself.print_unique_links_with_status_codes()\n\nself.get_pdf_text(\n    pdf, page=None, maxpages=None, password=None,\n    codec='utf-8', wrap=False, nav=False, override=False, caching=True)\n\nself.assert_pdf_text(\n    pdf, text, page=None, maxpages=None, password=None,\n    codec='utf-8', wrap=True, nav=False, override=False, caching=True)\n\nself.create_folder(folder)\n\nself.choose_file(selector, file_path, by=\"css selector\", timeout=None)\n\nself.save_element_as_image_file(selector, file_name, folder=None, overlay_text=\"\")\n\nself.download_file(file_url, destination_folder=None)\n\nself.save_file_as(file_url, new_file_name, destination_folder=None)\n\nself.save_data_as(data, file_name, destination_folder=None)\n\nself.append_data_to_file(data, file_name, destination_folder=None)\n\nself.get_file_data(file_name, folder=None)\n\nself.get_downloads_folder()\n\nself.get_browser_downloads_folder()\n\nself.get_path_of_downloaded_file(file, browser=False)\n\nself.is_downloaded_file_present(file, browser=False)\n\nself.delete_downloaded_file_if_present(file, browser=False)\n# Duplicates: self.delete_downloaded_file(file, browser=False)\n\nself.assert_downloaded_file(file, timeout=None, browser=False)\n\nself.assert_true(expr, msg=None)\n\nself.assert_false(expr, msg=None)\n\nself.assert_equal(first, second, msg=None)\n\nself.assert_not_equal(first, second, msg=None)\n\nself.assert_in(first, second, msg=None)\n\nself.assert_not_in(first, second, msg=None)\n\nself.assert_raises(*args, **kwargs)\n\nself.wait_for_attribute(selector, attribute, value=None, by=\"css selector\", timeout=None)\n\nself.assert_attribute(selector, attribute, value=None, by=\"css selector\", timeout=None)\n\nself.assert_title(title)\n\nself.assert_title_contains(substring)\n\nself.assert_url(url)\n\nself.assert_url_contains(substring)\n\nself.assert_no_js_errors(exclude=[])\n\nself.inspect_html()\n\nself.is_valid_url(url)\n\nself.is_online()\n\nself.is_chromium()\n\nself.get_chrome_version()\n\nself.get_chromium_version()\n\nself.get_chromedriver_version()\n\nself.get_chromium_driver_version()\n\nself.get_mfa_code(totp_key=None)\n# Duplicates\n# self.get_totp_code(totp_key=None)\n# self.get_google_auth_password(totp_key=None)\n# self.get_google_auth_code(totp_key=None)\n\nself.enter_mfa_code(selector, totp_key=None, by=\"css selector\", timeout=None)\n# Duplicates\n# self.enter_totp_code(selector, totp_key=None, by=\"css selector\", timeout=None)\n\nself.convert_css_to_xpath(css)\n\nself.convert_xpath_to_css(xpath)\n\nself.convert_to_css_selector(selector, by)\n\nself.set_value(selector, text, by=\"css selector\", timeout=None, scroll=True)\n\nself.js_update_text(selector, text, by=\"css selector\", timeout=None)\n# Duplicates\n# self.js_type(selector, text, by=\"css selector\", timeout=None)\n# self.set_text(selector, text, by=\"css selector\", timeout=None)\n\nself.set_text_content(selector, text, by=\"css selector\", timeout=None, scroll=False)\n\nself.jquery_update_text(selector, text, by=\"css selector\", timeout=None)\n# Duplicates\n# self.jquery_type(selector, text, by=\"css selector\", timeout=None)\n\nself.get_value(selector, by=\"css selector\", timeout=None)\n\nself.set_time_limit(time_limit)\n\nself.set_default_timeout(timeout)\n\nself.reset_default_timeout()\n\nself.fail(msg=None)\n\nself.skip(reason=\"\")\n\n############\n\nself.start_recording_console_logs()\n\nself.console_log_string(string)\n\nself.console_log_script(script)\n\nself.get_recorded_console_logs()\n\n############\n\nself.set_local_storage_item(key, value)\n\nself.get_local_storage_item(key)\n\nself.remove_local_storage_item(key)\n\nself.clear_local_storage()\n\nself.get_local_storage_keys()\n\nself.get_local_storage_items()\n\nself.set_session_storage_item(key, value)\n\nself.get_session_storage_item(key)\n\nself.remove_session_storage_item(key)\n\nself.clear_session_storage()\n\nself.get_session_storage_keys()\n\nself.get_session_storage_items()\n\n############\n\nself.set_wire_proxy(string)  # Requires \"--wire\"!\n\n############\n\nself.add_css_link(css_link)\n\nself.add_js_link(js_link)\n\nself.add_css_style(css_style)\n\nself.add_js_code_from_link(js_link)\n\nself.add_js_code(js_code)\n\nself.add_meta_tag(http_equiv=None, content=None)\n\n############\n\nself.create_presentation(name=None, theme=\"default\", transition=\"default\")\n\nself.add_slide(\n    content=None, image=None, code=None, iframe=None,\n    content2=None, notes=None, transition=None, name=None)\n\nself.save_presentation(\n    name=None, filename=None, show_notes=False, interval=0)\n\nself.begin_presentation(\n    name=None, filename=None, show_notes=False, interval=0)\n\n############\n\nself.create_pie_chart(\n    chart_name=None, title=None, subtitle=None,\n    data_name=None, unit=None, libs=True,\n    labels=True, legend=True)\n\nself.create_bar_chart(\n    chart_name=None, title=None, subtitle=None,\n    data_name=None, unit=None, libs=True,\n    labels=True, legend=True)\n\nself.create_column_chart(\n    chart_name=None, title=None, subtitle=None,\n    data_name=None, unit=None, libs=True,\n    labels=True, legend=True)\n\nself.create_line_chart(\n    chart_name=None, title=None, subtitle=None,\n    data_name=None, unit=None, zero=False, libs=True,\n    labels=True, legend=True)\n\nself.create_area_chart(\n    chart_name=None, title=None, subtitle=None,\n    data_name=None, unit=None, zero=False, libs=True,\n    labels=True, legend=True)\n\nself.add_series_to_chart(data_name=None, chart_name=None)\n\nself.add_data_point(label, value, color=None, chart_name=None)\n\nself.save_chart(chart_name=None, filename=None, folder=None)\n\nself.display_chart(chart_name=None, filename=None, interval=0)\n\nself.extract_chart(chart_name=None)\n\n############\n\nself.create_tour(name=None, theme=None)\n\nself.create_shepherd_tour(name=None, theme=None)\n\nself.create_bootstrap_tour(name=None)\n\nself.create_hopscotch_tour(name=None)\n\nself.create_introjs_tour(name=None)\n\nself.set_introjs_colors(theme_color=None, hover_color=None)\n\nself.add_tour_step(\n    message, selector=None, name=None, title=None, theme=None, alignment=None)\n\nself.play_tour(name=None, interval=0)\n# Duplicates\n# self.start_tour(name=None, interval=0):\n\nself.export_tour(name=None, filename=\"my_tour.js\", url=None)\n\n############\n\nself.activate_jquery_confirm()\n\nself.set_jqc_theme(theme, color=None, width=None)\n\nself.reset_jqc_theme()\n\nself.get_jqc_button_input(message, buttons, options=None)\n\nself.get_jqc_text_input(message, button=None, options=None)\n\nself.get_jqc_form_inputs(message, buttons, options=None)\n\n############\n\nself.activate_messenger()\n\nself.post_message(message, duration=None, pause=True, style=\"info\")\n\nself.post_message_and_highlight(message, selector, by=\"css selector\")\n\nself.post_success_message(message, duration=None, pause=True)\n\nself.post_error_message(message, duration=None, pause=True)\n\nself.set_messenger_theme(\n    theme=\"default\", location=\"default\", max_messages=\"default\")\n\n############\n\nself.generate_referral(start_page, destination_page, selector=None)\n\nself.generate_traffic(start_page, destination_page, loops=1, selector=None)\n\nself.generate_referral_chain(pages)\n\nself.generate_traffic_chain(pages, loops=1)\n\n############\n\nself.get_element(selector, by=\"css selector\", timeout=None)\n# Duplicates\n# self.wait_for_element_present(selector, by=\"css selector\", timeout=None)\n\nself.wait_for_query_selector(selector, by=\"css selector\", timeout=None)\n\nself.assert_element_present(selector, by=\"css selector\", timeout=None)\n\nself.assert_elements_present(*args, **kwargs)\n\n############\n\nself.find_element(selector, by=\"css selector\", timeout=None)\n# Duplicates\n# self.wait_for_element(selector, by=\"css selector\", timeout=None)\n# self.wait_for_element_visible(selector, by=\"css selector\", timeout=None)\n\nself.assert_element(selector, by=\"css selector\", timeout=None)\n# Duplicates\n# self.assert_element_visible(selector, by=\"css selector\", timeout=None)\n\nself.assert_elements(*args, **kwargs)\n# Duplicates\n# self.assert_elements_visible(*args, **kwargs)\n\n############\n\nself.find_text(text, selector=\"html\", by=\"css selector\", timeout=None)\n# Duplicates\n# self.wait_for_text(text, selector=\"html\", by=\"css selector\", timeout=None)\n# self.wait_for_text_visible(text, selector=\"html\", by=\"css selector\", timeout=None)\n\nself.find_exact_text(text, selector=\"html\", by=\"css selector\", timeout=None)\n# Duplicates\n# self.wait_for_exact_text(text, selector=\"html\", by=\"css selector\", timeout=None)\n# self.wait_for_exact_text_visible(text, selector=\"html\", by=\"css selector\", timeout=None)\n\nself.find_non_empty_text(selector=\"html\", by=\"css selector\", timeout=None)\n# Duplicates\n# self.wait_for_non_empty_text(selector=\"html\", by=\"css selector\", timeout=None)\n# self.wait_for_non_empty_text_visible(selector=\"html\", by=\"css selector\", timeout=None)\n\nself.assert_text(text, selector=\"html\", by=\"css selector\", timeout=None)\n# Duplicates\n# self.assert_text_visible(text, selector=\"html\", by=\"css selector\", timeout=None)\n\nself.assert_exact_text(text, selector=\"html\", by=\"css selector\", timeout=None)\n\n############\n\nself.wait_for_link_text_present(link_text, timeout=None)\n\nself.wait_for_partial_link_text_present(link_text, timeout=None)\n\nself.find_link_text(link_text, timeout=None)\n# Duplicates\n# self.wait_for_link_text(link_text, timeout=None)\n# self.wait_for_link_text_visible(link_text, timeout=None)\n\nself.assert_link_text(link_text, timeout=None)\n# Duplicates\n# self.assert_link(link_text, timeout=None)\n\n############\n\nself.find_partial_link_text(partial_link_text, timeout=None)\n# Duplicates\n# self.wait_for_partial_link_text(partial_link_text, timeout=None)\n\nself.assert_partial_link_text(partial_link_text, timeout=None)\n\n############\n\nself.wait_for_element_absent(selector, by=\"css selector\", timeout=None)\n# Duplicates\n# self.wait_for_element_not_present(selector, by=\"css selector\", timeout=None)\n\nself.assert_element_absent(selector, by=\"css selector\", timeout=None)\n# Duplicates\n# self.assert_element_not_present(selector, by=\"css selector\", timeout=None)\n\n############\n\nself.wait_for_element_clickable(selector, by=\"css selector\", timeout=None)\n\n############\n\nself.wait_for_element_not_visible(selector, by=\"css selector\", timeout=None)\n\nself.assert_element_not_visible(selector, by=\"css selector\", timeout=None)\n\n############\n\nself.wait_for_text_not_visible(text, selector=\"html\", by=\"css selector\", timeout=None)\n\nself.wait_for_exact_text_not_visible(text, selector=\"html\", by=\"css selector\", timeout=None)\n\nself.assert_text_not_visible(text, selector=\"html\", by=\"css selector\", timeout=None)\n\nself.assert_exact_text_not_visible(text, selector=\"html\", by=\"css selector\", timeout=None)\n\nself.assert_non_empty_text(selector=\"html\", by=\"css selector\", timeout=None)\n\n############\n\nself.wait_for_attribute_not_present(\n    selector, attribute, value=None, by=\"css selector\", timeout=None)\n\nself.assert_attribute_not_present(\n    selector, attribute, value=None, by=\"css selector\", timeout=None)\n\n############\n\nself.accept_alert(timeout=None)\n# Duplicates\n# self.wait_for_and_accept_alert(timeout=None)\n\nself.dismiss_alert(timeout=None)\n# Duplicates\n# self.wait_for_and_dismiss_alert(timeout=None)\n\nself.switch_to_alert(timeout=None)\n# Duplicates\n# self.wait_for_and_switch_to_alert(timeout=None)\n\n############\n\nself.quit_extra_driver(driver=None)\n\n############\n\nself.check_window(\n    name=\"default\", level=0, baseline=False, check_domain=True, full_diff=False)\n\n############\n\nself.deferred_assert_element(\n    selector, by=\"css selector\", timeout=None, fs=False)\n# Duplicates\n# self.delayed_assert_element(\n#     selector, by=\"css selector\", timeout=None, fs=False)\n\nself.deferred_assert_element_present(\n    selector, by=\"css selector\", timeout=None, fs=False)\n# Duplicates\n# self.delayed_assert_element_present(\n#     selector, by=\"css selector\", timeout=None, fs=False)\n\nself.deferred_assert_text(\n    text, selector=\"html\", by=\"css selector\", timeout=None, fs=False)\n# Duplicates\n# self.delayed_assert_text(\n#     text, selector=\"html\", by=\"css selector\", timeout=None, fs=False)\n\nself.deferred_assert_exact_text(\n    text, selector=\"html\", by=\"css selector\", timeout=None, fs=False)\n# Duplicates\n# self.delayed_assert_exact_text(\n#     text, selector=\"html\", by=\"css selector\", timeout=None, fs=False)\n\nself.deferred_assert_non_empty_text(\n    selector=\"html\", by=\"css selector\", timeout=None, fs=False)\n# Duplicates\n# self.delayed_assert_non_empty_text(\n#     selector=\"html\", by=\"css selector\", timeout=None, fs=False)\n\nself.deferred_check_window(\n    name=\"default\", level=0, baseline=False, check_domain=True, full_diff=False, fs=False)\n# Duplicates\n# self.delayed_check_window(\n#     name=\"default\", level=0, baseline=False,\n#     check_domain=True, full_diff=False, fs=False)\n\nself.process_deferred_asserts(print_only=False)\n# Duplicates: self.process_delayed_asserts(print_only=False)\n\n############\n\nself.fail(msg=None)  # Inherited from \"unittest\"\n\nself._print(TEXT)  # Calls Python's print() / Allows for translations\n

    \u2705 Test Folder: SeleniumBase/examples

    "}, {"location": "help_docs/mobile_testing/", "title": "\ud83d\udcf1 Mobile Testing", "text": ""}, {"location": "help_docs/mobile_testing/#mobile-testing", "title": "Mobile Testing", "text": "

    Use --mobile to run SeleniumBase tests using Chrome's mobile device emulator with default values for Device Metrics and User-Agent.

    Here's an example mobile test:

    SeleniumBase/examples/test_skype_site.py

    pytest test_skype_site.py --mobile\n

    To configure Device Metrics, use:

    --metrics=\"CSS_Width,CSS_Height,Pixel_Ratio\"\n

    To configure the User-Agent, use:

    --agent=\"USER-AGENT-STRING\"\n

    To find real values for Device Metrics, see:

    To find real User-Agent strings, see:

    Here's another example of a mobile test:

    SeleniumBase/examples/test_swag_labs.py

    pytest test_swag_labs.py --mobile\n

    Here's an example of configuring mobile settings for that test:

    # Run tests using Chrome's mobile device emulator (default settings)\npytest test_swag_labs.py --mobile\n\n# Run mobile tests specifying CSS Width, CSS Height, and Pixel-Ratio\npytest test_swag_labs.py --mobile --metrics=\"360,640,2\"\n\n# Run mobile tests specifying the user agent\npytest test_swag_labs.py --mobile --agent=\"Mozilla/5.0 (Linux; Android 9; Pixel 3 XL)\"\n

    "}, {"location": "help_docs/mysql_installation/", "title": "\ud83d\uddc4\ufe0f MySQL Instructions", "text": ""}, {"location": "help_docs/mysql_installation/#mysql-installation-instructions", "title": "MySQL Installation Instructions", "text": ""}, {"location": "help_docs/mysql_installation/#mysql-optional", "title": "MySQL (OPTIONAL)", "text": "

    (NOTE: If you don't plan on using the SeleniumBase MySQL DB feature, then you can skip this section.)

    "}, {"location": "help_docs/mysql_installation/#github-actions-ubuntu-linux-mysql-setup", "title": "GitHub Actions Ubuntu Linux MySQL Setup", "text": "
    sudo /etc/init.d/mysql start\nmysql -e 'CREATE DATABASE IF NOT EXISTS test_db;' -uroot -proot\nwget https://raw.githubusercontent.com/seleniumbase/SeleniumBase/master/seleniumbase/core/create_db_tables.sql\nsudo mysql -h 127.0.0.1 -uroot -proot test_db < create_db_tables.sql\nsudo mysql -e 'ALTER USER \"root\"@\"localhost\" IDENTIFIED BY \"test\";' -uroot -proot\nsudo service mysql restart\n

    Have SeleniumBase tests write to the MySQL DB:

    pytest --with-db_reporting\n

    Query MySQL DB Results:

    mysql -e 'select test_address,browser,state,start_time,runtime from test_db.test_run_data;' -uroot -ptest\n
    "}, {"location": "help_docs/mysql_installation/#standard-ubuntu-linux-mysql-setup", "title": "Standard Ubuntu Linux MySQL Setup", "text": "
    sudo apt update\nsudo apt install mysql-server\nsudo mysql_secure_installation\nsudo mysql -e 'CREATE DATABASE IF NOT EXISTS test_db;'\nsudo mysql -h 127.0.0.1 -u root test_db < seleniumbase/core/create_db_tables.sql\nsudo service mysql restart\n

    To change the password from root to test:

    mysqladmin -u root -p'root' password 'test'\nsudo service mysql restart\n
    "}, {"location": "help_docs/mysql_installation/#macos-mysql-setup", "title": "MacOS MySQL Setup", "text": "
    brew install mysql\n

    Then start the MySQL service:

    brew services start mysql\n

    (Continue with additional steps below to set up your DB.)

    "}, {"location": "help_docs/mysql_installation/#windows-mysql-setup", "title": "Windows MySQL Setup", "text": "

    Download MySQL here Follow the steps from the MySQL Downloads page.

    (Continue with additional steps below to set up your DB.)

    "}, {"location": "help_docs/mysql_installation/#access-your-mysql-db", "title": "Access your MySQL DB", "text": "

    If you want a visual tool to help make your MySQL life easier, try MySQL Workbench.

    "}, {"location": "help_docs/mysql_installation/#prepare-your-mysql-db", "title": "Prepare your MySQL DB", "text": "

    Use the create_db_tables.sql file to create the necessary tables for storing test data.

    "}, {"location": "help_docs/mysql_installation/#configure-your-mysql-db-for-seleniumbase", "title": "Configure your MySQL DB for SeleniumBase", "text": "

    Update your settings.py file with your MySQL DB credentials so that tests can write to the database when they run.

    "}, {"location": "help_docs/mysql_installation/#have-seleniumbase-tests-write-to-your-mysql-db", "title": "Have SeleniumBase tests write to your MySQL DB", "text": "

    Add the --with-db_reporting argument on the command line when you want tests to write to your MySQL database. Example:

    pytest --with-db_reporting\n
    "}, {"location": "help_docs/recorder_mode/", "title": "\ud83d\udd34 Recorder Mode", "text": ""}, {"location": "help_docs/recorder_mode/#recorder-mode", "title": "Recorder Mode \ud83d\udd34/\u23fa\ufe0f", "text": "

    \ud83d\udd34 SeleniumBase Recorder Mode lets you record & export browser actions into test automation scripts.

    \u23fa\ufe0f To make a new recording with Recorder Mode, use sbase mkrec, sbase codegen, or sbase record):

    sbase mkrec TEST_NAME.py --url=URL\n

    If the file already exists, you'll get an error. If no URL is provided, you'll start on a blank page and will need to navigate somewhere for the Recorder to activate. (The Recorder captures events on URLs that start with https, http, or file.) The command above runs an empty test that stops at a breakpoint so that you can perform manual browser actions for the Recorder. When you have finished recording, type \"c\" on the command-line and press [ENTER] to continue from the breakpoint. The test will complete and a file called TEST_NAME_rec.py will be automatically created in the ./recordings folder. That file will get copied back to the original folder with the name you gave it. (You can run with Edge instead of Chrome by adding --edge to the command above. For headed Linux machines, add --gui to prevent the default headless mode on Linux.)

    Example:

    sbase mkrec new_test.py --url=wikipedia.org\n\n* RECORDING initialized: new_test.py\n\npytest new_test.py --rec -q -s --url=wikipedia.org\n\n>>>>>>>>>>>>>>>>>> PDB set_trace >>>>>>>>>>>>>>>>>\n\n> PATH_TO_YOUR_CURRENT_DIRECTORY/new_test.py(9)\n.\n   5         def test_recording(self):\n   6             if self.recorder_ext:\n   7                 # When done recording actions,\n8                 # type \"c\", and press [Enter].\n9  ->             import pdb; pdb.set_trace()\nreturn None\n(Pdb+) c\n\n>>>>>>>>>>>>>>>>>> PDB continue >>>>>>>>>>>>>>>>>>\n\n>>> RECORDING SAVED as: recordings/new_test_rec.py\n**************************************************\n\n*** RECORDING COPIED to: new_test.py\n

    \ud83d\udd34 You can also activate Recorder Mode from the Desktop App:

    sbase recorder\n* Starting the SeleniumBase Recorder Desktop App...\n

    \u23fa\ufe0f While a recording is in progress, you can press the [ESC] key to pause the Recorder. To resume the recording, you can hit the [~`] key, which is located directly below the [ESC] key on most keyboards.

    \u23fa\ufe0f From within Recorder Mode there are two additional modes: \"Assert Element Mode\" and \"Assert Text Mode\". To switch into \"Assert Element Mode\", press the [^]-key (SHIFT+6): The border will become purple, and you'll be able to click on elements to assert from your test. To switch into \"Assert Text Mode\", press the [&]-key (SHIFT+7): The border will become teal, and you'll be able to click on elements for asserting text from your test.

    While using either of the two special Assertion Modes, certain actions such as clicking on links won't have any effect. This lets you make assertions on elements without navigating away from the page, etc. To add an assertion for buttons without triggering default \"click\" behavior, mouse-down on the button and then mouse-up somewhere else. (This prevents a detected click while still recording the assert.) To return back to the original Recorder Mode, press any key other than [SHIFT] or [BACKSPACE] (Eg: Press [CONTROL], etc.). Press [ESC] once to leave the Assertion Modes, but it'll stop the Recorder if you press it again.

    \u23fa\ufe0f For extra flexibility, the sbase mkrec command can be split into four separate commands:

    sbase mkfile TEST_NAME.py --rec\n\npytest TEST_NAME.py --rec -q -s\n\nsbase print ./recordings/TEST_NAME_rec.py -n\n\ncp ./recordings/TEST_NAME_rec.py ./TEST_NAME.py\n

    The first command creates a boilerplate test with a breakpoint; the second command runs the test with the Recorder activated; the third command prints the completed test to the console; and the fourth command replaces the initial boilerplate with the completed test. If you're just experimenting with the Recorder, you can run the second command as many times as you want, and it'll override previous recordings saved to ./recordings/TEST_NAME_rec.py. (Note that -s is needed to allow breakpoints, unless you already have a pytest.ini file present with addopts = --capture=no in it. The -q is optional, which shortens pytest console output.)

    \u23fa\ufe0f You can also use the Recorder to add code to an existing test. To do that, you'll first need to create a breakpoint in your code to insert manual browser actions:

    import pdb; pdb.set_trace()\n

    Now you'll be able to run your test with pytest, and it will stop at the breakpoint for you to add in actions: (Press c and ENTER on the command-line to continue from the breakpoint.)

    pytest TEST_NAME.py --rec -s\n

    \u23fa\ufe0f You can also set a breakpoint at the start of your test by adding --trace as a pytest command-line option: (This is useful when running Recorder Mode without any pdb breakpoints.)

    pytest TEST_NAME.py --trace --rec -s\n

    \u23fa\ufe0f After the test completes, a file called TEST_NAME_rec.py will be automatically created in the ./recordings folder, which will include the actions performed by the test, and the manual actions that you added in.

    \u23fa\ufe0f Here's a command-line notification for a completed recording:

    >>> RECORDING SAVED as: recordings/TEST_NAME_rec.py\n***************************************************\n

    \u23fa\ufe0f When running additional tests from the same Python module, Recordings will get added to the file that was created from the first test:

    >>> RECORDING ADDED to: recordings/TEST_NAME_rec.py\n***************************************************\n

    \u23fa\ufe0f Recorder Mode works by saving your recorded actions into the browser's sessionStorage. SeleniumBase then reads from the browser's sessionStorage to take the raw data and generate a full test from it. Keep in mind that sessionStorage is only present while the browser tab remains in the same domain/origin. (The sessionStorage of that tab goes away if you leave that domain/origin.) To compensate, links to web pages of different domain/origin will automatically open a new tab for you in Recorder Mode.

    \u23fa\ufe0f Additionally, the SeleniumBase self.open(URL) method will also open a new tab for you in Recorder Mode if the domain/origin is different from the current URL. If you need to navigate to a different domain/origin from within the same tab, call self.save_recorded_actions() first, which saves the recorded data for later. When a recorded test completes, SeleniumBase scans the sessionStorage data of all open browser tabs for generating the completed script.

    \u23fa\ufe0f As an alternative to activating Recorder Mode with the --rec command-line arg, you can also call self.activate_recorder() from your tests. Using the Recorder this way is only useful for tests that stay on the same URL. This is because the standard Recorder Mode functions as a Chrome extension and persists wherever the browser goes. (This version only stays on the page where called.)

    \u23fa\ufe0f (Note that same domain/origin is not the same as same URL. Example: https://xkcd.com/353 and https://xkcd.com/1537 are two different URLs with the same domain/origin. That means both URLs share the same sessionStorage, and that changes persist to different URLs of the same domain/origin. If you want to find out a website's origin during a test, just call: self.get_origin(), which returns the value of window.location.origin from the browser's console.)

    \u23fa\ufe0f Inside recorded tests, you might find the self.open_if_not_url(URL) method, which opens the URL given if the browser is not currently on that page. SeleniumBase uses this method in recorded scripts when the Recorder detects that a browser action changed the current URL. This method prevents an unnecessary page load and shows what page the test visited after a browser action.

    To learn more about SeleniumBase, check out the Docs Site:

    All the code is on GitHub:

    "}, {"location": "help_docs/shadow_dom/", "title": "\ud83d\udc64 Shadow DOM Support", "text": ""}, {"location": "help_docs/shadow_dom/#shadow-dom-support-shadow-root-interaction", "title": "Shadow DOM support / Shadow-root interaction", "text": "

    \ud83d\udd35 SeleniumBase lets you pierce through open Shadow DOM selectors (to interact with elements inside) by adding ::shadow to CSS fragments that include a shadow-root element. For multi-layered shadow-roots, you must individually pierce through each shadow-root element that you want to get through.

    \ud83d\udd35 Here are some examples of Shadow DOM selectors:

    css_1 = \"downloads-manager::shadow #no-downloads\"\n\ncss_2 = \"downloads-manager::shadow #downloadsList downloads-item::shadow #file-link\"\n\ncss_3 = \"downloads-manager::shadow downloads-toolbar::shadow cr-toolbar::shadow cr-toolbar-search-field::shadow cr-icon-button\"\n\ncss_4 = \"downloads-manager::shadow downloads-toolbar::shadow cr-toolbar::shadow cr-toolbar-search-field::shadow #searchInput\"\n\ncss_5 = \"downloads-manager::shadow downloads-toolbar::shadow cr-toolbar::shadow cr-toolbar-search-field::shadow #clearSearch\"\n

    \ud83d\udd35 The shadow-root (::shadow) elements are transitional, and therefore cannot be the final part of your CSS selectors. Complete your CSS selectors by including an element that's inside a shadow-root.

    \ud83d\udd35 NOTE: ::shadow selectors only exist within SeleniumBase. (They are not part of standard CSS.)

    \ud83d\udd35 Here are some examples of tests that interact with Shadow DOM elements: * examples/shadow_root_test.py * examples/test_shadow_dom.py * examples/old_wordle_script.py

    "}, {"location": "help_docs/syntax_formats/", "title": "\ud83d\udd21 Syntax Formats", "text": ""}, {"location": "help_docs/syntax_formats/#the-23-syntax-formats-design-patterns", "title": "The 23 Syntax Formats / Design Patterns 1. BaseCase direct class inheritance 2. BaseCase subclass inheritance 3. The \"sb\" pytest fixture (no class) 4. The \"sb\" pytest fixture (in class) 5. Page Object Model with BaseCase 6. Page Object Model with the \"sb\" fixture 7. Using \"request\" to get \"sb\" (no class) 8. Using \"request\" to get \"sb\" (in class) 9. Overriding the driver via BaseCase 10. Overriding the driver via \"sb\" fixture 11. BaseCase with Chinese translations 12. BaseCase with Dutch translations 13. BaseCase with French translations 14. BaseCase with Italian translations 15. BaseCase with Japanese translations 16. BaseCase with Korean translations 17. BaseCase with Portuguese translations 18. BaseCase with Russian translations 19. BaseCase with Spanish translations 20. Gherkin syntax with \"behave\" BDD runner 21. SeleniumBase SB (Python context manager) 22. The driver manager (via context manager) 23. The driver manager (via direct import)", "text": "SeleniumBase supports multiple ways of structuring tests:

    In this format, (which is used by most of the tests in the SeleniumBase examples folder), BaseCase is imported at the top of a Python file, followed by a Python class inheriting BaseCase. Then, any test method defined in that class automatically gains access to SeleniumBase methods, including the setUp() and tearDown() methods that are automatically called for opening and closing web browsers at the start and end of tests.

    To run a test of this format, use pytest or pynose. Adding BaseCase.main(__name__, __file__) enables python to run pytest on your file indirectly. Here's an example:

    from seleniumbase import BaseCase\nBaseCase.main(__name__, __file__)\n\nclass MyTestClass(BaseCase):\n    def test_demo_site(self):\n        self.open(\"https://seleniumbase.io/demo_page\")\n        self.type(\"#myTextInput\", \"This is Automated\")\n        self.click(\"#myButton\")\n        self.assert_element(\"tbody#tbodyId\")\n        self.assert_text(\"Automation Practice\", \"h3\")\n        self.click_link(\"SeleniumBase Demo Page\")\n        self.assert_exact_text(\"Demo Page\", \"h1\")\n        self.assert_no_js_errors()\n

    (See examples/test_demo_site.py for the full test.)

    Using BaseCase inheritance is a great starting point for anyone learning SeleniumBase, and it follows good object-oriented programming principles.

    There are situations where you may want to customize the setUp and tearDown of your tests. Maybe you want to have all your tests login to a specific web site first, or maybe you want to have your tests report results through an API call depending on whether a test passed or failed. This can be done by creating a subclass of BaseCase and then carefully creating custom setUp() and tearDown() methods that don't overwrite the critical functionality of the default SeleniumBase setUp() and tearDown() methods. Afterwards, your test classes will inherit the subclass of BaseCase with the added functionality, rather than directly inheriting BaseCase itself. Here's an example of that:

    from seleniumbase import BaseCase\nBaseCase.main(__name__, __file__)\n\nclass BaseTestCase(BaseCase):\n    def setUp(self):\n        super().setUp()\n        # <<< Run custom setUp() code for tests AFTER the super().setUp() >>>\n\n    def tearDown(self):\n        self.save_teardown_screenshot()  # On failure or \"--screenshot\"\n        if self.has_exception():\n            # <<< Run custom code if the test failed. >>>\n            pass\n        else:\n            # <<< Run custom code if the test passed. >>>\n            pass\n        # (Wrap unreliable tearDown() code in a try/except block.)\n        # <<< Run custom tearDown() code BEFORE the super().tearDown() >>>\n        super().tearDown()\n\n    def login(self):\n        # <<< Placeholder. Add your code here. >>>\n        # Reduce duplicate code in tests by having reusable methods like this.\n        # If the UI changes, the fix can be applied in one place.\n        pass\n\n    def example_method(self):\n        # <<< Placeholder. Add your code here. >>>\n        pass\n\nclass MyTests(BaseTestCase):\n    def test_example(self):\n        self.login()\n        self.example_method()\n        self.type(\"input\", \"Name\")\n        self.click(\"form button\")\n        # ...\n

    (See examples/boilerplates/base_test_case.py for more info.)

    The pytest framework comes with a unique system called fixtures, which replaces import statements at the top of Python files by importing libraries directly into test definitions. More than just being an import, a pytest fixture can also automatically call predefined setUp() and tearDown() methods at the beginning and end of test methods. To work, sb is added as an argument to each test method definition that needs SeleniumBase functionality. This means you no longer need import statements in your Python files to use SeleniumBase. If using other pytest fixtures in your tests, you may need to use the SeleniumBase fixture (instead of BaseCase class inheritance) for compatibility reasons. Here's an example of the sb fixture in a test that does not use Python classes:

    def test_sb_fixture_with_no_class(sb):\n    sb.open(\"https://google.com/ncr\")\n    sb.type('[title=\"Search\"]', 'SeleniumBase\\n')\n    sb.click('a[href*=\"github.com/seleniumbase/SeleniumBase\"]')\n    sb.click('a[title=\"seleniumbase\"]')\n

    (See the top of examples/test_sb_fixture.py for the test.)

    The sb pytest fixture can also be used inside of a class. There is a slight change to the syntax because that means test methods must also include self in their argument definitions when test methods are defined. (The self argument represents the class object, and is used in every test method that lives inside of a class.) Once again, no import statements are needed in your Python files for this to work. Here's an example of using the sb fixture in a test method that lives inside of a Python class:

    class Test_SB_Fixture:\n    def test_sb_fixture_inside_class(self, sb):\n        sb.open(\"https://google.com/ncr\")\n        sb.type('[title=\"Search\"]', 'SeleniumBase\\n')\n        sb.click('a[href*=\"github.com/seleniumbase/SeleniumBase\"]')\n        sb.click('a[title=\"examples\"]')\n

    (See the bottom of examples/test_sb_fixture.py for the test.)

    With SeleniumBase, you can use Page Objects to break out code from tests, but remember, the self variable (from test methods that inherit BaseCase) contains the driver and all other framework-specific variable definitions. Therefore, that self must be passed as an arg into any outside class method in order to call SeleniumBase methods from there. In the example below, the self variable from the test method is passed into the sb arg of the Page Object class method because the self arg of the Page Object class method is already being used for its own class. Every Python class method definition must include the self as the first arg.

    from seleniumbase import BaseCase\nBaseCase.main(__name__, __file__)\n\nclass LoginPage:\n    def login_to_swag_labs(self, sb, username):\n        sb.open(\"https://www.saucedemo.com\")\n        sb.type(\"#user-name\", username)\n        sb.type(\"#password\", \"secret_sauce\")\n        sb.click('input[type=\"submit\"]')\n\nclass MyTests(BaseCase):\n    def test_swag_labs_login(self):\n        LoginPage().login_to_swag_labs(self, \"standard_user\")\n        self.assert_element(\"div.inventory_list\")\n        self.assert_element('div:contains(\"Sauce Labs Backpack\")')\n

    (See examples/boilerplates/samples/swag_labs_test.py for the full test.)

    This is similar to the classic Page Object Model with BaseCase inheritance, except that this time we pass the sb pytest fixture from the test into the sb arg of the page object class method, (instead of passing self). Now that you're using sb as a pytest fixture, you no longer need to import BaseCase anywhere in your code. See the example below:

    class LoginPage:\n    def login_to_swag_labs(self, sb, username):\n        sb.open(\"https://www.saucedemo.com\")\n        sb.type(\"#user-name\", username)\n        sb.type(\"#password\", \"secret_sauce\")\n        sb.click('input[type=\"submit\"]')\n\nclass MyTests:\n    def test_swag_labs_login(self, sb):\n        LoginPage().login_to_swag_labs(sb, \"standard_user\")\n        sb.assert_element(\"div.inventory_list\")\n        sb.assert_element('div:contains(\"Sauce Labs Backpack\")')\n

    (See examples/boilerplates/samples/sb_swag_test.py for the full test.)

    The pytest request fixture can be used to retrieve other pytest fixtures from within tests, such as the sb fixture. This allows you to have more control over when fixtures get initialized because the fixture no longer needs to be loaded at the very beginning of test methods. This is done by calling request.getfixturevalue('sb') from the test. Here's an example of using the pytest request fixture to load the sb fixture in a test method that does not use Python classes:

    def test_request_sb_fixture(request):\n    sb = request.getfixturevalue('sb')\n    sb.open(\"https://seleniumbase.io/demo_page\")\n    sb.assert_text(\"SeleniumBase\", \"#myForm h2\")\n    sb.assert_element(\"input#myTextInput\")\n    sb.type(\"#myTextarea\", \"This is me\")\n    sb.click(\"#myButton\")\n    sb.tearDown()\n

    (See the top of examples/test_request_sb_fixture.py for the test.)

    The pytest request fixture can also be used to get the sb fixture from inside a Python class. Here's an example of that:

    class Test_Request_Fixture:\n    def test_request_sb_fixture_in_class(self, request):\n        sb = request.getfixturevalue('sb')\n        sb.open(\"https://seleniumbase.io/demo_page\")\n        sb.assert_element(\"input#myTextInput\")\n        sb.type(\"#myTextarea\", \"Automated\")\n        sb.assert_text(\"This Text is Green\", \"#pText\")\n        sb.click(\"#myButton\")\n        sb.assert_text(\"This Text is Purple\", \"#pText\")\n        sb.tearDown()\n

    (See the bottom of examples/test_request_sb_fixture.py for the test.)

    When you want to use SeleniumBase methods via BaseCase, but you want total freedom to control how you spin up your web browsers, this is the format you want. Although SeleniumBase gives you plenty of command-line options to change how your browsers are launched, this format gives you more control when the existing options aren't enough. Here's an example of that:

    from selenium import webdriver\nfrom seleniumbase import BaseCase\nBaseCase.main(__name__, __file__)\n\nclass OverrideDriverTest(BaseCase):\n    def get_new_driver(self, *args, **kwargs):\n\"\"\"This method overrides get_new_driver() from BaseCase.\"\"\"\n        options = webdriver.ChromeOptions()\n        options.add_argument(\"--disable-3d-apis\")\n        options.add_argument(\"--disable-notifications\")\n        if self.headless:\n            options.add_argument(\"--headless=new\")\n            options.add_argument(\"--disable-gpu\")\n        options.add_experimental_option(\n            \"excludeSwitches\", [\"enable-automation\", \"enable-logging\"],\n        )\n        prefs = {\n            \"credentials_enable_service\": False,\n            \"profile.password_manager_enabled\": False,\n        }\n        options.add_experimental_option(\"prefs\", prefs)\n        return webdriver.Chrome(options=options)\n\n    def test_simple(self):\n        self.open(\"https://seleniumbase.io/demo_page\")\n        self.assert_text(\"Demo Page\", \"h1\")\n

    (From examples/test_override_driver.py)

    The above format lets you customize selenium-wire for intercepting and inspecting requests and responses during SeleniumBase tests. Here's how a selenium-wire integration may look:

    from seleniumbase import BaseCase\nfrom seleniumwire import webdriver  # Requires \"pip install selenium-wire\"\nBaseCase.main(__name__, __file__)\n\n\nclass WireTestCase(BaseCase):\n    def get_new_driver(self, *args, **kwargs):\n        options = webdriver.ChromeOptions()\n        options.add_experimental_option(\n            \"excludeSwitches\", [\"enable-automation\"]\n        )\n        options.add_experimental_option(\"useAutomationExtension\", False)\n        return webdriver.Chrome(options=options)\n\n    def test_simple(self):\n        self.open(\"https://seleniumbase.io/demo_page\")\n        for request in self.driver.requests:\n            print(request.url)\n

    (NOTE: The selenium-wire integration is now included with seleniumbase: Add --wire as a pytest command-line option to activate.)

    When you want to use SeleniumBase methods via the sb pytest fixture, but you want total freedom to control how you spin up your web browsers, this is the format you want. Although SeleniumBase gives you plenty of command-line options to change how your browsers are launched, this format gives you more control when the existing options aren't enough.

    \"\"\"Overriding the \"sb\" fixture to override the driver.\"\"\"\nimport pytest\n\n@pytest.fixture()\ndef sb(request):\n    from selenium import webdriver\n    from seleniumbase import BaseCase\n\n    class BaseClass(BaseCase):\n        def get_new_driver(self, *args, **kwargs):\n\"\"\"This method overrides get_new_driver() from BaseCase.\"\"\"\n            options = webdriver.ChromeOptions()\n            if self.headless:\n                options.add_argument(\"--headless=new\")\n                options.add_argument(\"--disable-gpu\")\n            options.add_experimental_option(\n                \"excludeSwitches\", [\"enable-automation\"],\n            )\n            return webdriver.Chrome(options=options)\n\n        def setUp(self):\n            super().setUp()\n\n        def base_method(self):\n            pass\n\n        def tearDown(self):\n            self.save_teardown_screenshot()  # On failure or \"--screenshot\"\n            super().tearDown()\n\n    sb = BaseClass(\"base_method\")\n    sb.setUpClass()\n    sb.setUp()\n    yield sb\n    sb.tearDown()\n    sb.tearDownClass()\n\ndef test_override_fixture_no_class(sb):\n    sb.open(\"https://seleniumbase.io/demo_page\")\n    sb.type(\"#myTextInput\", \"This is Automated\")\n\nclass TestOverride:\n    def test_override_fixture_inside_class(self, sb):\n        sb.open(\"https://seleniumbase.io/demo_page\")\n        sb.type(\"#myTextInput\", \"This is Automated\")\n

    (From examples/test_override_sb_fixture.py)

    Here's how the selenium-wire integration may look when overriding the sb pytest fixture to override the driver:

    import pytest\n\n@pytest.fixture()\ndef sb(request):\n    import sys\n    from seleniumbase import BaseCase\n    from seleniumwire import webdriver  # Requires \"pip install selenium-wire\"\n\n    class BaseClass(BaseCase):\n        def get_new_driver(self, *args, **kwargs):\n            options = webdriver.ChromeOptions()\n            if \"linux\" in sys.platform:\n                options.add_argument(\"--headless=new\")\n            options.add_experimental_option(\n                \"excludeSwitches\", [\"enable-automation\"],\n            )\n            return webdriver.Chrome(options=options)\n\n        def setUp(self):\n            super().setUp()\n\n        def tearDown(self):\n            self.save_teardown_screenshot()  # On failure or \"--screenshot\"\n            super().tearDown()\n\n        def base_method(self):\n            pass\n\n    sb = BaseClass(\"base_method\")\n    sb.setUpClass()\n    sb.setUp()\n    yield sb\n    sb.tearDown()\n    sb.tearDownClass()\n\ndef test_wire_with_no_class(sb):\n    sb.open(\"https://seleniumbase.io/demo_page\")\n    for request in sb.driver.requests:\n        print(request.url)\n\nclass TestWire:\n    def test_wire_inside_class(self, sb):\n        sb.open(\"https://seleniumbase.io/demo_page\")\n        for request in sb.driver.requests:\n            print(request.url)\n

    (NOTE: The selenium-wire integration is now included with seleniumbase: Add --wire as a pytest command-line option to activate. If you need both --wire with --undetected modes together, you'll still need to override get_new_driver().)

    This format is similar to the English version with BaseCase inheritance, but there's a different import statement, and method names have been translated into Chinese. Here's an example of that:

    from seleniumbase.translate.chinese import \u7852\u6d4b\u8bd5\u7528\u4f8b\n\u7852\u6d4b\u8bd5\u7528\u4f8b.main(__name__, __file__)\n\n\nclass \u6211\u7684\u6d4b\u8bd5\u7c7b(\u7852\u6d4b\u8bd5\u7528\u4f8b):\n    def test_\u4f8b\u5b501(self):\n        self.\u5f00\u542f(\"https://zh.wikipedia.org/wiki/\")\n        self.\u65ad\u8a00\u6807\u9898(\"\u7ef4\u57fa\u767e\u79d1\uff0c\u81ea\u7531\u7684\u767e\u79d1\u5168\u4e66\")\n        self.\u65ad\u8a00\u5143\u7d20('a[title=\"Wikipedia:\u5173\u4e8e\"]')\n        self.\u65ad\u8a00\u6587\u672c(\"\u65b0\u95fb\u52a8\u6001\", \"span#\u65b0\u95fb\u52a8\u6001\")\n        self.\u8f93\u5165\u6587\u672c('input[name=\"search\"]', \"\u821e\u9f8d\")\n        self.\u5355\u51fb('button:contains(\"\u641c\u7d22\")')\n        self.\u65ad\u8a00\u6587\u672c(\"\u821e\u9f8d\", \"#firstHeading\")\n        self.\u65ad\u8a00\u5143\u7d20('img[src*=\"Chinese_draak.jpg\"]')\n        self.\u56de\u53bb()\n        self.\u8f93\u5165\u6587\u672c('input[name=\"search\"]', \"\u9ebb\u5a46\u8c46\u8150\")\n        self.\u5355\u51fb('button:contains(\"\u641c\u7d22\")')\n        self.\u65ad\u8a00\u6587\u672c(\"\u9ebb\u5a46\u8c46\u8150\", \"#firstHeading\")\n        self.\u65ad\u8a00\u5143\u7d20('figure:contains(\"\u4e00\u5bb6\u4e2d\u9910\u9928\u7684\u9ebb\u5a46\u8c46\u8150\")')\n        self.\u56de\u53bb()\n        self.\u8f93\u5165\u6587\u672c('input[name=\"search\"]', \"\u7cbe\u6b66\u82f1\u96c4\")\n        self.\u5355\u51fb('button:contains(\"\u641c\u7d22\")')\n        self.\u65ad\u8a00\u5143\u7d20('img[src*=\"Fist_of_legend.jpg\"]')\n        self.\u65ad\u8a00\u6587\u672c(\"\u674e\u8fde\u6770\", 'li a[title=\"\u674e\u8fde\u6770\"]')\n

    (See examples/translations/chinese_test_1.py for the Chinese test.)

    This format is similar to the English version with BaseCase inheritance, but there's a different import statement, and method names have been translated into Dutch. Here's an example of that:

    from seleniumbase.translate.dutch import Testgeval\nTestgeval.main(__name__, __file__)\n\n\nclass MijnTestklasse(Testgeval):\n    def test_voorbeeld_1(self):\n        self.openen(\"https://nl.wikipedia.org/wiki/Hoofdpagina\")\n        self.controleren_element('a[title*=\"hoofdpagina gaan\"]')\n        self.controleren_tekst(\"Welkom op Wikipedia\", \"td.hp-welkom\")\n        self.typ(\"#searchInput\", \"Stroopwafel\")\n        self.klik(\"#searchButton\")\n        self.controleren_tekst(\"Stroopwafel\", \"#firstHeading\")\n        self.controleren_element('img[src*=\"Stroopwafels\"]')\n        self.typ(\"#searchInput\", \"Rijksmuseum Amsterdam\")\n        self.klik(\"#searchButton\")\n        self.controleren_tekst(\"Rijksmuseum\", \"#firstHeading\")\n        self.controleren_element('img[src*=\"Rijksmuseum\"]')\n        self.terug()\n        self.controleren_url_bevat(\"Stroopwafel\")\n        self.vooruit()\n        self.controleren_url_bevat(\"Rijksmuseum\")\n

    (See examples/translations/dutch_test_1.py for the Dutch test.)

    This format is similar to the English version with BaseCase inheritance, but there's a different import statement, and method names have been translated into French. Here's an example of that:

    from seleniumbase.translate.french import CasDeBase\nCasDeBase.main(__name__, __file__)\n\n\nclass MaClasseDeTest(CasDeBase):\n    def test_exemple_1(self):\n        self.ouvrir(\"https://fr.wikipedia.org/wiki/\")\n        self.v\u00e9rifier_texte(\"Wikip\u00e9dia\")\n        self.v\u00e9rifier_\u00e9l\u00e9ment('[alt=\"Wikip\u00e9dia\"]')\n        self.js_taper(\"#searchform input\", \"Cr\u00e8me br\u00fbl\u00e9e\")\n        self.cliquer(\"#searchform button\")\n        self.v\u00e9rifier_texte(\"Cr\u00e8me br\u00fbl\u00e9e\", \"#firstHeading\")\n        self.v\u00e9rifier_\u00e9l\u00e9ment('img[alt*=\"Cr\u00e8me br\u00fbl\u00e9e\"]')\n        self.js_taper(\"#searchform input\", \"Jardin des Tuileries\")\n        self.cliquer(\"#searchform button\")\n        self.v\u00e9rifier_texte(\"Jardin des Tuileries\", \"#firstHeading\")\n        self.v\u00e9rifier_\u00e9l\u00e9ment('img[alt*=\"Jardin des Tuileries\"]')\n        self.retour()\n        self.v\u00e9rifier_url_contient(\"br\u00fbl\u00e9e\")\n        self.en_avant()\n        self.v\u00e9rifier_url_contient(\"Jardin\")\n

    (See examples/translations/french_test_1.py for the French test.)

    This format is similar to the English version with BaseCase inheritance, but there's a different import statement, and method names have been translated into Italian. Here's an example of that:

    from seleniumbase.translate.italian import CasoDiProva\nCasoDiProva.main(__name__, __file__)\n\n\nclass MiaClasseDiTest(CasoDiProva):\n    def test_esempio_1(self):\n        self.apri(\"https://it.wikipedia.org/wiki/\")\n        self.verificare_testo(\"Wikipedia\")\n        self.verificare_elemento('a[title=\"Lingua italiana\"]')\n        self.digitare(\"#searchInput\", \"Pizza\")\n        self.fare_clic(\"#searchButton\")\n        self.verificare_testo(\"Pizza\", \"#firstHeading\")\n        self.verificare_elemento('figure img[src*=\"pizza\"]')\n        self.digitare(\"#searchInput\", \"Colosseo\")\n        self.fare_clic(\"#searchButton\")\n        self.verificare_testo(\"Colosseo\", \"#firstHeading\")\n        self.verificare_elemento('figure img[src*=\"Colosseo\"]')\n        self.indietro()\n        self.verificare_url_contiene(\"Pizza\")\n        self.avanti()\n        self.verificare_url_contiene(\"Colosseo\")\n

    (See examples/translations/italian_test_1.py for the Italian test.)

    This format is similar to the English version with BaseCase inheritance, but there's a different import statement, and method names have been translated into Japanese. Here's an example of that:

    from seleniumbase.translate.japanese import \u30bb\u30ec\u30cb\u30a6\u30e0\u30c6\u30b9\u30c8\u30b1\u30fc\u30b9\n\u30bb\u30ec\u30cb\u30a6\u30e0\u30c6\u30b9\u30c8\u30b1\u30fc\u30b9.main(__name__, __file__)\n\n\nclass \u79c1\u306e\u30c6\u30b9\u30c8\u30af\u30e9\u30b9(\u30bb\u30ec\u30cb\u30a6\u30e0\u30c6\u30b9\u30c8\u30b1\u30fc\u30b9):\n    def test_\u4f8b1(self):\n        self.\u3092\u958b\u304f(\"https://ja.wikipedia.org/wiki/\")\n        self.\u30c6\u30ad\u30b9\u30c8\u3092\u78ba\u8a8d\u3059\u308b(\"\u30a6\u30a3\u30ad\u30da\u30c7\u30a3\u30a2\")\n        self.\u8981\u7d20\u3092\u78ba\u8a8d\u3059\u308b('[title*=\"\u30a6\u30a3\u30ad\u30da\u30c7\u30a3\u30a2\u3078\u3088\u3046\u3053\u305d\"]')\n        self.JS\u5165\u529b('input[name=\"search\"]', \"\u30a2\u30cb\u30e1\")\n        self.\u30af\u30ea\u30c3\u30af\u3057\u3066(\"#searchform button\")\n        self.\u30c6\u30ad\u30b9\u30c8\u3092\u78ba\u8a8d\u3059\u308b(\"\u30a2\u30cb\u30e1\", \"#firstHeading\")\n        self.JS\u5165\u529b('input[name=\"search\"]', \"\u5bff\u53f8\")\n        self.\u30af\u30ea\u30c3\u30af\u3057\u3066(\"#searchform button\")\n        self.\u30c6\u30ad\u30b9\u30c8\u3092\u78ba\u8a8d\u3059\u308b(\"\u5bff\u53f8\", \"#firstHeading\")\n        self.\u8981\u7d20\u3092\u78ba\u8a8d\u3059\u308b('img[alt=\"\u63e1\u308a\u5bff\u53f8\"]')\n        self.JS\u5165\u529b(\"#searchInput\", \"\u30ec\u30b4\u30e9\u30f3\u30c9\u30fb\u30b8\u30e3\u30d1\u30f3\")\n        self.\u30af\u30ea\u30c3\u30af\u3057\u3066(\"#searchform button\")\n        self.\u8981\u7d20\u3092\u78ba\u8a8d\u3059\u308b('img[src*=\"LEGOLAND_JAPAN\"]')\n        self.\u30ea\u30f3\u30af\u30c6\u30ad\u30b9\u30c8\u3092\u78ba\u8a8d\u3059\u308b(\"\u540d\u53e4\u5c4b\u57ce\")\n        self.\u30ea\u30f3\u30af\u30c6\u30ad\u30b9\u30c8\u3092\u30af\u30ea\u30c3\u30af\u3057\u307e\u3059(\"\u30c6\u30fc\u30de\u30d1\u30fc\u30af\")\n        self.\u30c6\u30ad\u30b9\u30c8\u3092\u78ba\u8a8d\u3059\u308b(\"\u30c6\u30fc\u30de\u30d1\u30fc\u30af\", \"#firstHeading\")\n

    (See examples/translations/japanese_test_1.py for the Japanese test.)

    This format is similar to the English version with BaseCase inheritance, but there's a different import statement, and method names have been translated into Korean. Here's an example of that:

    from seleniumbase.translate.korean import \uc140\ub808\ub284_\ud14c\uc2a4\ud2b8_\ucf00\uc774\uc2a4\n\uc140\ub808\ub284_\ud14c\uc2a4\ud2b8_\ucf00\uc774\uc2a4.main(__name__, __file__)\n\n\nclass \ud14c\uc2a4\ud2b8_\ud074\ub798\uc2a4(\uc140\ub808\ub284_\ud14c\uc2a4\ud2b8_\ucf00\uc774\uc2a4):\n    def test_\uc2e4\uc2dc\uc608_1(self):\n        self.\uc5f4\uae30(\"https://ko.wikipedia.org/wiki/\")\n        self.\ud14d\uc2a4\ud2b8_\ud655\uc778(\"\uc704\ud0a4\ubc31\uacfc\")\n        self.\uc694\uc18c_\ud655\uc778('[title=\"\uc704\ud0a4\ubc31\uacfc:\uc18c\uac1c\"]')\n        self.JS_\uc785\ub825(\"#searchform input\", \"\uae40\uce58\")\n        self.\ud074\ub9ad(\"#searchform button\")\n        self.\ud14d\uc2a4\ud2b8_\ud655\uc778(\"\uae40\uce58\", \"#firstHeading\")\n        self.\uc694\uc18c_\ud655\uc778('img[src*=\"Various_kimchi.jpg\"]')\n        self.\ub9c1\ud06c_\ud14d\uc2a4\ud2b8_\ud655\uc778(\"\ud55c\uad6d \uc694\ub9ac\")\n        self.JS_\uc785\ub825(\"#searchform input\", \"\ube44\ube54\ubc25\")\n        self.\ud074\ub9ad(\"#searchform button\")\n        self.\ud14d\uc2a4\ud2b8_\ud655\uc778(\"\ube44\ube54\ubc25\", \"#firstHeading\")\n        self.\uc694\uc18c_\ud655\uc778('img[src*=\"Dolsot-bibimbap.jpg\"]')\n        self.\ub9c1\ud06c_\ud14d\uc2a4\ud2b8\ub97c_\ud074\ub9ad\ud569\ub2c8\ub2e4(\"\ub3cc\uc1a5\ube44\ube54\ubc25\")\n        self.\ud14d\uc2a4\ud2b8_\ud655\uc778(\"\ub3cc\uc1a5\ube44\ube54\ubc25\", \"#firstHeading\")\n

    (See examples/translations/korean_test_1.py for the Korean test.)

    This format is similar to the English version with BaseCase inheritance, but there's a different import statement, and method names have been translated into Portuguese. Here's an example of that:

    from seleniumbase.translate.portuguese import CasoDeTeste\nCasoDeTeste.main(__name__, __file__)\n\n\nclass MinhaClasseDeTeste(CasoDeTeste):\n    def test_exemplo_1(self):\n        self.abrir(\"https://pt.wikipedia.org/wiki/\")\n        self.verificar_texto(\"Wikip\u00e9dia\")\n        self.verificar_elemento('[title=\"L\u00edngua portuguesa\"]')\n        self.digitar(\"#searchform input\", \"Jo\u00e3o Pessoa\")\n        self.clique(\"#searchform button\")\n        self.verificar_texto(\"Jo\u00e3o Pessoa\", \"#firstHeading\")\n        self.verificar_elemento('img[alt*=\"Jo\u00e3o Pessoa\"]')\n        self.digitar(\"#searchform input\", \"Florian\u00f3polis\")\n        self.clique(\"#searchform button\")\n        self.verificar_texto(\"Florian\u00f3polis\", \"h1#firstHeading\")\n        self.verificar_elemento('td:contains(\"Avenida Beira-Mar\")')\n        self.voltar()\n        self.verificar_url_cont\u00e9m(\"Jo\u00e3o_Pessoa\")\n        self.atualizar_a_p\u00e1gina()\n        self.js_digitar(\"#searchform input\", \"Teatro Amazonas\")\n        self.clique(\"#searchform button\")\n        self.verificar_texto(\"Teatro Amazonas\", \"#firstHeading\")\n        self.verificar_texto_do_link(\"Festival Amazonas de \u00d3pera\")\n

    (See examples/translations/portuguese_test_1.py for the Portuguese test.)

    This format is similar to the English version with BaseCase inheritance, but there's a different import statement, and method names have been translated into Russian. Here's an example of that:

    from seleniumbase.translate.russian import \u0422\u0435\u0441\u0442\u041d\u0430\u0421\u0435\u043b\u0435\u043d\n\u0422\u0435\u0441\u0442\u041d\u0430\u0421\u0435\u043b\u0435\u043d.main(__name__, __file__)\n\n\nclass \u041c\u043e\u0439\u0422\u0435\u0441\u0442\u043e\u0432\u044b\u0439\u041a\u043b\u0430\u0441\u0441(\u0422\u0435\u0441\u0442\u041d\u0430\u0421\u0435\u043b\u0435\u043d):\n    def test_\u043f\u0440\u0438\u043c\u0435\u0440_1(self):\n        self.\u043e\u0442\u043a\u0440\u044b\u0442\u044c(\"https://ru.wikipedia.org/wiki/\")\n        self.\u043f\u043e\u0434\u0442\u0432\u0435\u0440\u0434\u0438\u0442\u044c_\u044d\u043b\u0435\u043c\u0435\u043d\u0442('[title=\"\u0420\u0443\u0441\u0441\u043a\u0438\u0439 \u044f\u0437\u044b\u043a\"]')\n        self.\u043f\u043e\u0434\u0442\u0432\u0435\u0440\u0434\u0438\u0442\u044c_\u0442\u0435\u043a\u0441\u0442(\"\u0412\u0438\u043a\u0438\u043f\u0435\u0434\u0438\u044f\", \"h2.main-wikimedia-header\")\n        self.\u0432\u0432\u0435\u0434\u0438\u0442\u0435(\"#searchInput\", \"\u041c\u0413\u0423\")\n        self.\u043d\u0430\u0436\u043c\u0438\u0442\u0435(\"#searchButton\")\n        self.\u043f\u043e\u0434\u0442\u0432\u0435\u0440\u0434\u0438\u0442\u044c_\u0442\u0435\u043a\u0441\u0442(\"\u0443\u043d\u0438\u0432\u0435\u0440\u0441\u0438\u0442\u0435\u0442\", \"#firstHeading\")\n        self.\u043f\u043e\u0434\u0442\u0432\u0435\u0440\u0434\u0438\u0442\u044c_\u044d\u043b\u0435\u043c\u0435\u043d\u0442('img[alt*=\"\u0413\u043b\u0430\u0432\u043d\u043e\u0435 \u0437\u0434\u0430\u043d\u0438\u0435 \u041c\u0413\u0423\"]')\n        self.\u0432\u0432\u0435\u0434\u0438\u0442\u0435(\"#searchInput\", \"\u043f\u0440\u0438\u043a\u043b\u044e\u0447\u0435\u043d\u0438\u044f \u0428\u0443\u0440\u0438\u043a\u0430\")\n        self.\u043d\u0430\u0436\u043c\u0438\u0442\u0435(\"#searchButton\")\n        self.\u043f\u043e\u0434\u0442\u0432\u0435\u0440\u0434\u0438\u0442\u044c_\u0442\u0435\u043a\u0441\u0442(\"\u041e\u043f\u0435\u0440\u0430\u0446\u0438\u044f \u00ab\u042b\u00bb \u0438 \u0434\u0440\u0443\u0433\u0438\u0435 \u043f\u0440\u0438\u043a\u043b\u044e\u0447\u0435\u043d\u0438\u044f \u0428\u0443\u0440\u0438\u043a\u0430\")\n        self.\u043f\u043e\u0434\u0442\u0432\u0435\u0440\u0434\u0438\u0442\u044c_\u044d\u043b\u0435\u043c\u0435\u043d\u0442('img[alt=\"\u041f\u043e\u0441\u0442\u0435\u0440 \u0444\u0438\u043b\u044c\u043c\u0430\"]')\n        self.\u043d\u0430\u0437\u0430\u0434()\n        self.\u043f\u043e\u0434\u0442\u0432\u0435\u0440\u0434\u0438\u0442\u044c_URL_\u0441\u043e\u0434\u0435\u0440\u0436\u0438\u0442(\"\u0443\u043d\u0438\u0432\u0435\u0440\u0441\u0438\u0442\u0435\u0442\")\n        self.\u0432\u043f\u0435\u0440\u0435\u0434()\n        self.\u043f\u043e\u0434\u0442\u0432\u0435\u0440\u0434\u0438\u0442\u044c_URL_\u0441\u043e\u0434\u0435\u0440\u0436\u0438\u0442(\"\u0428\u0443\u0440\u0438\u043a\u0430\")\n

    (See examples/translations/russian_test_1.py for the Russian test.)

    This format is similar to the English version with BaseCase inheritance, but there's a different import statement, and method names have been translated into Spanish. Here's an example of that:

    from seleniumbase.translate.spanish import CasoDePrueba\nCasoDePrueba.main(__name__, __file__)\n\n\nclass MiClaseDePrueba(CasoDePrueba):\n    def test_ejemplo_1(self):\n        self.abrir(\"https://es.wikipedia.org/wiki/\")\n        self.verificar_texto(\"Wikipedia\")\n        self.verificar_elemento('[title=\"Wikipedia:Bienvenidos\"]')\n        self.escriba('[name=\"search\"]', \"Parque de Atracciones Tibidabo\")\n        self.haga_clic('button:contains(\"Buscar\")')\n        self.verificar_texto(\"Tibidabo\", \"#firstHeading\")\n        self.verificar_elemento('img[src*=\"Tibidabo\"]')\n        self.escriba('input[name=\"search\"]', \"Palma de Mallorca\")\n        self.haga_clic('button:contains(\"Buscar\")')\n        self.verificar_texto(\"Palma de Mallorca\", \"#firstHeading\")\n        self.verificar_elemento('img[src*=\"Palma\"]')\n        self.volver()\n        self.verificar_url_contiene(\"Tibidabo\")\n        self.adelante()\n        self.verificar_url_contiene(\"Mallorca\")\n

    (See examples/translations/spanish_test_1.py for the Spanish test.)

    With Behave's BDD Gherkin format, you can use natural language to write tests that work with SeleniumBase methods. Behave tests are run by calling behave on the command-line. This requires some special files in a specific directory structure. Here's an example of that structure:

    features/\n\u251c\u2500\u2500 __init__.py\n\u251c\u2500\u2500 behave.ini\n\u251c\u2500\u2500 environment.py\n\u251c\u2500\u2500 feature_file.feature\n\u2514\u2500\u2500 steps/\n    \u251c\u2500\u2500 __init__.py\n    \u251c\u2500\u2500 imported.py\n    \u2514\u2500\u2500 step_file.py\n

    A *.feature file might look like this:

    Feature: SeleniumBase scenarios for the RealWorld App\n\nScenario: Verify RealWorld App (log in / sign out)\n    Given Open \"seleniumbase.io/realworld/login\"\nAnd Clear Session Storage\nWhen Type \"demo_user\" into \"#username\"\nAnd Type \"secret_pass\" into \"#password\"\nAnd Do MFA \"GAXG2MTEOR3DMMDG\" into \"#totpcode\"\nThen Assert exact text \"Welcome!\" in \"h1\"\nAnd Highlight \"img#image1\"\nAnd Click 'a:contains(\"This Page\")'\nAnd Save screenshot to logs\nWhen Click link \"Sign out\"\nThen Assert element 'a:contains(\"Sign in\")'\nAnd Assert text \"You have been signed out!\"\n

    (From examples/behave_bdd/features/realworld.feature)

    You'll need the environment.py file for tests to work. Here it is:

    from seleniumbase import BaseCase\nfrom seleniumbase.behave import behave_sb\nbehave_sb.set_base_class(BaseCase)  # Accepts a BaseCase subclass\nfrom seleniumbase.behave.behave_sb import before_all  # noqa\nfrom seleniumbase.behave.behave_sb import before_feature  # noqa\nfrom seleniumbase.behave.behave_sb import before_scenario  # noqa\nfrom seleniumbase.behave.behave_sb import before_step  # noqa\nfrom seleniumbase.behave.behave_sb import after_step  # noqa\nfrom seleniumbase.behave.behave_sb import after_scenario  # noqa\nfrom seleniumbase.behave.behave_sb import after_feature  # noqa\nfrom seleniumbase.behave.behave_sb import after_all  # noqa\n

    (From examples/behave_bdd/features/environment.py)

    Inside that file, you can use BaseCase (or a subclass) for the inherited class.

    For your behave tests to have access to SeleniumBase Behave steps, you can create an imported.py file with the following line:

    from seleniumbase.behave import steps  # noqa\n

    That will allow you to use lines like this in your *.feature files:

    Feature: SeleniumBase scenarios for the RealWorld App\n\nScenario: Verify RealWorld App (log in / sign out)\n    Given Open \"seleniumbase.io/realworld/login\"\nAnd Clear Session Storage\nWhen Type \"demo_user\" into \"#username\"\nAnd Type \"secret_pass\" into \"#password\"\nAnd Do MFA \"GAXG2MTEOR3DMMDG\" into \"#totpcode\"\nThen Assert exact text \"Welcome!\" in \"h1\"\nAnd Highlight \"img#image1\"\nAnd Click 'a:contains(\"This Page\")'\nAnd Save screenshot to logs\n

    You can also create your own step files (Eg. step_file.py):

    from behave import step\n\n@step(\"Open the Swag Labs Login Page\")\ndef go_to_swag_labs(context):\n    sb = context.sb\n    sb.open(\"https://www.saucedemo.com\")\n    sb.clear_local_storage()\n\n@step(\"Login to Swag Labs with {user}\")\ndef login_to_swag_labs(context, user):\n    sb = context.sb\n    sb.type(\"#user-name\", user)\n    sb.type(\"#password\", \"secret_sauce\\n\")\n

    (For more information, see the SeleniumBase Behave BDD ReadMe.)

    This format provides a pure Python way of using SeleniumBase without a test runner. Options can be passed via method instantiation or from the command-line. When setting the test option to True (or calling python --test), then standard test logging will occur, such as screenshots and reports for failing tests. All the usual SeleniumBase options are available, such as customizing the browser settings, etc. Here are some examples:

    from seleniumbase import SB\n\nwith SB() as sb:  # By default, browser=\"chrome\" if not set.\n    sb.open(\"https://seleniumbase.github.io/realworld/login\")\n    sb.type(\"#username\", \"demo_user\")\n    sb.type(\"#password\", \"secret_pass\")\n    sb.enter_mfa_code(\"#totpcode\", \"GAXG2MTEOR3DMMDG\")  # 6-digit\n    sb.assert_text(\"Welcome!\", \"h1\")\n    sb.highlight(\"img#image1\")  # A fancier assert_element() call\n    sb.click('a:contains(\"This Page\")')  # Use :contains() on any tag\n    sb.click_link(\"Sign out\")  # Link must be \"a\" tag. Not \"button\".\n    sb.assert_element('a:contains(\"Sign in\")')\n    sb.assert_exact_text(\"You have been signed out!\", \"#top_message\")\n

    (See examples/raw_sb.py for the test.)

    Here's another example, which uses test mode:

    from seleniumbase import SB\n\nwith SB(test=True) as sb:\n    sb.open(\"https://google.com/ncr\")\n    sb.type('[name=\"q\"]', \"SeleniumBase on GitHub\\n\")\n    sb.click('a[href*=\"github.com/seleniumbase\"]')\n    sb.highlight(\"div.Layout-main\")\n    sb.highlight(\"div.Layout-sidebar\")\n    sb.sleep(0.5)\n\nwith SB(test=True, rtf=True, demo=True) as sb:\n    sb.open(\"seleniumbase.github.io/demo_page\")\n    sb.type(\"#myTextInput\", \"This is Automated\")\n    sb.assert_text(\"This is Automated\", \"#myTextInput\")\n    sb.assert_text(\"This Text is Green\", \"#pText\")\n    sb.click('button:contains(\"Click Me\")')\n    sb.assert_text(\"This Text is Purple\", \"#pText\")\n    sb.click(\"#checkBox1\")\n    sb.assert_element_not_visible(\"div#drop2 img#logo\")\n    sb.drag_and_drop(\"img#logo\", \"div#drop2\")\n    sb.assert_element(\"div#drop2 img#logo\")\n

    (See examples/raw_test_scripts.py for the test.)

    This pure Python format gives you a raw webdriver instance in a with block. The SeleniumBase Driver Manager will automatically make sure that your driver is compatible with your browser version. It gives you full access to customize driver options via method args or via the command-line. The driver will automatically call quit() after the code leaves the with block. Here are some examples:

    \"\"\"This script can be run with pure \"python\". (pytest not needed).\"\"\"\nfrom seleniumbase import js_utils\nfrom seleniumbase import page_actions\nfrom seleniumbase import DriverContext\n\n# Driver Context Manager - (By default, browser=\"chrome\". Lots of options)\nwith DriverContext() as driver:\n    driver.get(\"https://seleniumbase.github.io/\")\n    js_utils.highlight_with_js(driver, 'img[alt=\"SeleniumBase\"]', loops=6)\n\nwith DriverContext(browser=\"chrome\", incognito=True) as driver:\n    driver.get(\"https://seleniumbase.io/apps/calculator\")\n    page_actions.wait_for_element(driver, '[id=\"4\"]').click()\n    page_actions.wait_for_element(driver, '[id=\"2\"]').click()\n    page_actions.wait_for_text(driver, \"42\", \"#output\")\n    js_utils.highlight_with_js(driver, \"#output\", loops=6)\n\nwith DriverContext() as driver:\n    driver.get(\"https://seleniumbase.github.io/demo_page\")\n    js_utils.highlight_with_js(driver, \"h2\", loops=5)\n    by_css = \"css selector\"\n    driver.find_element(by_css, \"#myTextInput\").send_keys(\"Automation\")\n    driver.find_element(by_css, \"#checkBox1\").click()\n    js_utils.highlight_with_js(driver, \"img\", loops=5)\n

    (See examples/raw_driver_context.py for an example.)

    Another way of running Selenium tests with pure python (as opposed to using pytest or pynose) is by using this format, which bypasses BaseCase methods while still giving you a flexible driver with a manager. SeleniumBase includes helper files such as page_actions.py, which may help you get around some of the limitations of bypassing BaseCase. Here's an example:

    \"\"\"This script can be run with pure \"python\". (pytest not needed).\"\"\"\nfrom seleniumbase import Driver\nfrom seleniumbase import js_utils\nfrom seleniumbase import page_actions\n\n# Example with options. (Also accepts command-line options.)\ndriver = Driver(browser=\"chrome\", headless=False)\ntry:\n    driver.get(\"https://seleniumbase.io/apps/calculator\")\n    page_actions.wait_for_element(driver, '[id=\"4\"]').click()\n    page_actions.wait_for_element(driver, '[id=\"2\"]').click()\n    page_actions.wait_for_text(driver, \"42\", \"#output\")\n    js_utils.highlight_with_js(driver, \"#output\", loops=6)\nfinally:\n    driver.quit()\n\n# Example 2 using default args or command-line options\ndriver = Driver()\ntry:\n    driver.get(\"https://seleniumbase.github.io/demo_page\")\n    js_utils.highlight_with_js(driver, \"h2\", loops=5)\n    by_css = \"css selector\"\n    driver.find_element(by_css, \"#myTextInput\").send_keys(\"Automation\")\n    driver.find_element(by_css, \"#checkBox1\").click()\n    js_utils.highlight_with_js(driver, \"img\", loops=5)\nfinally:\n    driver.quit()\n

    (From examples/raw_browser_launcher.py)

    The above format can be used as a drop-in replacement for virtually every Python/selenium framework, as it uses the raw driver instance for handling commands. The Driver() method simplifies the work of managing drivers with optimal settings, and it can be configured via multiple method args. The Driver also accepts command-line options (such as python --headless) so that you don't need to modify your tests directly to use different settings. These command-line options only take effect if the associated method args remain unset (or set to None) for the specified options.

    "}, {"location": "help_docs/thank_you/", "title": "\ud83d\ude4f Thank You", "text": ""}, {"location": "help_docs/thank_you/#thank-you-for-flying-with-seleniumbase", "title": "Thank you for flying with SeleniumBase! \ud83e\udd85", "text": "

    SeleniumBase Playlist on YouTube:

    SeleniumBase GitHub Repo Link:

    SeleniumBase Gitter Chat Link:

    Other Social Media Links:

    "}, {"location": "help_docs/translations/", "title": "\ud83c\udf0f Translations", "text": ""}, {"location": "help_docs/translations/#translated-tests", "title": "\ud83c\udf0f Translated Tests \ud83c\ude3a Translation API \ud83c\ude3a", "text": "

    SeleniumBase supports the following 10 languages: English, Chinese, Dutch, French, Italian, Japanese, Korean, Portuguese, Russian, and Spanish. (Examples can be found in SeleniumBase/examples/translations)

    Multi-language tests run with pytest like other tests. Test methods have a one-to-one mapping to supported languages. Here's an example of a translated test:

    # Chinese Translation\nfrom seleniumbase.translate.chinese import \u7852\u6d4b\u8bd5\u7528\u4f8b\n\nclass \u6211\u7684\u6d4b\u8bd5\u7c7b(\u7852\u6d4b\u8bd5\u7528\u4f8b):\n    def test_\u4f8b\u5b501(self):\n        self.\u5f00\u542f(\"https://zh.wikipedia.org/wiki/\")\n        self.\u65ad\u8a00\u6807\u9898(\"\u7ef4\u57fa\u767e\u79d1\uff0c\u81ea\u7531\u7684\u767e\u79d1\u5168\u4e66\")\n        self.\u65ad\u8a00\u5143\u7d20('a[title=\"Wikipedia:\u5173\u4e8e\"]')\n        self.\u65ad\u8a00\u6587\u672c(\"\u65b0\u95fb\u52a8\u6001\", \"span#\u65b0\u95fb\u52a8\u6001\")\n        self.\u8f93\u5165\u6587\u672c('input[name=\"search\"]', \"\u821e\u9f8d\")\n        self.\u5355\u51fb('button:contains(\"\u641c\u7d22\")')\n        self.\u65ad\u8a00\u6587\u672c(\"\u821e\u9f8d\", \"#firstHeading\")\n        self.\u65ad\u8a00\u5143\u7d20('img[src*=\"Chinese_draak.jpg\"]')\n

    Here's another example:

    # Japanese Translation\nfrom seleniumbase.translate.japanese import \u30bb\u30ec\u30cb\u30a6\u30e0\u30c6\u30b9\u30c8\u30b1\u30fc\u30b9\n\nclass \u79c1\u306e\u30c6\u30b9\u30c8\u30af\u30e9\u30b9(\u30bb\u30ec\u30cb\u30a6\u30e0\u30c6\u30b9\u30c8\u30b1\u30fc\u30b9):\n    def test_\u4f8b1(self):\n        self.\u3092\u958b\u304f(\"https://ja.wikipedia.org/wiki/\")\n        self.\u30c6\u30ad\u30b9\u30c8\u3092\u78ba\u8a8d\u3059\u308b(\"\u30a6\u30a3\u30ad\u30da\u30c7\u30a3\u30a2\")\n        self.\u8981\u7d20\u3092\u78ba\u8a8d\u3059\u308b('[title*=\"\u30a6\u30a3\u30ad\u30da\u30c7\u30a3\u30a2\u3078\u3088\u3046\u3053\u305d\"]')\n        self.JS\u5165\u529b('input[name=\"search\"]', \"\u30a2\u30cb\u30e1\")\n        self.\u30af\u30ea\u30c3\u30af\u3057\u3066(\"#searchform button\")\n        self.\u30c6\u30ad\u30b9\u30c8\u3092\u78ba\u8a8d\u3059\u308b(\"\u30a2\u30cb\u30e1\", \"#firstHeading\")\n        self.JS\u5165\u529b('input[name=\"search\"]', \"\u5bff\u53f8\")\n        self.\u30af\u30ea\u30c3\u30af\u3057\u3066(\"#searchform button\")\n        self.\u30c6\u30ad\u30b9\u30c8\u3092\u78ba\u8a8d\u3059\u308b(\"\u5bff\u53f8\", \"#firstHeading\")\n        self.\u8981\u7d20\u3092\u78ba\u8a8d\u3059\u308b('img[alt=\"\u63e1\u308a\u5bff\u53f8\"]')\n

    You can use SeleniumBase to selectively translate the method names of any test from one language to another with the console scripts interface. Additionally, the import line at the top of the Python file will change to import the new BaseCase. Example: BaseCase becomes CasoDeTeste when a test is translated into Portuguese.

    seleniumbase translate\n
    * Usage:\nseleniumbase translate [SB_FILE.py] [LANGUAGE] [ACTION]\n\n* Languages:\n``--en`` / ``--English``  |  ``--zh`` / ``--Chinese``\n``--nl`` / ``--Dutch``    |  ``--fr`` / ``--French``\n``--it`` / ``--Italian``  |  ``--ja`` / ``--Japanese``\n``--ko`` / ``--Korean``   |  ``--pt`` / ``--Portuguese``\n``--ru`` / ``--Russian``  |  ``--es`` / ``--Spanish``\n\n* Actions:\n``-p`` / ``--print``  (Print translation output to the screen)\n``-o`` / ``--overwrite``  (Overwrite the file being translated)\n``-c`` / ``--copy``  (Copy the translation to a new ``.py`` file)\n\n* Options:\n``-n``  (include line Numbers when using the Print action)\n\n* Examples:\nTranslate test_1.py into Chinese and only print the output:\n>>> seleniumbase translate test_1.py --zh  -p\nTranslate test_2.py into Portuguese and overwrite the file:\n>>> seleniumbase translate test_2.py --pt  -o\nTranslate test_3.py into Dutch and make a copy of the file:\n>>> seleniumbase translate test_3.py --nl  -c\n\n* Output:\nTranslates a SeleniumBase Python file into the language\nspecified. Method calls and ``import`` lines get swapped.\nBoth a language and an action must be specified.\nThe ``-p`` action can be paired with one other action.\nWhen running with ``-c`` (or ``--copy``) the new file name\nwill be the original name appended with an underscore\nplus the 2-letter language code of the new language.\n(Example: Translating ``test_1.py`` into Japanese with\n``-c`` will create a new file called ``test_1_ja.py``.)\n
    "}, {"location": "help_docs/useful_grep_commands/", "title": "\ud83d\udcdc Useful grep commands", "text": ""}, {"location": "help_docs/useful_grep_commands/#useful-grep-commands", "title": "Useful grep commands", "text": "

    There are several useful grep commands for helping you find and/or replace text in multiple files. Examples:

    "}, {"location": "help_docs/useful_grep_commands/#list-all-files-containing-selfget_new_driver-ignoring-pyc-files-from-the-current-directory", "title": "List all files containing self.get_new_driver(, ignoring \".pyc\" files, from the current directory", "text": "

    grep -rl \"self.get_new_driver(\" * --exclude=\\*.pyc OR grep -rl * -e \"self.get_new_driver(\" --exclude=\\*.pyc

    To only search .py files, use --include=\\*.py:

    grep -rl \"self.get_new_driver(\" * --include=\\*.py

    "}, {"location": "help_docs/useful_grep_commands/#replace-all-occurrences-of-foo_abc-with-bar_xyz-on-linux-for-python-files-from-the-current-directory", "title": "Replace all occurrences of \"foo_abc\" with \"bar_xyz\" on Linux, for Python files from the current directory", "text": "

    sed -i 's/foo_abc/bar_xyz/g' *.py

    "}, {"location": "help_docs/useful_grep_commands/#replace-all-occurrences-of-foo_abc-with-bar_xyz-on-macos-for-python-files-from-the-current-directory", "title": "Replace all occurrences of \"foo_abc\" with \"bar_xyz\" on macOS, for Python files from the current directory", "text": "

    sed -i '' 's/foo_abc/bar_xyz/g' *.py

    "}, {"location": "help_docs/useful_grep_commands/#find-all-chromedriver-processes-this-combines-ps-with-grep", "title": "Find all chromedriver processes (this combines ps with grep):", "text": "

    ps -ef |grep chromedriver

    "}, {"location": "help_docs/useful_grep_commands/#references", "title": "References", "text": ""}, {"location": "help_docs/using_safari_driver/", "title": "\ud83e\udded Using Safari Driver", "text": ""}, {"location": "help_docs/using_safari_driver/#using-safaris-webdriver-for-running-browser-tests-on-macos", "title": "Using Safari's WebDriver for running browser tests on macOS", "text": "

    (NOTE: Safari's WebDriver requires macOS 10.13 \"High Sierra\" or later.)

    You can find the official Apple documentation regarding \"Testing with WebDriver in Safari\" on the following page: https://developer.apple.com/documentation/webkit/testing_with_webdriver_in_safari

    Run safaridriver --enable once in a terminal to enable Safari's WebDriver. (If you\u2019re upgrading from a previous macOS release, you may need to prefix the command with sudo.)

    Now you can use --browser=safari to run your SeleniumBase tests on Safari.

    "}, {"location": "help_docs/virtualenv_instructions/", "title": "\u2699\ufe0f Virtualenv Instructions", "text": ""}, {"location": "help_docs/virtualenv_instructions/#virtual-environment-tutorial", "title": "Virtual Environment Tutorial", "text": "

    There are multiple ways of creating a Python virtual environment. This tutorial covers two of those:

    venv creates virtual environments in the location where run (generally with Python projects).

    mkvirtualenv creates virtual environments in one place (generally in your home directory).

    (The Python Software Foundation recommends venv for creating virtual environments.)

    Option 1: Using \"venv\"

    macOS/Linux terminal (python3 -m venv ENV)

    python3 -m venv sbase_env\nsource sbase_env/bin/activate\n

    Windows CMD prompt (py -m venv ENV):

    py -m venv sbase_env\ncall sbase_env\\\\Scripts\\\\activate\n

    To exit a virtual env, type deactivate.

    Option 2: Using virtualenvwrapper

    macOS/Linux terminal:

    python3 -m pip install virtualenvwrapper --force-reinstall\nexport WORKON_HOME=$HOME/.virtualenvs\nsource `which virtualenvwrapper.sh`\n

    (Shortcut: Run source virtualenv_install.sh from the top-level SeleniumBase folder to perform the above steps.)

    (If you add source `which virtualenvwrapper.sh` to your local bash file (~/.bash_profile on macOS, or ~/.bashrc on Linux), virtualenvwrapper commands such as mkvirtualenv will be available whenever you open a new command prompt.)

    Windows CMD prompt:

    py -m pip install virtualenvwrapper-win --force-reinstall --user\n

    (Shortcut: Run win_virtualenv.bat from the top-level SeleniumBase folder to perform the above step.)

    Create a virtual environment:
    mkvirtualenv sbase_env\n

    (If you have multiple versions of Python installed on your machine, and you want your virtual environment to use a specific Python version, add --python=PATH_TO_PYTHON_EXE to your mkvirtualenv command with the Python executable to use.)

    virtualenvwrapper commands:

    Creating a virtual environment:

    mkvirtualenv sbase_env\n

    Leaving your virtual environment:

    deactivate\n

    Returning to a virtual environment:

    workon sbase_env\n

    Listing all virtual environments:

    workon\n

    Deleting a virtual environment:

    rmvirtualenv sbase_env\n

    If the python and python3 versions don't match (while in a virtualenv on macOS or Linux), the following command will sync the versions:

    alias python=python3\n

    (To remove an alias, use: unalias NAME)

    To verify the python version, use:

    python --version\n

    To see the PATH of your python (macOS/Linux), use:

    which python\n

    python-guide.org/en/latest/dev/virtualenvs has more information about Python virtual environments. For specific details about VirtualEnv and VirtualEnvWrapper, see http://virtualenv.readthedocs.org/en/latest/ and http://virtualenvwrapper.readthedocs.org/en/latest/.

    "}, {"location": "integrations/azure/azure_pipelines/ReadMe/", "title": "\ud83e\udd16 Azure Pipelines", "text": ""}, {"location": "integrations/azure/azure_pipelines/ReadMe/#running-browser-based-test-automation-with-azure-pipelines-by-using-seleniumbase", "title": "Running browser-based test automation with Azure Pipelines by using SeleniumBase", "text": ""}, {"location": "integrations/azure/azure_pipelines/ReadMe/#step-0-fork-the-seleniumbase-repo-on-github-to-get-started-quickly", "title": "Step 0. Fork the SeleniumBase repo on GitHub to get started quickly.", "text": ""}, {"location": "integrations/azure/azure_pipelines/ReadMe/#step-1-get-azure-pipelines-from-the-github-marketplace", "title": "Step 1. Get Azure Pipelines from the GitHub Marketplace", "text": ""}, {"location": "integrations/azure/azure_pipelines/ReadMe/#navigate-to-httpsgithubcommarketplaceazure-pipelines", "title": "Navigate to https://github.com/marketplace/azure-pipelines", "text": ""}, {"location": "integrations/azure/azure_pipelines/ReadMe/#step-2-go-to-microsoft-azure-devops-to-set-up-your-environment", "title": "Step 2. Go to Microsoft Azure DevOps to set up your environment", "text": ""}, {"location": "integrations/azure/azure_pipelines/ReadMe/#select-start-free-with-github", "title": "Select \"Start free with GitHub >\":", "text": ""}, {"location": "integrations/azure/azure_pipelines/ReadMe/#give-your-new-project-a-name-and-set-visibility-to-public-for-your-seleniumbase-fork", "title": "Give your new project a name and set visibility to public (for your SeleniumBase fork):", "text": ""}, {"location": "integrations/azure/azure_pipelines/ReadMe/#select-that-your-code-is-hosted-on-github", "title": "Select that your code is hosted on GitHub", "text": ""}, {"location": "integrations/azure/azure_pipelines/ReadMe/#select-your-fork-of-seleniumbase-as-your-repository", "title": "Select your fork of SeleniumBase as your repository", "text": ""}, {"location": "integrations/azure/azure_pipelines/ReadMe/#copy-the-azure-pipelinesyml-file-from-seleniumbase-into-the-azure-pipelinesyml-box-to-create-your-new-pipeline", "title": "Copy the azure-pipelines.yml file from SeleniumBase into the azure-pipelines.yml box to create your new pipeline", "text": ""}, {"location": "integrations/azure/azure_pipelines/ReadMe/#when-youre-done-copying-click-run", "title": "When you're done copying, click \"Run\".", "text": ""}, {"location": "integrations/azure/azure_pipelines/ReadMe/#step-3-congratulations-your-browser-tests-are-now-running", "title": "Step 3. Congratulations! Your browser tests are now running!", "text": "

    https://dev.azure.com/seleniumbase/seleniumbase/_build/results?buildId=234

    "}, {"location": "integrations/azure/azure_pipelines/ReadMe/#every-time-you-create-a-pull-request-now-azure-pipelines-will-run-your-tests-automatically", "title": "Every time you create a pull request now, Azure Pipelines will run your tests automatically.", "text": "

    To learn more, study SeleniumBase and see how the azure-pipelines.yml file works.

    "}, {"location": "integrations/azure/jenkins/ReadMe/", "title": "\ud83e\udd16 Jenkins on Azure", "text": ""}, {"location": "integrations/azure/jenkins/ReadMe/#building-a-browser-based-test-automation-server-with-jenkins-on-azure-by-using-seleniumbase", "title": "Building a browser-based test automation server with Jenkins on Azure by using SeleniumBase", "text": "

    (2022 NOTE: Steps from this 2019 tutorial from Boston Code Camp are now out-of-date. For installing Jenkins from the Azure Marketplace, you can try using Bitnami Jenkins. Or, for the newer official Microsoft tutorial, see Get Started: Install Jenkins on an Azure Linux VM, and then continue with Step 4 below to resume SeleniumBase setup after you've created your Jenkins instance.)

    "}, {"location": "integrations/azure/jenkins/ReadMe/#step-0-fork-the-seleniumbase-repo-on-github-to-get-started-quickly", "title": "Step 0. Fork the SeleniumBase repo on GitHub to get started quickly.", "text": ""}, {"location": "integrations/azure/jenkins/ReadMe/#step-1-find-jenkins-in-the-azure-marketplace", "title": "Step 1. Find Jenkins in the Azure Marketplace", "text": ""}, {"location": "integrations/azure/jenkins/ReadMe/#search-for-jenkins-in-the-azure-marketplace-and-select-the-jenkins-publisher-microsoft-result-to-get-to-the-jenkins-start-page", "title": "Search for \"Jenkins\" in the Azure Marketplace and select the Jenkins (Publisher: Microsoft) result to get to the Jenkins Start page.", "text": ""}, {"location": "integrations/azure/jenkins/ReadMe/#step-2-launch-a-jenkins-instance", "title": "Step 2. Launch a Jenkins instance", "text": ""}, {"location": "integrations/azure/jenkins/ReadMe/#click-create-and-follow-the-steps", "title": "Click \"Create\" and follow the steps...", "text": ""}, {"location": "integrations/azure/jenkins/ReadMe/#continue-to-additional-settings-when-youre-done-with-basics", "title": "Continue to \"Additional Settings\" when you're done with \"Basics\".", "text": ""}, {"location": "integrations/azure/jenkins/ReadMe/#on-the-additional-settings-section-set-the-size-to-b2s", "title": "On the \"Additional Settings\" section, set the Size to \"B2s\":", "text": ""}, {"location": "integrations/azure/jenkins/ReadMe/#once-youve-reached-step-5-click-create-to-complete-the-setup", "title": "Once you've reached Step 5, click \"Create\" to complete the setup.", "text": ""}, {"location": "integrations/azure/jenkins/ReadMe/#step-3-inspect-your-new-jenkins-instance-to-ssh-into-the-new-machine", "title": "Step 3. Inspect your new Jenkins instance to SSH into the new machine", "text": ""}, {"location": "integrations/azure/jenkins/ReadMe/#once-your-new-jenkins-instance-has-finished-launching-you-should-be-able-to-see-the-main-page", "title": "Once your new Jenkins instance has finished launching, you should be able to see the main page", "text": ""}, {"location": "integrations/azure/jenkins/ReadMe/#on-the-main-page-you-should-be-able-to-find-the-public-ip-address", "title": "On the main page, you should be able to find the Public IP Address.", "text": "
    ssh USERNAME@IP_ADDRESS\n
    "}, {"location": "integrations/azure/jenkins/ReadMe/#step-4-clone-the-seleniumbase-repository-from-the-root-directory", "title": "Step 4. Clone the SeleniumBase repository from the root (\"/\") directory.", "text": "
    cd /\nsudo git clone https://github.com/seleniumbase/SeleniumBase.git\n
    "}, {"location": "integrations/azure/jenkins/ReadMe/#step-5-enter-the-linux-folder", "title": "Step 5. Enter the \"linux\" folder", "text": "
    cd SeleniumBase/integrations/linux/\n
    "}, {"location": "integrations/azure/jenkins/ReadMe/#step-6-give-the-jenkins-user-sudo-access-see-jenkins_permissionssh-for-details", "title": "Step 6. Give the \"jenkins\" user sudo access (See jenkins_permissions.sh for details)", "text": "
    ./jenkins_permissions.sh\n
    "}, {"location": "integrations/azure/jenkins/ReadMe/#step-7-become-the-jenkins-user-and-enter-a-bash-shell", "title": "Step 7. Become the \"jenkins\" user and enter a \"bash\" shell", "text": "
    sudo su jenkins\nbash\n
    "}, {"location": "integrations/azure/jenkins/ReadMe/#step-8-install-dependencies-see-linuxfilesh-for-details", "title": "Step 8. Install dependencies (See Linuxfile.sh for details)", "text": "
    ./Linuxfile.sh\n
    "}, {"location": "integrations/azure/jenkins/ReadMe/#step-9-start-up-the-headless-browser-display-mechanism-xvfb-see-xvfb_launchersh-for-details", "title": "Step 9. Start up the headless browser display mechanism: Xvfb (See Xvfb_launcher.sh for details)", "text": "
    ./Xvfb_launcher.sh\n
    "}, {"location": "integrations/azure/jenkins/ReadMe/#step-10-go-to-the-seleniumbase-directory", "title": "Step 10. Go to the SeleniumBase directory", "text": "
    cd /SeleniumBase\n
    "}, {"location": "integrations/azure/jenkins/ReadMe/#step-11-install-the-requirements-for-seleniumbase", "title": "Step 11. Install the requirements for SeleniumBase", "text": "
    sudo pip install -r requirements.txt --upgrade\n
    "}, {"location": "integrations/azure/jenkins/ReadMe/#step-12-install-seleniumbase-make-sure-you-already-installed-the-requirements-above", "title": "Step 12. Install SeleniumBase (Make sure you already installed the requirements above)", "text": "
    sudo python setup.py develop\n
    "}, {"location": "integrations/azure/jenkins/ReadMe/#step-13-install-chromedriver", "title": "Step 13. Install chromedriver", "text": "
    sudo seleniumbase install chromedriver\n
    "}, {"location": "integrations/azure/jenkins/ReadMe/#step-14-run-an-example-test-in-chrome-to-verify-installation-may-take-up-to-10-seconds", "title": "Step 14. Run an example test in Chrome to verify installation (May take up to 10 seconds)", "text": "
    pytest examples/my_first_test.py --headless --browser=chrome\n
    "}, {"location": "integrations/azure/jenkins/ReadMe/#step-15-secure-your-jenkins-machine", "title": "Step 15. Secure your Jenkins machine", "text": ""}, {"location": "integrations/azure/jenkins/ReadMe/#navigate-to-httpjenkins_ip_addressjenkins-on-azure", "title": "Navigate to http://JENKINS_IP_ADDRESS/jenkins-on-azure/", "text": "

    (Depending on your version of Jenkins, you may see the following screen, or nothing at all.)

    "}, {"location": "integrations/azure/jenkins/ReadMe/#initially-jenkins-uses-only-http-which-makes-it-less-secure", "title": "Initially, Jenkins uses only http, which makes it less secure.", "text": ""}, {"location": "integrations/azure/jenkins/ReadMe/#youll-need-to-set-up-ssh-port-forwarding-in-order-to-secure-it", "title": "You'll need to set up SSH Port Forwarding in order to secure it.", "text": "

    ssh -L 127.0.0.1:8080:localhost:8080 USERNAME@DNS_NAME

    "}, {"location": "integrations/azure/jenkins/ReadMe/#step-16-login-to-jenkins", "title": "Step 16. Login to Jenkins", "text": ""}, {"location": "integrations/azure/jenkins/ReadMe/#if-youve-correctly-set-up-ssh-port-forwarding-the-url-will-be-http1270018080", "title": "If you've correctly set up SSH Port Forwarding, the url will be http://127.0.0.1:8080/", "text": ""}, {"location": "integrations/azure/jenkins/ReadMe/#youll-need-to-get-the-password-from-the-ssh-terminal-on-the-linux-machine-to-log-in", "title": "You'll need to get the password from the SSH terminal on the Linux machine to log in", "text": "
    sudo cat /var/lib/jenkins/secrets/initialAdminPassword\n
    "}, {"location": "integrations/azure/jenkins/ReadMe/#step-17-customize-jenkins", "title": "Step 17. Customize Jenkins", "text": ""}, {"location": "integrations/azure/jenkins/ReadMe/#step-18-create-an-admin-user", "title": "Step 18. Create an Admin user", "text": ""}, {"location": "integrations/azure/jenkins/ReadMe/#once-jenkins-has-finished-loading-the-top-left-of-the-page-should-look-like-this", "title": "Once Jenkins has finished loading, the top left of the page should look like this", "text": ""}, {"location": "integrations/azure/jenkins/ReadMe/#step-19-create-a-new-jenkins-job", "title": "Step 19. Create a new Jenkins job", "text": ""}, {"location": "integrations/azure/jenkins/ReadMe/#step-20-setup-your-new-jenkins-job", "title": "Step 20. Setup your new Jenkins job", "text": "
    cd examples\npytest my_first_test.py --headless\n
    "}, {"location": "integrations/azure/jenkins/ReadMe/#click-save-when-youre-done", "title": "Click \"Save\" when you're done.", "text": ""}, {"location": "integrations/azure/jenkins/ReadMe/#step-21-run-your-new-jenkins-job", "title": "Step 21. Run your new Jenkins job", "text": ""}, {"location": "integrations/azure/jenkins/ReadMe/#step-22-see-the-top-jenkins-page-for-an-overview-of-all-jobs", "title": "Step 22. See the top Jenkins page for an overview of all jobs", "text": ""}, {"location": "integrations/azure/jenkins/ReadMe/#step-23-future-work", "title": "Step 23. Future Work", "text": "

    If you have a web application that you want to test, you'll be able to create SeleniumBase tests and add them to Jenkins as you saw here. You may want to create a Deploy job, which downloads the latest version of your repository, and then kicks off all tests to run after that. You could then tell that Deploy job to auto-run whenever a change is pushed to your repository by using: \"Poll SCM\". All your tests would then be able to run by using: \"Build after other projects are built\".

    "}, {"location": "integrations/azure/jenkins/ReadMe/#congratulations-youre-now-well-on-your-way-to-becoming-a-build-release-automation-engineer", "title": "Congratulations! You're now well on your way to becoming a build & release / automation engineer!", "text": ""}, {"location": "integrations/docker/ReadMe/", "title": "\ud83d\udc33 Docker Start Guide", "text": ""}, {"location": "integrations/docker/ReadMe/#docker-setup-instructions-for-seleniumbase", "title": "Docker setup instructions for SeleniumBase", "text": ""}, {"location": "integrations/docker/ReadMe/#1-install-the-docker-toolbox", "title": "1. Install the Docker Toolbox", "text": "

    You can get that from here: https://www.docker.com/products/docker-toolbox

    You might also want to install the Docker Engine: https://docs.docker.com/engine/installation/

    "}, {"location": "integrations/docker/ReadMe/#2-create-your-seleniumbase-docker-environment", "title": "2. Create your SeleniumBase Docker environment", "text": "
    docker-machine create --driver virtualbox seleniumbase\n
    "}, {"location": "integrations/docker/ReadMe/#if-your-docker-environment-ever-goes-down-for-any-reason-you-can-bring-it-back-up-with-a-restart", "title": "(If your Docker environment ever goes down for any reason, you can bring it back up with a restart.)", "text": "
    docker-machine restart seleniumbase\n
    "}, {"location": "integrations/docker/ReadMe/#3-configure-your-shell", "title": "3. Configure your shell", "text": "
    eval \"$(docker-machine env seleniumbase)\"\n
    "}, {"location": "integrations/docker/ReadMe/#4-go-to-the-seleniumbase-home-directory-on-the-command-line-which-is-where-dockerfile-is-located-this-assumes-youve-already-cloned-the-seleniumbase-repo", "title": "4. Go to the SeleniumBase home directory on the command line, which is where Dockerfile is located. (This assumes you've already cloned the SeleniumBase repo.)", "text": ""}, {"location": "integrations/docker/ReadMe/#5-create-your-docker-image-from-your-dockerfile-get-ready-to-wait-awhile", "title": "5. Create your Docker image from your Dockerfile: (Get ready to wait awhile)", "text": "
    docker build -t seleniumbase .\n

    If running on an Apple M1 Mac, use this instead:

    docker build --platform linux/amd64 -t seleniumbase .\n
    "}, {"location": "integrations/docker/ReadMe/#6-run-the-example-test-with-chrome-inside-your-docker-once-the-test-completes-after-a-few-seconds-youll-automatically-exit-the-docker-shell", "title": "6. Run the example test with Chrome inside your Docker: (Once the test completes after a few seconds, you'll automatically exit the Docker shell)", "text": "
    docker run seleniumbase ./run_docker_test_in_chrome.sh\n
    "}, {"location": "integrations/docker/ReadMe/#7-now-run-the-same-test-with-firefox-inside-your-docker", "title": "7. Now run the same test with Firefox inside your Docker", "text": "
    docker run seleniumbase ./run_docker_test_in_firefox.sh\n
    "}, {"location": "integrations/docker/ReadMe/#8-you-can-also-enter-docker-and-stay-inside-the-shell", "title": "8. You can also enter Docker and stay inside the shell", "text": "
    docker run -i -t seleniumbase\n
    "}, {"location": "integrations/docker/ReadMe/#9-now-you-can-run-the-example-test-from-inside-the-docker-shell", "title": "9. Now you can run the example test from inside the Docker shell", "text": "
    ./run_docker_test_in_chrome.sh\n
    "}, {"location": "integrations/docker/ReadMe/#10-when-youre-satisfied-you-may-exit-the-docker-shell", "title": "10. When you're satisfied, you may exit the Docker shell", "text": "
    exit\n
    "}, {"location": "integrations/docker/ReadMe/#11-optional-since-docker-images-and-containers-take-up-a-lot-of-space-you-may-want-to-clean-up-your-machine-from-time-to-time-when-theyre-not-being-used", "title": "11. (Optional) Since Docker images and containers take up a lot of space, you may want to clean up your machine from time to time when they\u2019re not being used", "text": "

    Details on that can be found here: http://stackoverflow.com/questions/17236796/how-to-remove-old-docker-containers

    Here are a few of those cleanup commands:

    docker container prune\ndocker system prune\ndocker images | grep \"<none>\" | awk '{print $3}' | xargs docker rmi\ndocker rm 'docker ps --no-trunc -aq'\n

    If you want to completely remove all of your Docker containers and images, use these commands: (If there's nothing to delete, those commands will return an error.)

    docker rm -f $(docker ps -a -q)\ndocker rmi -f $(docker images -q)\n

    Finally, if you want to wipe out your SeleniumBase Docker virtualbox, use these commands:

    docker-machine kill seleniumbase\ndocker-machine rm seleniumbase\n

    For more cleanup commands, check out: https://codefresh.io/blog/everyday-hacks-docker/

    "}, {"location": "integrations/docker/ReadMe/#13-optional-more-reading-on-docker-can-be-found-here", "title": "13. (Optional) More reading on Docker can be found here", "text": ""}, {"location": "integrations/github/workflows/ReadMe/", "title": "\ud83e\udd16 GitHub CI", "text": ""}, {"location": "integrations/github/workflows/ReadMe/#running-browser-tests-on-github-actions-with-seleniumbase", "title": "Running browser tests on GitHub Actions with SeleniumBase", "text": ""}, {"location": "integrations/github/workflows/ReadMe/#step-0-create-a-fork-of-seleniumbase-on-github-to-help-you-get-started", "title": "Step 0. Create a fork of SeleniumBase on GitHub to help you get started.", "text": ""}, {"location": "integrations/github/workflows/ReadMe/#step-1-from-the-github-actions-tab-choose-to-set-up-a-python-package-workflow", "title": "Step 1. From the GitHub Actions tab, choose to set up a Python package Workflow.", "text": ""}, {"location": "integrations/github/workflows/ReadMe/#step-2-add-your-workflow-yml-script", "title": "Step 2. Add your workflow .yml script.", "text": ""}, {"location": "integrations/github/workflows/ReadMe/#step-3-commit-your-changes-to-github", "title": "Step 3. Commit your changes to GitHub.", "text": ""}, {"location": "integrations/github/workflows/ReadMe/#step-4-your-tests-will-now-run-on-every-pull-request-and-on-every-commit-to-the-master-branch", "title": "Step 4. Your tests will now run on every pull request and on every commit to the master branch.", "text": " "}, {"location": "integrations/github/workflows/ReadMe/#congratulations-you-now-know-how-to-create-and-run-browser-tests-with-github-actions", "title": "Congratulations! You now know how to create and run browser tests with GitHub Actions!", "text": ""}, {"location": "integrations/github/workflows/ReadMe/#study-seleniumbase-to-learn-more", "title": "Study SeleniumBase to learn more!", "text": ""}, {"location": "integrations/google_cloud/ReadMe/", "title": "\ud83e\udd16 Jenkins on Google Cloud", "text": ""}, {"location": "integrations/google_cloud/ReadMe/#building-a-browser-based-test-automation-server-on-the-google-cloud-platform-by-using-seleniumbase", "title": "Building a browser-based test automation server on the Google Cloud Platform by using SeleniumBase", "text": "

    (This tutorial, from a previous Google Cloud Meetup, will teach you how to setup a Linux server for running automated browser tests. The cost of running this server is about $13.60/month on Google Cloud (enough to handle 5 parallel tests). This is less expensive than using other platforms.)

    "}, {"location": "integrations/google_cloud/ReadMe/#step-1-open-the-google-cloud-platform-cloud-launcher", "title": "Step 1. Open the Google Cloud Platform Cloud Launcher", "text": ""}, {"location": "integrations/google_cloud/ReadMe/#step-2-launch-a-jenkins-instance", "title": "Step 2. Launch a Jenkins instance", "text": ""}, {"location": "integrations/google_cloud/ReadMe/#step-3-connect-with-your-new-jenkins-instance", "title": "Step 3. Connect with your new Jenkins instance", "text": ""}, {"location": "integrations/google_cloud/ReadMe/#step-4-clone-the-seleniumbase-repository-from-the-root-directory", "title": "Step 4. Clone the SeleniumBase repository from the root (\"/\") directory.", "text": "
    cd /\nsudo git clone https://github.com/seleniumbase/SeleniumBase.git\n
    "}, {"location": "integrations/google_cloud/ReadMe/#step-5-enter-the-linux-folder", "title": "Step 5. Enter the \"linux\" folder", "text": "
    cd SeleniumBase/integrations/linux/\n
    "}, {"location": "integrations/google_cloud/ReadMe/#step-6-give-jenkins-aka-tomcat-user-sudo-access-see-tomcat_permissionssh-for-details", "title": "Step 6. Give Jenkins (aka \"tomcat\" user) sudo access (See tomcat_permissions.sh for details)", "text": "
    ./tomcat_permissions.sh\n
    "}, {"location": "integrations/google_cloud/ReadMe/#step-7-become-tomcat-the-jenkins-user-and-enter-a-bash-shell", "title": "Step 7. Become \"tomcat\" (the Jenkins user) and enter a \"bash\" shell", "text": "
    sudo su tomcat\nbash\n
    "}, {"location": "integrations/google_cloud/ReadMe/#step-8-install-dependencies-see-linuxfilesh-for-details", "title": "Step 8. Install dependencies (See Linuxfile.sh for details)", "text": "
    ./Linuxfile.sh\n
    "}, {"location": "integrations/google_cloud/ReadMe/#step-9-start-up-the-headless-browser-display-mechanism-xvfb-see-xvfb_launchersh-for-details", "title": "Step 9. Start up the headless browser display mechanism: Xvfb (See Xvfb_launcher.sh for details)", "text": "
    ./Xvfb_launcher.sh\n
    "}, {"location": "integrations/google_cloud/ReadMe/#step-10-go-to-the-seleniumbase-directory", "title": "Step 10. Go to the SeleniumBase directory", "text": "
    cd /SeleniumBase\n
    "}, {"location": "integrations/google_cloud/ReadMe/#step-11-install-the-requirements-for-seleniumbase", "title": "Step 11. Install the requirements for SeleniumBase", "text": "
    sudo pip install -r requirements.txt --upgrade\n
    "}, {"location": "integrations/google_cloud/ReadMe/#step-12-install-seleniumbase", "title": "Step 12. Install SeleniumBase", "text": "
    sudo python setup.py develop\n
    "}, {"location": "integrations/google_cloud/ReadMe/#step-13-run-an-example-test-on-chrome-to-verify-installation-may-take-up-to-10-seconds", "title": "Step 13. Run an example test on Chrome to verify installation (May take up to 10 seconds)", "text": "
    pytest examples/my_first_test.py --headless\n
    "}, {"location": "integrations/google_cloud/ReadMe/#step-14-if-you-prefer-using-nosetests-that-works-too", "title": "Step 14. If you prefer using nosetests, that works too", "text": "
    nosetests examples/my_first_test.py --headless\n
    "}, {"location": "integrations/google_cloud/ReadMe/#step-15-you-can-also-verify-that-the-example-test-runs-on-firefox", "title": "Step 15. You can also verify that the example test runs on Firefox", "text": "
    pytest examples/my_first_test.py --headless --browser=firefox\n
    "}, {"location": "integrations/google_cloud/ReadMe/#step-16-login-to-jenkins", "title": "Step 16. Login to Jenkins", "text": ""}, {"location": "integrations/google_cloud/ReadMe/#step-17-create-a-new-jenkins-job", "title": "Step 17. Create a new Jenkins job", "text": ""}, {"location": "integrations/google_cloud/ReadMe/#step-18-setup-your-new-jenkins-job", "title": "Step 18. Setup your new Jenkins job", "text": "
    pytest examples/my_first_test.py --headless\n
    "}, {"location": "integrations/google_cloud/ReadMe/#step-19-run-your-new-jenkins-job", "title": "Step 19. Run your new Jenkins job", "text": ""}, {"location": "integrations/google_cloud/ReadMe/#step-20-future-work", "title": "Step 20. Future Work", "text": "

    If you have a web application that you want to test, you'll be able to create SeleniumBase tests and add them to Jenkins as you saw here. You may want to create a Deploy job, which downloads the latest version of your repository, and then kicks off all tests to run after that. You could then tell that Deploy job to auto-run whenever a change is pushed to your repository by using: \"Poll SCM\". All your tests would then be able to run by using: \"Build after other projects are built\". You can also use MySQL to save test results in the DB so that you can query the data at any time.

    "}, {"location": "integrations/google_cloud/ReadMe/#congratulations-youre-now-well-on-your-way-to-becoming-a-build-release-automation-engineer", "title": "Congratulations! You're now well on your way to becoming a build & release / automation engineer!", "text": ""}, {"location": "integrations/google_cloud/ReadMe/#mysql-db-setup-instructions", "title": "MySQL DB setup instructions", "text": ""}, {"location": "integrations/google_cloud/ReadMe/#step-21-return-to-the-google-cloud-launcher-and-launch-a-mysql-instance", "title": "Step 21. Return to the Google Cloud Launcher and launch a MySQL Instance", "text": ""}, {"location": "integrations/google_cloud/ReadMe/#step-22-get-the-connection-credentials-for-your-new-mysql-instance", "title": "Step 22. Get the Connection credentials for your new MySQL Instance", "text": ""}, {"location": "integrations/google_cloud/ReadMe/#step-23-get-a-mysql-gui-tool-so-that-you-can-connect-to-your-mysql-instance", "title": "Step 23. Get a MySQL GUI tool so that you can connect to your MySQL Instance", "text": ""}, {"location": "integrations/google_cloud/ReadMe/#step-24-create-a-new-connection-to-your-mysql-instance", "title": "Step 24. Create a new connection to your MySQL Instance", "text": ""}, {"location": "integrations/google_cloud/ReadMe/#step-25-create-a-new-databaseschema-in-your-mysql-instance", "title": "Step 25. Create a new database/schema in your MySQL Instance", "text": ""}, {"location": "integrations/google_cloud/ReadMe/#step-26-create-the-necessary-tables-in-your-mysql-databaseschema", "title": "Step 26. Create the necessary tables in your MySQL database/schema", "text": ""}, {"location": "integrations/google_cloud/ReadMe/#step-27-have-your-local-clone-of-seleniumbase-connect-to-your-mysql-db-instance", "title": "Step 27. Have your local clone of SeleniumBase connect to your MySQL DB Instance", "text": ""}, {"location": "integrations/google_cloud/ReadMe/#step-28-have-your-seleniumbase-jenkins-jobs-use-your-mysql-db-instance", "title": "Step 28. Have your SeleniumBase Jenkins jobs use your MySQL DB Instance", "text": "
    pytest examples/test_suite.py --headless --with-db_reporting\n
    "}, {"location": "integrations/google_cloud/ReadMe/#step-29-run-your-new-jenkins-job", "title": "Step 29. Run your new Jenkins job", "text": ""}, {"location": "integrations/google_cloud/ReadMe/#step-30-congratulations-youve-successfully-completed-this-tutorial", "title": "Step 30. Congratulations! You've successfully completed this tutorial!", "text": ""}, {"location": "seleniumbase/common/ReadMe/", "title": "\ud83d\udd10 Decorators / Security", "text": ""}, {"location": "seleniumbase/common/ReadMe/#using-seleniumbasecommon-methods", "title": "Using seleniumbase/common methods.", "text": ""}, {"location": "seleniumbase/common/ReadMe/#part-1-decorators-from-decoratorspy", "title": "Part 1: Decorators - (from decorators.py)", "text": ""}, {"location": "seleniumbase/common/ReadMe/#use-these-python-decorators-with-your-test-methods-as-needed", "title": "Use these Python decorators with your test methods as needed", "text": "

    Example demonstrating a rate-limited printing functionality:

    import unittest\nfrom seleniumbase import decorators\n\nclass MyTestClass(unittest.TestCase):\n\n    @decorators.rate_limited(3.5)  # The arg is max calls per second\n    def print_item(self, item):\n        print(item)\n\n    def test_rate_limited_printing(self):\n        print(\"\\nRunning rate-limited print test:\")\n        for item in range(1, 11):\n            self.print_item(item)\n
    "}, {"location": "seleniumbase/common/ReadMe/#part-2-stringpassword-obfuscation-encryption-and-decryption", "title": "Part 2: String/Password Obfuscation, Encryption, and Decryption", "text": ""}, {"location": "seleniumbase/common/ReadMe/#intro", "title": "Intro", "text": "

    Often in your tests, you may need to login to a website to perform testing. This generally means storing passwords in plaintext formats. For security reasons, that may not be an optimal solution. For this reason, encryption/obfuscation tools have been built here to help you mask your passwords in your tests. It's not a bulletproof solution, but it can keep anyone looking over your shoulder during test creation from getting your login passwords if they don't have your encryption key, which is stored in a separate file.

    "}, {"location": "seleniumbase/common/ReadMe/#usage", "title": "Usage", "text": "
    python obfuscate.py\n\nEnter password to obfuscate: (CTRL+C to exit)\nPassword: *********\nVerify password:\nPassword: *********\n\nHere is the obfuscated password:\n$^*ENCRYPT=RXlYMSJWTz8HSwM=?&#$\n

    (You can also use unobfuscate.py to encrypt passwords without having them masked while typing them. Or you can use it to decrypt an obfuscated password.)

    from seleniumbase import encryption\n...\npassword = encryption.decrypt('$^*ENCRYPT=RXlYMSJWTz8HSwM=?&#$')\n

    (You'll notice that encrypted strings have a common start token and end token. This is to help tell them apart from non-encrypted strings. You can customize these tokens in settings.py. The current default setting is $^*ENCRYPT= for the start token and ?&#$ for the end token.)

    See decryption_test.py for an example of decrypting encrypted passwords in tests.

    "}, {"location": "seleniumbase/console_scripts/ReadMe/", "title": "\ud83c\udf20 Console Scripts", "text": ""}, {"location": "seleniumbase/console_scripts/ReadMe/#console-scripts", "title": "Console Scripts \ud83c\udf20", "text": "

    \ud83c\udf1f SeleniumBase console scripts can do many things, such as downloading web drivers, creating test directories with config files, activating the SeleniumBase Recorder, launching the SeleniumBase Commander, translating tests into other languages, running a Selenium Grid, and more.

    (For running tests, use pytest with SeleniumBase.)

    COMMANDS:\n      get / install    [DRIVER] [OPTIONS]\nmethods          (List common Python methods)\noptions          (List common pytest options)\nbehave-options   (List common behave options)\ngui / commander  [OPTIONAL PATH or TEST FILE]\nbehave-gui       (SBase Commander for Behave)\ncaseplans        [OPTIONAL PATH or TEST FILE]\nmkdir            [DIRECTORY] [OPTIONS]\nmkfile           [FILE.py] [OPTIONS]\nmkrec / codegen  [FILE.py] [OPTIONS]\nrecorder         (Open Recorder Desktop App.)\nrecord           (If args: mkrec. Else: App.)\nmkpres           [FILE.py] [LANG]\nmkchart          [FILE.py] [LANG]\nprint            [FILE] [OPTIONS]\ntranslate        [SB_FILE.py] [LANG] [ACTION]\nconvert          [WEBDRIVER_UNITTEST_FILE.py]\nextract-objects  [SB_FILE.py]\ninject-objects   [SB_FILE.py] [OPTIONS]\nobjectify        [SB_FILE.py] [OPTIONS]\nrevert-objects   [SB_FILE.py] [OPTIONS]\nencrypt / obfuscate\n      decrypt / unobfuscate\n      download server  (Get Selenium Grid JAR file)\ngrid-hub         [start|stop] [OPTIONS]\ngrid-node        [start|stop] --hub=[HOST/IP]\n* (EXAMPLE: \"sbase get chromedriver\") *\n\n    Type \"sbase help [COMMAND]\" for specific command info.\n    For info on all commands, type: \"seleniumbase --help\".\n    Use \"pytest\" for running tests.\n
    get / install
    sbase get [DRIVER] [OPTIONS]\nsbase install [DRIVER] [OPTIONS]\n
    sbase get chromedriver\nsbase get geckodriver\nsbase get edgedriver\nsbase get chromedriver 114\nsbase get chromedriver 114.0.5735.90\nsbase get chromedriver -p\n

    (Drivers: chromedriver, geckodriver, edgedriver, iedriver, operadriver, uc_driver)

    (Options: A specific driver version or major version integer. If not set, the driver version matches the browser. -p / --path: Also copy to \"/usr/local/bin\".)

    Downloads the webdriver to seleniumbase/drivers/ (chromedriver is required for Chrome automation) (geckodriver is required for Firefox automation) (edgedriver is required for MS__Edge automation)

    methods
    sbase methods\n

    Displays common SeleniumBase Python methods.

    options
    sbase options\n

    Displays common pytest command-line options that are available when using SeleniumBase.

    --browser=BROWSER  (The web browser to use. Default is \"chrome\")\n--edge / --firefox / --safari  (Shortcut for browser selection.)\n--headless  (Run tests headlessly. Default mode on Linux OS.)\n--demo  (Slow down and visually see test actions as they occur.)\n--slow  (Slow down the automation. Faster than using Demo Mode.)\n--rs / --reuse-session  (Reuse browser session between tests.)\n--crumbs  (Clear all cookies between tests reusing a session.)\n--maximize  (Start tests with the web browser window maximized.)\n--dashboard  (Enable SeleniumBase\\'s Dashboard at dashboard.html)\n--incognito  (Enable Chromium\\'s Incognito mode.)\n--guest  (Enable Chromium\\'s Guest Mode.)\n--dark  (Enable Chromium\\'s Dark Mode.)\n--uc  (Use undetected-chromedriver to evade detection.)\n-m=MARKER  (Run tests with the specified pytest marker.)\n-n=NUM  (Multithread the tests using that many threads.)\n-v  (Verbose mode. Print the full names of each test run.)\n--html=report.html  (Create a detailed pytest-html report.)\n--collect-only / --co  (Only show discovered tests. No run.)\n--co -q  (Only show full names of discovered tests. No run.)\n-x  (Stop running tests after the first failure is reached.)\n--pdb  (Enter the Post Mortem Debug Mode after any test fails.)\n--trace  (Enter Debug Mode immediately after starting any test.)\n| Debug Mode Commands  >>>   help / h: List all commands. |\n|   n: Next line of method. s: Step through. c: Continue. |\n|  return / r: Run until method returns. j: Jump to line. |\n| where / w: Show stack spot. u: Up stack. d: Down stack. |\n| longlist / ll: See code. dir(): List namespace objects. |\n--help / -h  (Display list of all available pytest options.)\n--final-debug  (Enter Final Debug Mode after each test ends.)\n--recorder / --rec  (Save browser actions as Python scripts.)\n--rec-behave / --rec-gherkin  (Save actions as Gherkin code.)\n--rec-print  (Display recorded scripts when they are created.)\n--save-screenshot  (Save a screenshot at the end of each test.)\n--archive-logs  (Archive old log files instead of deleting them.)\n--check-js  (Check for JavaScript errors after page loads.)\n--start-page=URL  (The browser start page when tests begin.)\n--agent=STRING  (Modify the web browser\\'s User-Agent string.)\n--mobile  (Use Chromium\\'s mobile device emulator during tests.)\n--metrics=STRING  (Set mobile \"CSSWidth,CSSHeight,PixelRatio\".)\n--ad-block  (Block some types of display ads after page loads.)\n--settings-file=FILE  (Override default SeleniumBase settings.)\n--env=ENV  (Set the test env. Access with \"self.env\" in tests.)\n--data=DATA  (Extra test data. Access with \"self.data\" in tests.)\n--disable-csp  (Disable the Content Security Policy of websites.)\n--remote-debug  (Sync to Ch-R-Debugger chrome://inspect/#devices)\n--server=SERVER  (The Selenium Grid server/IP used for tests.)\n--port=PORT  (The Selenium Grid port used by the test server.)\n--proxy=SERVER:PORT  (Connect to a proxy server:port for tests.)\n--proxy=USER:PASS@SERVER:PORT  (Use authenticated proxy server.)\n\nFor the full list of command-line options, type: \"pytest --help\".\n
    behave-options
    sbase behave-options\n

    Displays common Behave command-line options that are available when using SeleniumBase.

    -D browser=BROWSER  (The web browser to use. Default is \"chrome\")\n-D headless  (Run tests headlessly. Default mode on Linux OS.)\n-D demo  (Slow down and visually see test actions as they occur.)\n-D slow  (Slow down the automation. Faster than using Demo Mode.)\n-D reuse-session / -D rs  (Reuse browser session between tests.)\n-D crumbs  (Clear all cookies between tests reusing a session.)\n-D maximize  (Start tests with the web browser window maximized.)\n-D dashboard  (Enable SeleniumBase\\'s Dashboard at dashboard.html)\n-D incognito  (Enable Chromium\\'s Incognito Mode.)\n-D guest  (Enable Chromium\\'s Guest Mode.)\n-D dark  (Enable Chromium\\'s Dark Mode.)\n-D uc  (Use undetected-chromedriver to evade detection.)\n--no-snippets / -q  (Quiet mode. Don\\'t print snippets.)\n--dry-run / -d  (Dry run. Only show discovered tests.)\n--stop  (Stop running tests after the first failure is reached.)\n-D pdb  (Enter the Post Mortem Debug Mode after any test fails.)\n| Debug Mode Commands  >>>   help / h: List all commands. |\n|   n: Next line of method. s: Step through. c: Continue. |\n|  return / r: Run until method returns. j: Jump to line. |\n| where / w: Show stack spot. u: Up stack. d: Down stack. |\n| longlist / ll: See code. dir(): List namespace objects. |\n-D recorder  (Record browser actions to generate test scripts.)\n-D rec-print  (Display recorded scripts when they are created.)\n-D save-screenshot  (Save a screenshot at the end of each test.)\n-D archive-logs  (Archive old log files instead of deleting them.)\n-D check-js  (Check for JavaScript errors after page loads.)\n-D start-page=URL  (The browser start page when tests begin.)\n-D agent=STRING  (Modify the web browser\\'s User-Agent string.)\n-D mobile  (Use Chromium\\'s mobile device emulator during tests.)\n-D metrics=STRING  (Set mobile \"CSSWidth,CSSHeight,PixelRatio\".)\n-D ad-block  (Block some types of display ads after page loads.)\n-D settings-file=FILE  (Override default SeleniumBase settings.)\n-D env=ENV  (Set the test env. Access with \"self.env\" in tests.)\n-D data=DATA  (Extra test data. Access with \"self.data\" in tests.)\n-D disable-csp  (Disable the Content Security Policy of websites.)\n-D remote-debug  (Sync to Ch-R-Debugger chrome://inspect/#devices)\n-D server=SERVER  (The Selenium Grid server/IP used for tests.)\n-D port=PORT  (The Selenium Grid port used by the test server.)\n-D proxy=SERVER:PORT  (Connect to a proxy server:port for tests.)\n-D proxy=USER:PASS@SERVER:PORT  (Use authenticated proxy server.)\n\nFor the full list of command-line options, type: \"behave --help\".\n
    gui / commander
    sbase gui [OPTIONAL PATH or TEST FILE]\nsbase commander [OPTIONAL PATH or TEST FILE]\n
    behave-gui
    sbase behave-gui [OPTIONAL PATH or TEST FILE]\nsbase gui-behave [OPTIONAL PATH or TEST FILE]\n
    sbase behave-gui\nsbase behave-gui -i=calculator\nsbase behave-gui features/\nsbase behave-gui features/calculator.feature\n

    Launches SeleniumBase Commander / GUI for Behave.

    caseplans
    sbase caseplans [OPTIONAL PATH or TEST FILE]\n
    sbase caseplans\nsbase caseplans -k agent\nsbase caseplans -m marker2\nsbase caseplans test_suite.py\nsbase caseplans offline_examples/\n

    Launches the SeleniumBase Case Plans Generator.

    mkdir
    sbase mkdir [DIRECTORY] [OPTIONS]\n
    sbase mkdir ui_tests\n

    -b / --basic (Only config files. No tests added.)

    Creates a new folder for running SBase scripts. The new folder contains default config files, sample tests for helping new users get started, and Python boilerplates for setting up customized test frameworks.

    ui_tests/\n\u251c\u2500\u2500 __init__.py\n\u251c\u2500\u2500 my_first_test.py\n\u251c\u2500\u2500 parameterized_test.py\n\u251c\u2500\u2500 pytest.ini\n\u251c\u2500\u2500 requirements.txt\n\u251c\u2500\u2500 setup.cfg\n\u251c\u2500\u2500 test_demo_site.py\n\u2514\u2500\u2500 boilerplates/\n    \u251c\u2500\u2500 __init__.py\n    \u251c\u2500\u2500 base_test_case.py\n    \u251c\u2500\u2500 boilerplate_test.py\n    \u251c\u2500\u2500 classic_obj_test.py\n    \u251c\u2500\u2500 page_objects.py\n    \u251c\u2500\u2500 sb_fixture_test.py\n    \u2514\u2500\u2500 samples/\n        \u251c\u2500\u2500 __init__.py\n        \u251c\u2500\u2500 google_objects.py\n        \u251c\u2500\u2500 google_test.py\n        \u251c\u2500\u2500 sb_swag_test.py\n        \u2514\u2500\u2500 swag_labs_test.py\n

    If running with the -b or --basic option:

    ui_tests/\n\u251c\u2500\u2500 __init__.py\n\u251c\u2500\u2500 pytest.ini\n\u251c\u2500\u2500 requirements.txt\n\u2514\u2500\u2500 setup.cfg\n
    mkfile
    sbase mkfile [FILE.py] [OPTIONS]\n
    sbase mkfile new_test.py\n

    -b / --basic (Basic boilerplate / single-line test) -r / --rec (adds Pdb+ breakpoint for Recorder Mode)

    --en / --English | --zh / --Chinese --nl / --Dutch | --fr / --French --it / --Italian | --ja / --Japanese --ko / --Korean | --pt / --Portuguese --ru / --Russian | --es / --Spanish

    --bc / --basecase (BaseCase class inheritance) --pf / --pytest-fixture (sb pytest fixture) --cf / --class-fixture (class + sb pytest fixture) --cm / --context-manager (SB context manager) --dc / --driver-context (DriverContext manager) --dm / --driver-manager (Driver manager)

    Creates a new SBase test file with boilerplate code. If the file already exists, an error is raised. By default, uses English with BaseCase inheritance, and creates a boilerplate with common SeleniumBase methods: \"open\", \"type\", \"click\", \"assert_element\", and \"assert_text\". If using the basic boilerplate option, only the \"open\" method is included. Only the BaseCase format supports Languages or Recorder Mode.

    mkrec / record / codegen
    sbase mkrec [FILE.py] [OPTIONS]\nsbase codegen [FILE.py] [OPTIONS]\n
    sbase mkrec new_test.py\nsbase mkrec new_test.py --url=seleniumbase.io\nsbase codegen new_test.py\nsbase codegen new_test.py --url=wikipedia.org\n

    --url=URL (Sets the initial start page URL.) --edge (Use Edge browser instead of Chrome.) --gui / --headed (Use headed mode on Linux.) --uc / --undetected (Use undetectable mode.) --overwrite (Overwrite file when it exists.) --behave (Also output Behave/Gherkin files.)

    Creates a new SeleniumBase test using the Recorder. If the filename already exists, an error is raised.

    recorder
    sbase recorder [OPTIONS]\n

    --uc / --undetected (Use undetectable mode.) --behave (Also output Behave/Gherkin files.)

    Launches the SeleniumBase Recorder Desktop App.

    mkpres
    sbase mkpres [FILE.py] [LANG]\n
    sbase mkpres new_presentation.py --en\n

    --en / --English | --zh / --Chinese --nl / --Dutch | --fr / --French --it / --Italian | --ja / --Japanese --ko / --Korean | --pt / --Portuguese --ru / --Russian | --es / --Spanish

    Creates a new presentation with 3 example slides. If the file already exists, an error is raised. By default, the slides are written in English, and use \"serif\" theme with \"slide\" transition. The slides can be used as a basic boilerplate.

    mkchart
    sbase mkchart [FILE.py] [LANG]\n
    sbase mkchart new_chart.py --en\n

    --en / --English | --zh / --Chinese --nl / --Dutch | --fr / --French --it / --Italian | --ja / --Japanese --ko / --Korean | --pt / --Portuguese --ru / --Russian | --es / --Spanish

    Creates a new SeleniumBase chart presentation. If the file already exists, an error is raised. By default, the slides are written in English, and use a \"sky\" theme with \"slide\" transition. The chart can be used as a basic boilerplate.

    print
    sbase print [FILE] [OPTIONS]\n

    -n (Add line Numbers to the rows)

    Prints the code/text of any file with syntax-highlighting.

    translate
    sbase translate [SB_FILE.py] [LANGUAGE] [ACTION]\n

    --en / --English | --zh / --Chinese --nl / --Dutch | --fr / --French --it / --Italian | --ja / --Japanese --ko / --Korean | --pt / --Portuguese --ru / --Russian | --es / --Spanish

    -p / --print (Print translation output to the screen) -o / --overwrite (Overwrite the file being translated) -c / --copy (Copy the translation to a new .py file)

    -n (include line Numbers when using the Print action)

    Translates a SeleniumBase Python file into the language specified. Method calls and \"import\" lines get swapped. Both a language and an action must be specified. The -p action can be paired with one other action. When running with -c (or --copy), the new file name will be the original name appended with an underscore plus the 2-letter language code of the new language. (Example: Translating \"test_1.py\" into Japanese with -c will create a new file called \"test_1_ja.py\".)

    extract-objects
    sbase extract-objects [SB_FILE.py]\n

    Creates page objects based on selectors found in a seleniumbase Python file and saves those objects to the \"page_objects.py\" file in the same folder as the tests.

    inject-objects
    sbase inject-objects [SB_FILE.py] [OPTIONS]\n

    -c, --comments (Add object selectors to the comments.)

    Takes the page objects found in the \"page_objects.py\" file and uses those to replace matching selectors in the selected seleniumbase Python file.

    objectify
    sbase objectify [SB_FILE.py] [OPTIONS]\n

    -c, --comments (Add object selectors to the comments.)

    A modified version of the file where the selectors have been replaced with variable names defined in \"page_objects.py\", supporting the Page Object Pattern. (This has the same outcome as combining extract-objects with inject-objects)

    revert-objects
    sbase revert-objects [SB_FILE.py] [OPTIONS]\n

    -c, --comments (Keep existing comments for the lines.)

    Reverts the changes made by seleniumbase objectify ... or seleniumbase inject-objects ... when run against a seleniumbase Python file. Objects will get replaced by selectors stored in the \"page_objects.py\" file.

    convert
    sbase convert [WEBDRIVER_UNITTEST_FILE.py]\n

    Converts a Selenium IDE exported WebDriver unittest file into a SeleniumBase file. Adds _SB to the new file name while keeping the original file intact. Works with Katalon Recorder scripts. See This ReadMe for details.

    encrypt / obfuscate

    sbase encrypt OR sbase obfuscate

    Runs the password encryption/obfuscation tool. (Where you can enter a password to encrypt/obfuscate.)

    decrypt / unobfuscate

    sbase decrypt OR sbase unobfuscate

    Runs the password decryption/unobfuscation tool. (Where you can enter an encrypted password to decrypt.)

    download
    sbase download server\n

    Downloads the Selenium Server JAR file for Grid usage. (That JAR file is required when using a Selenium Grid)

    grid-hub
    sbase grid-hub {start|stop|restart} [OPTIONS]\n

    -v, --verbose (Increases verbosity of logging output.) --timeout=TIMEOUT (Close idle browser windows after TIMEOUT seconds.)

    Controls the Selenium Grid Hub server, which allows for running tests on multiple machines in parallel to speed up test runs and reduce the total time of test suite execution. You can start, restart, or stop the Grid Hub server.

    grid-node
    sbase grid-node {start|stop|restart} [OPTIONS]\n

    --hub=HUB_IP (The Grid Hub IP Address to connect to.) (Default: 127.0.0.1) -v, --verbose (Increases verbosity of logging output.)

    Controls the Selenium Grid node, which serves as a worker machine for your Selenium Grid Hub server. You can start, restart, or stop the Grid node.

    "}, {"location": "seleniumbase/utilities/selenium_grid/ReadMe/", "title": "\ud83c\udf10 Selenium Grid", "text": "The Selenium Grid Hub:

    The Selenium Grid Hub lets you distribute tests to run in parallel across multiple node machines. Each node machine can then run its own allocation of tests. This allows you to run a large suite of tests very quickly.

    Running the Selenium Grid Hub:

    The following commands will work once you've installed seleniumbase.

    Downloading the Selenium Server JAR file:
    seleniumbase download server\n
    Grid Hub server controls:
    seleniumbase grid-hub {start|stop|restart} [OPTIONS]\n

    Options:

    Grid node server controls:
    seleniumbase grid-node {start|stop|restart} --hub=[HUB_IP] [OPTIONS]\n

    Options:

    When the Grid Hub Console is up and running, you'll be able to find it here: http://127.0.0.1:4444/grid/console

    Now you can run your tests on the Selenium Grid:

    pytest test_demo_site.py --server=IP_ADDRESS --port=4444\n

    You can also run your tests on someone else's Selenium Grid to avoid managing your own. Here are some Selenium Grids that you can use (and the run command format):

    pytest test_demo_site.py --server=USERNAME:KEY@hub.browserstack.com --port=80\n
    pytest test_demo_site.py --server=USERNAME:KEY@ondemand.us-east-1.saucelabs.com --port=443 --protocol=https\n
    pytest test_demo_site.py --server=USERNAME:KEY@demo.perfectomobile.com/nexperience/perfectomobile --port=443\n
    pytest test_demo_site.py --server=USERNAME:KEY@hub.testingbot.com --port=80\n
    pytest test_demo_site.py --server=USERNAME:KEY@hub.lambdatest.com --port=80\n
    pytest test_demo_site.py --server=USERNAME:KEY@hub.crossbrowsertesting.com --port=80\n

    To use a server on the https protocol, add --protocol=https: (SeleniumBase 1.65.2 and newer uses https automatically for --port=443.)

    pytest test_demo_site.py --protocol=https --server=IP_ADDRESS --port=PORT\n

    (For setting browser desired capabilities while running Selenium remotely, see the desired capabilities documentation and the sample files located in SeleniumBase/examples/capabilities)

    More info about the Selenium Grid Hub can be found here: "}]} \ No newline at end of file