diff --git a/README.md b/README.md
index 5fd4d1b9888..73ec1f0f75d 100755
--- a/README.md
+++ b/README.md
@@ -8,7 +8,7 @@

-
+
diff --git a/examples/raw_browser_launcher.py b/examples/raw_browser_launcher.py
index 5ee7da58074..a5aa0af4ee1 100644
--- a/examples/raw_browser_launcher.py
+++ b/examples/raw_browser_launcher.py
@@ -9,14 +9,12 @@
success = False
try:
driver = get_driver("chrome", headless=False)
- driver.get('data:text/html,Data URL')
- source = driver.page_source
- assert "Data URL" in source
- # An example of "is_element_visible()" from "page_actions"
- assert page_actions.is_element_visible(driver, "h1.top")
- # Extra fun with Javascript
- js_utils.highlight_with_js(driver, "h1.top", 8, "")
- success = True # No errors
+ driver.get("https://seleniumbase.io/apps/calculator")
+ page_actions.wait_for_element_visible(driver, "4", "id").click()
+ page_actions.wait_for_element_visible(driver, "2", "id").click()
+ page_actions.wait_for_text_visible(driver, "42", "output", "id")
+ js_utils.highlight_with_js(driver, "#output", 6, "")
+ success = True
finally:
driver.quit()
assert success
diff --git a/help_docs/syntax_formats.md b/help_docs/syntax_formats.md
index 019cdb675de..b7c269a0d0b 100755
--- a/help_docs/syntax_formats.md
+++ b/help_docs/syntax_formats.md
@@ -235,12 +235,12 @@ from seleniumbase import page_actions
success = False
try:
driver = get_driver("chrome", headless=False)
- driver.get('data:text/html,Data URL')
- source = driver.page_source
- assert "Data URL" in source
- assert page_actions.is_element_visible(driver, "h1.top")
- js_utils.highlight_with_js(driver, "h1.top", 8, "")
- success = True # No errors
+ driver.get("https://seleniumbase.io/apps/calculator")
+ page_actions.wait_for_element_visible(driver, "4", "id").click()
+ page_actions.wait_for_element_visible(driver, "2", "id").click()
+ page_actions.wait_for_text_visible(driver, "42", "output", "id")
+ js_utils.highlight_with_js(driver, "#output", 6, "")
+ success = True
finally:
driver.quit()
assert success
diff --git a/mkdocs_build/requirements.txt b/mkdocs_build/requirements.txt
index cea1d864af4..b80d43faeac 100644
--- a/mkdocs_build/requirements.txt
+++ b/mkdocs_build/requirements.txt
@@ -23,7 +23,7 @@ bleach==5.0.0
jsmin==3.0.1
lunr==0.6.2
nltk==3.7
-watchdog==2.1.7
+watchdog==2.1.8
mkdocs==1.3.0
mkdocs-material==8.2.15
mkdocs-exclude-search==0.6.4
diff --git a/seleniumbase/__version__.py b/seleniumbase/__version__.py
index 396c73c61fc..edc2bb6963c 100755
--- a/seleniumbase/__version__.py
+++ b/seleniumbase/__version__.py
@@ -1,2 +1,2 @@
# seleniumbase package
-__version__ = "3.0.1"
+__version__ = "3.0.2"
diff --git a/seleniumbase/drivers/ReadMe.md b/seleniumbase/drivers/ReadMe.md
index d191a7526a7..82c81969781 100755
--- a/seleniumbase/drivers/ReadMe.md
+++ b/seleniumbase/drivers/ReadMe.md
@@ -1,19 +1,30 @@
-###
SeleniumBase webdriver storage
+###
SeleniumBase webdriver storage
* You need a different webdriver for each web browser you want to run automation on: ``chromedriver`` for Chrome, ``edgedriver`` for Edge, ``geckodriver`` for Firefox, ``operadriver`` for Opera, and ``iedriver`` for Internet Explorer.
+```bash
+seleniumbase get chromedriver
+seleniumbase get geckodriver
+seleniumbase get edgedriver
+seleniumbase get iedriver
+seleniumbase get operadriver
```
-seleniumbase install chromedriver
-seleniumbase install geckodriver
-seleniumbase install edgedriver
-seleniumbase install iedriver
-seleniumbase install operadriver
-```
-After running the commands above, web drivers will get downloaded into this folder. SeleniumBase will then use those drivers during test runs if present. (The drivers don't come with SeleniumBase by default.)
+
+After running the commands above, web drivers will get downloaded into this folder. SeleniumBase will then use those drivers during tests if present. (The drivers don't come with SeleniumBase by default.)
* If you have the latest version of Chrome installed, get the latest chromedriver (otherwise it defaults to chromedriver 2.44 for compatibility reasons):
+
```bash
-seleniumbase install chromedriver latest
+sbase get chromedriver latest
```
If the necessary driver is not found in this location while running tests, SeleniumBase will instead look for the driver on the System PATH. If the necessary driver is not on the System PATH either, SeleniumBase will automatically attempt to download the required driver.
+
+* You can also download specific versions of drivers. Examples:
+
+```bash
+sbase get chromedriver 101
+sbase get chromedriver 101.0.4951.41
+sbase get chromedriver latest-1
+sbase get edgedriver 101.0.1210.32
+```
diff --git a/seleniumbase/fixtures/page_actions.py b/seleniumbase/fixtures/page_actions.py
index cbd0ada5273..76cbbe53ad1 100755
--- a/seleniumbase/fixtures/page_actions.py
+++ b/seleniumbase/fixtures/page_actions.py
@@ -9,14 +9,14 @@
The default option for searching for elements is by CSS Selector.
This can be changed by overriding the "By" parameter.
Options are:
-By.CSS_SELECTOR
-By.CLASS_NAME
-By.ID
-By.NAME
-By.LINK_TEXT
-By.XPATH
-By.TAG_NAME
-By.PARTIAL_LINK_TEXT
+By.CSS_SELECTOR # "css selector"
+By.CLASS_NAME # "class name"
+By.ID # "id"
+By.NAME # "name"
+By.LINK_TEXT # "link text"
+By.XPATH # "xpath"
+By.TAG_NAME # "tag name"
+By.PARTIAL_LINK_TEXT # "partial link text"
"""
import codecs
diff --git a/seleniumbase/fixtures/shared_utils.py b/seleniumbase/fixtures/shared_utils.py
index c3c47fd449b..aa5b771cd88 100755
--- a/seleniumbase/fixtures/shared_utils.py
+++ b/seleniumbase/fixtures/shared_utils.py
@@ -76,7 +76,11 @@ def __time_limit_exceeded(message):
def check_if_time_limit_exceeded():
- if sb_config.time_limit and not sb_config.recorder_mode:
+ if (
+ hasattr(sb_config, "time_limit")
+ and sb_config.time_limit
+ and not sb_config.recorder_mode
+ ):
time_limit = sb_config.time_limit
now_ms = int(time.time() * 1000)
if now_ms > sb_config.start_time_ms + sb_config.time_limit_ms: