diff --git a/README.md b/README.md
index 964ae2d5ef7..348ca80b6d4 100755
--- a/README.md
+++ b/README.md
@@ -1,11 +1,11 @@
-
-
-
+
+
+
-
+
Everything you need to test websites.
@@ -68,7 +68,7 @@ python setup.py install
```
If multiple versions of Python are installed, be specific (E.g. use ``python3`` instead of ``python``).
-* You can also install ``seleniumbase`` from [pypi](https://pypi.python.org/pypi/seleniumbase):
+* You can also install ``seleniumbase`` from [pypi](https://pypi.python.org/pypi/seleniumbase).
```bash
pip install seleniumbase
```
@@ -112,17 +112,17 @@ from seleniumbase import BaseCase
class MyTestClass(BaseCase):
def test_basic(self):
+ self.open("https://store.xkcd.com/search")
+ self.type('input[name="q"]', "xkcd book\n")
+ self.assert_text("xkcd: volume 0", "h3")
self.open("https://xkcd.com/353/")
self.assert_title("xkcd: Python")
self.assert_element('img[alt="Python"]')
self.click('a[rel="license"]')
self.assert_text("free to copy and reuse")
self.go_back()
- self.click("link=About")
- self.assert_text("xkcd.com", "h2")
- self.open("://store.xkcd.com/collections/everything")
- self.update_text("input.search-input", "xkcd book\n")
- self.assert_exact_text("xkcd: volume 0", "h3")
+ self.click_link_text("About")
+ self.assert_exact_text("xkcd.com", "h2")
```
* By default, **[CSS Selectors](https://www.w3schools.com/cssref/css_selectors.asp)** are used for finding page elements.
@@ -132,7 +132,7 @@ class MyTestClass(BaseCase):
```python
self.open(URL) # Navigate to the web page
self.click(SELECTOR) # Click a page element
-self.update_text(SELECTOR, TEXT) # Type text (Add "\n" to text for pressing enter/return.)
+self.type(SELECTOR, TEXT) # Type text (Add "\n" to text for pressing enter/return.)
self.assert_element(SELECTOR) # Assert element is visible
self.assert_text(TEXT) # Assert text is visible (has optional SELECTOR arg)
self.assert_title(PAGE_TITLE) # Assert page title
@@ -163,7 +163,7 @@ SeleniumBase automatically handles common WebDriver actions such as spinning up
SeleniumBase uses simple syntax for commands, such as:
```python
-self.update_text("input", "dogs\n")
+self.type("input", "dogs\n")
```
The same command with regular WebDriver is very messy:
@@ -523,10 +523,10 @@ self.click("div#my_id")
Typing Text
-self.update_text(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(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:
```python
-self.update_text("input#id_value", "2012")
+self.type("input#id_value", "2012")
```
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.
If you want to type in special keys, that's easy too. Here's an example:
diff --git a/docs/img/sb_logo_10.png b/docs/img/sb_logo_10.png
new file mode 100644
index 00000000000..8e8d92f7237
Binary files /dev/null and b/docs/img/sb_logo_10.png differ
diff --git a/examples/basic_test.py b/examples/basic_test.py
index a27642c1c98..bf0cc30005f 100755
--- a/examples/basic_test.py
+++ b/examples/basic_test.py
@@ -8,9 +8,9 @@
class MyTestClass(BaseCase):
def test_basic(self):
+ self.open("https://store.xkcd.com/search")
+ self.type('input[name="q"]', "xkcd book\n")
self.open("https://xkcd.com/353/")
self.click('a[rel="license"]')
self.go_back()
- self.click("link=About")
- self.open("://store.xkcd.com/collections/everything")
- self.update_text("input.search-input", "xkcd book\n")
+ self.click_link_text("About")
diff --git a/examples/boilerplates/samples/google_test.py b/examples/boilerplates/samples/google_test.py
index 29b3e0acd11..97928efe80c 100755
--- a/examples/boilerplates/samples/google_test.py
+++ b/examples/boilerplates/samples/google_test.py
@@ -10,7 +10,7 @@ class GoogleTests(BaseCase):
def test_google_dot_com(self):
self.open('https://google.com/ncr')
- self.update_text(HomePage.search_box, 'github')
+ self.type(HomePage.search_box, 'github')
self.assert_element(HomePage.list_box)
self.assert_element(HomePage.search_button)
self.assert_element(HomePage.feeling_lucky_button)
diff --git a/examples/github_test.py b/examples/github_test.py
index 2ef2bfd41fb..9dab1f539f7 100755
--- a/examples/github_test.py
+++ b/examples/github_test.py
@@ -18,7 +18,7 @@ def test_github(self):
"""AppleWebKit/537.36 (KHTML, like Gecko) """
"""Chrome/75.0.3770.100 Safari/537.36""")
self.open("https://github.com/")
- self.update_text("input.header-search-input", "SeleniumBase\n")
+ self.type("input.header-search-input", "SeleniumBase\n")
self.slow_click('a[href="/seleniumbase/SeleniumBase"]')
self.assert_element("div.repository-content")
self.assert_text("SeleniumBase", "h1")
diff --git a/examples/master_qa/masterqa_test_1.py b/examples/master_qa/masterqa_test_1.py
index 6a6950fdc59..6f758cdbd90 100755
--- a/examples/master_qa/masterqa_test_1.py
+++ b/examples/master_qa/masterqa_test_1.py
@@ -16,8 +16,8 @@ def test_xkcd(self):
self.verify("Can you find the moon?")
self.click('a[rel="next"]')
self.verify("Do the drones look safe?")
- self.open("https://store.xkcd.com/collections/everything")
- self.update_text("input.search-input", "book\n")
+ self.open("https://store.xkcd.com/search")
+ self.type("input.search-input", "book\n")
self.verify("Do you see books in the search results?")
self.open("https://xkcd.com/213/")
for i in range(5):
diff --git a/examples/my_first_test.py b/examples/my_first_test.py
index 97b188f01f6..ebdf8a11bf3 100755
--- a/examples/my_first_test.py
+++ b/examples/my_first_test.py
@@ -4,17 +4,17 @@
class MyTestClass(BaseCase):
def test_basic(self):
+ self.open("https://store.xkcd.com/search")
+ self.type('input[name="q"]', "xkcd book\n")
+ self.assert_text("xkcd: volume 0", "h3")
self.open("https://xkcd.com/353/")
self.assert_title("xkcd: Python")
self.assert_element('img[alt="Python"]')
self.click('a[rel="license"]')
self.assert_text("free to copy and reuse")
self.go_back()
- self.click("link=About")
- self.assert_text("xkcd.com", "h2")
- self.open("://store.xkcd.com/collections/everything")
- self.update_text("input.search-input", "xkcd book\n")
- self.assert_exact_text("xkcd: volume 0", "h3")
+ self.click_link_text("About")
+ self.assert_exact_text("xkcd.com", "h2")
####
@@ -23,14 +23,17 @@ def test_basic(self):
# **** NOTES / USEFUL INFO ****
#
# 1. By default, CSS Selectors are used to identify elements.
- # Other options include: "LINK_TEXT", "PARTIAL_LINK_TEXT", "NAME",
+ # CSS Guide: "https://www.w3schools.com/cssref/css_selectors.asp".
+ # Other selectors include: "LINK_TEXT", "PARTIAL_LINK_TEXT", "NAME",
# "CLASS_NAME", and "ID", but most of those can be expressed as CSS.
+ #
# Here's an example of changing the "by":
# [
# from selenium.webdriver.common.by import By
# ...
# self.click('Next', by=By.PARTIAL_LINK_TEXT)
# ]
+ #
# XPath is used by default if the arg starts with "/", "./", or "(":
# [
# self.click('/html/body/div[3]/div[4]/p[2]/a')
@@ -39,27 +42,46 @@ def test_basic(self):
# If you're completely new to CSS selectors, right-click on a
# web page and select "Inspect" to see the CSS in the html.
#
- # 2. Most methods have the optional `timeout` argument. Ex:
+ # 2. Most methods have the optional "timeout" argument.
+ # Here's an example of changing the "timeout":
# [
# self.assert_element('img[alt="Python"]', timeout=15)
# ]
- # The `timeout` argument tells the method how many seconds to wait
- # for an element to appear before raising an exception. This is
+ # The "timeout" argument tells the method how many seconds to wait
+ # for an element to appear before failing the test. This is
# useful if a web page needs additional time to load an element.
- # If you don't specify a `timeout`, a default timeout is used.
+ # If you don't specify a "timeout", a default timeout is used.
# Default timeouts are configured in seleniumbase/config/settings.py
#
- # 3. SeleniumBase methods are very versatile. For example,
- # self.update_text(SELECTOR, TEXT) does the following:
- # * Waits for the element to be visible
- # * Waits for the element to be interactive
- # * Clears the text field
- # * Types in the new text
- # * Hits Enter/Submit (if the text ends in "\n")
+ # 3. SeleniumBase methods often perform multiple actions. For example,
+ # self.type(SELECTOR, TEXT) will do the following:
+ # * Wait for the element to be visible
+ # * Wait for the element to be interactive
+ # * Clear the text field
+ # * Type in the new text
+ # * Press Enter/Submit if the text ends in "\n"
#
- # self.update_text(S, T) can also be written as self.input(S, T)
+ # 4. Duplicate method names may exist for the same method:
+ # (This makes it easier to switch over from other test frameworks.)
+ # Example:
+ # self.open() = self.visit() = self.open_url() = self.goto()
+ # self.type() = self.update_text() = self.input()
+ # self.send_keys() = self.add_text()
+ # self.get_element() = self.wait_for_element_present()
+ # self.find_element() = self.wait_for_element_visible()
+ # = self.wait_for_element()
+ # self.assert_element() = self.assert_element_visible()
+ # self.assert_text() = self.assert_text_visible()
+ # self.find_text() = self.wait_for_text_visible()
+ # = self.wait_for_text()
+ # self.click_link_text(text) = self.click(link=text)
+ # = self.click_link(text)
+ # * self.get(url) is SPECIAL: *
+ # If {url} is a valid URL, self.get() works just like self.open()
+ # Otherwise {url} becomes a selector for calling self.get_element()
#
- # 4. There's usually more than one way to do the same thing. Ex:
+ # 5. There's usually more than one way to do the same thing.
+ # Example 1:
# [
# self.assert_text("xkcd: volume 0", "h3")
# ]
@@ -68,33 +90,37 @@ def test_basic(self):
# text = self.get_text("h3")
# self.assert_true("xkcd: volume 0" in text)
# ]
- # Or:
+ # Is also the same as:
# [
- # text = self.find_element("h3").text
+ # element = self.find_element("h3")
+ # text = element.text
# self.assert_true("xkcd: volume 0" in text)
# ]
#
- # And the following line:
+ # Example 2:
+ # [
+ # self.assert_exact_text("xkcd.com", "h2")
+ # ]
+ # Is the same as:
+ # [
+ # text = self.get_text("h2").strip()
+ # self.assert_true("xkcd.com".strip() == text)
+ # ]
+ #
+ # Example 3:
# [
# title = self.get_attribute("#comic img", "title")
# ]
- # Can also be written as:
+ # Is the same as:
# [
# element = self.find_element("#comic img")
# title = element.get_attribute("title")
# ]
#
- # 5. self.assert_exact_text(TEXT) ignores leading and trailing
+ # 6. self.assert_exact_text(TEXT) ignores leading and trailing
# whitespace in the TEXT assertion.
# So, self.assert_exact_text("Some Text") will find [" Some Text "].
#
- # 6. For backwards-compatibilty, some SeleniumBase methods that do the
- # same thing have multiple names, kept on from previous versions.
- # Ex: self.wait_for_element() is the same as self.find_element().
- # Both search for and return the element, and raise an exception if
- # the element does not appear on the page within the timeout limit.
- # And self.assert_element() does this too (without returning it).
- #
# 7. If a URL starts with "://", then "https://" is automatically used.
# Example: [self.open("://URL")] becomes [self.open("https://URL")]
# This helps by reducing the line length by 5 characters.
diff --git a/examples/offline_examples/test_demo_page.py b/examples/offline_examples/test_demo_page.py
index 3766aca0001..8cd4d99a3eb 100755
--- a/examples/offline_examples/test_demo_page.py
+++ b/examples/offline_examples/test_demo_page.py
@@ -21,10 +21,10 @@ def test_demo_page(self):
# Assert that the text appears within a given element
self.assert_text("Demo Page", "h1")
- # Update the text of various text fields on the page
- self.update_text("#myTextInput", "This is Automated")
- self.update_text("textarea.area1", "Testing Time!\n")
- self.update_text('[name="preText2"]', "Typing Text!")
+ # Type/update text in text fields on the page
+ self.type("#myTextInput", "This is Automated")
+ self.type("textarea.area1", "Testing Time!\n")
+ self.type('[name="preText2"]', "Typing Text!")
# Verify that a hover dropdown link changes page text
self.assert_text("Automation Practice", "h3")
@@ -92,9 +92,8 @@ def test_demo_page(self):
# Assert link text - Use click_link_text() to click
self.assert_link_text("seleniumbase.com")
self.assert_link_text("SeleniumBase on GitHub")
-
- # Assert the title of the current web page
- self.assert_link_text("seleniumbase.com")
- self.assert_link_text("SeleniumBase on GitHub")
self.assert_link_text("seleniumbase.io")
self.assert_link_text("SeleniumBase Demo Page")
+
+ # Assert exact text
+ self.assert_exact_text("Demo Page", "h1")
diff --git a/examples/parameterized_test.py b/examples/parameterized_test.py
index d88c6e632e0..159d7cf372f 100644
--- a/examples/parameterized_test.py
+++ b/examples/parameterized_test.py
@@ -11,6 +11,6 @@ class GoogleTestClass(BaseCase):
])
def test_parameterized_google_search(self, search_term, expected_text):
self.open('https://google.com/ncr')
- self.update_text('input[title="Search"]', search_term + '\n')
+ self.type('input[title="Search"]', search_term + '\n')
self.assert_element('#result-stats')
self.assert_text(expected_text, '#search')
diff --git a/examples/swag_labs_suite.py b/examples/swag_labs_suite.py
index 1d33264c21f..284a64454cb 100755
--- a/examples/swag_labs_suite.py
+++ b/examples/swag_labs_suite.py
@@ -10,8 +10,8 @@ def login(self, username="standard_user"):
self.open("https://www.saucedemo.com/")
if username not in self.get_text("#login_credentials"):
self.fail("Invalid user for login: %s" % username)
- self.update_text("#user-name", username)
- self.update_text("#password", "secret_sauce")
+ self.type("#user-name", username)
+ self.type("#password", "secret_sauce")
self.click('input[type="submit"]')
self.assert_element("#inventory_container")
self.assert_text("Products", "div.product_label")
@@ -58,9 +58,9 @@ def test_swag_labs_basic_functional_flow(self, username):
self.click("link=CHECKOUT")
self.assert_exact_text("Checkout: Your Information", "div.subheader")
self.assert_element("a.cart_cancel_link")
- self.update_text("#first-name", "SeleniumBase")
- self.update_text("#last-name", "Rocks")
- self.update_text("#postal-code", "01720")
+ self.type("#first-name", "SeleniumBase")
+ self.type("#last-name", "Rocks")
+ self.type("#postal-code", "01720")
# Checkout - Overview
self.click("input.btn_primary")
diff --git a/examples/test_apple_site.py b/examples/test_apple_site.py
index 3488d4b4cdd..f3bf97caab0 100755
--- a/examples/test_apple_site.py
+++ b/examples/test_apple_site.py
@@ -10,7 +10,7 @@ def test_apple_developer_site_webdriver_instructions(self):
self.message_duration = 2.0
self.open("https://developer.apple.com/search/")
title = "Testing with WebDriver in Safari"
- self.update_text('[placeholder*="developer.apple.com"]', title + "\n")
+ self.type('[placeholder*="developer.apple.com"]', title + "\n")
self.click("link=%s" % title)
self.assert_element('[href="/documentation"]')
self.assert_text(title, "h1")
diff --git a/examples/test_demo_site.py b/examples/test_demo_site.py
index 30e9c70081a..daf2502ba3b 100755
--- a/examples/test_demo_site.py
+++ b/examples/test_demo_site.py
@@ -15,10 +15,10 @@ def test_demo_site(self):
# Assert that the text appears within a given element
self.assert_text("Demo Page", "h1")
- # Update the text of various text fields on the page
- self.update_text("#myTextInput", "This is Automated")
- self.update_text("textarea.area1", "Testing Time!\n")
- self.update_text('[name="preText2"]', "Typing Text!")
+ # Type/update text in text fields on the page
+ self.type("#myTextInput", "This is Automated")
+ self.type("textarea.area1", "Testing Time!\n")
+ self.type('[name="preText2"]', "Typing Text!")
# Verify that a hover dropdown link changes page text
self.assert_text("Automation Practice", "h3")
@@ -93,3 +93,9 @@ def test_demo_site(self):
# Assert exact text
self.assert_exact_text("Demo Page", "h1")
+
+ # Assert no broken links
+ self.assert_no_404_errors()
+
+ # Assert no JavaScript errors
+ self.assert_no_js_errors()
diff --git a/examples/test_event_firing.py b/examples/test_event_firing.py
index 15b16ae6ac3..0a5cacb0b8f 100755
--- a/examples/test_event_firing.py
+++ b/examples/test_event_firing.py
@@ -33,6 +33,6 @@ def test_event_firing_webdriver(self):
print("\n* EventFiringWebDriver example *")
self.open("https://xkcd.com/1862/")
self.click("link=About")
- self.open("https://store.xkcd.com/collections/everything")
- self.update_text("input.search-input", "xkcd book\n")
+ self.open("https://store.xkcd.com/search")
+ self.type('input[name="q"]', "xkcd book\n")
self.open("https://xkcd.com/1822/")
diff --git a/examples/test_hack_search.py b/examples/test_hack_search.py
index ff40f1cc340..cb17c2c5c73 100755
--- a/examples/test_hack_search.py
+++ b/examples/test_hack_search.py
@@ -13,7 +13,7 @@ def test_hack_search(self):
self.assert_element('input[title="Search"]')
self.set_attribute('[action="/search"]', "action", "//bing.com/search")
self.set_attributes('[value="Google Search"]', "value", "Bing Search")
- self.update_text('input[title="Search"]', "SeleniumBase GitHub")
+ self.type('input[title="Search"]', "SeleniumBase GitHub")
self.click('[value="Bing Search"]')
self.assert_element("h1.b_logo")
self.click('[href*="github.com/seleniumbase/SeleniumBase"]')
diff --git a/examples/test_pytest_parametrize.py b/examples/test_pytest_parametrize.py
index 151a2242ba5..bf57016aa55 100644
--- a/examples/test_pytest_parametrize.py
+++ b/examples/test_pytest_parametrize.py
@@ -4,7 +4,7 @@
@pytest.mark.parametrize('value', ["pytest", "selenium"])
def test_sb_fixture_with_no_class(sb, value):
sb.open("https://google.com/ncr")
- sb.update_text('input[title="Search"]', value + '\n')
+ sb.type('input[title="Search"]', value + '\n')
sb.assert_text(value, "div#center_col")
@@ -12,5 +12,5 @@ class Test_SB_Fixture():
@pytest.mark.parametrize('value', ["pytest", "selenium"])
def test_sb_fixture_inside_class(self, sb, value):
sb.open("https://google.com/ncr")
- sb.update_text('input[title="Search"]', value + '\n')
+ sb.type('input[title="Search"]', value + '\n')
sb.assert_text(value, "div#center_col")
diff --git a/examples/test_sb_fixture.py b/examples/test_sb_fixture.py
index 4bda3de06c7..0d1dd508d6d 100644
--- a/examples/test_sb_fixture.py
+++ b/examples/test_sb_fixture.py
@@ -3,7 +3,7 @@
# "sb" pytest fixture test in a method with no class
def test_sb_fixture_with_no_class(sb):
sb.open("https://google.com/ncr")
- sb.update_text('input[title="Search"]', 'SeleniumBase\n')
+ sb.type('input[title="Search"]', 'SeleniumBase\n')
sb.click('a[href*="github.com/seleniumbase/SeleniumBase"]')
sb.click('a[title="seleniumbase"]')
@@ -12,6 +12,6 @@ def test_sb_fixture_with_no_class(sb):
class Test_SB_Fixture():
def test_sb_fixture_inside_class(self, sb):
sb.open("https://google.com/ncr")
- sb.update_text('input[title="Search"]', 'SeleniumBase\n')
+ sb.type('input[title="Search"]', 'SeleniumBase\n')
sb.click('a[href*="github.com/seleniumbase/SeleniumBase"]')
sb.click('a[title="examples"]')
diff --git a/examples/test_swag_labs.py b/examples/test_swag_labs.py
index 51f8915ca8d..97a2fcdc4b1 100755
--- a/examples/test_swag_labs.py
+++ b/examples/test_swag_labs.py
@@ -8,8 +8,8 @@ def login(self, username="standard_user"):
self.open("https://www.saucedemo.com/")
if username not in self.get_text("#login_credentials"):
self.fail("Invalid user for login: %s" % username)
- self.update_text("#user-name", username)
- self.update_text("#password", "secret_sauce")
+ self.type("#user-name", username)
+ self.type("#password", "secret_sauce")
self.click('input[type="submit"]')
self.assert_element("#inventory_container")
self.assert_text("Products", "div.product_label")
@@ -50,9 +50,9 @@ def test_swag_labs_basic_flow(self):
self.click("link=CHECKOUT")
self.assert_exact_text("Checkout: Your Information", "div.subheader")
self.assert_element("a.cart_cancel_link")
- self.update_text("#first-name", "SeleniumBase")
- self.update_text("#last-name", "Rocks")
- self.update_text("#postal-code", "01720")
+ self.type("#first-name", "SeleniumBase")
+ self.type("#last-name", "Rocks")
+ self.type("#postal-code", "01720")
# Checkout - Overview
self.click("input.btn_primary")
diff --git a/examples/translations/chinese_test_1.py b/examples/translations/chinese_test_1.py
index 99d2f034ce8..2e6e17988a3 100755
--- a/examples/translations/chinese_test_1.py
+++ b/examples/translations/chinese_test_1.py
@@ -17,6 +17,6 @@ def test_例子1(self):
self.回去()
self.单击链接文本("兰德尔·门罗")
self.断言文本("兰德尔·门罗", "#firstHeading")
- self.更新文本("#searchInput", "程式设计")
+ self.输入文本("#searchInput", "程式设计")
self.单击("#searchButton")
self.断言文本("程序设计", "#firstHeading")
diff --git a/examples/translations/dutch_test_1.py b/examples/translations/dutch_test_1.py
index 9929efde8d8..d300c0b2ec8 100755
--- a/examples/translations/dutch_test_1.py
+++ b/examples/translations/dutch_test_1.py
@@ -8,11 +8,11 @@ def test_voorbeeld_1(self):
self.openen("https://nl.wikipedia.org/wiki/Hoofdpagina")
self.controleren_element('a[title*="hoofdpagina gaan"]')
self.controleren_tekst("Welkom op Wikipedia", "td.hp-welkom")
- self.tekst_bijwerken("#searchInput", "Stroopwafel")
+ self.typ("#searchInput", "Stroopwafel")
self.klik("#searchButton")
self.controleren_tekst("Stroopwafel", "#firstHeading")
self.controleren_element('img[alt="Stroopwafels"]')
- self.tekst_bijwerken("#searchInput", "Rijksmuseum Amsterdam")
+ self.typ("#searchInput", "Rijksmuseum Amsterdam")
self.klik("#searchButton")
self.controleren_tekst("Rijksmuseum", "#firstHeading")
self.controleren_element('img[alt="Het Rijksmuseum"]')
diff --git a/examples/translations/english_test_1.py b/examples/translations/english_test_1.py
index 8ccd83b7a9f..e532acd0756 100755
--- a/examples/translations/english_test_1.py
+++ b/examples/translations/english_test_1.py
@@ -4,10 +4,10 @@
class MyTestClass(BaseCase):
def test_example_1(self):
- url = "https://store.xkcd.com/collections/everything"
+ url = "https://store.xkcd.com/collections/posters"
self.open(url)
- self.update_text("input.search-input", "xkcd book\n")
- self.assert_exact_text("xkcd: volume 0", "h3")
+ self.type("input.search-input", "xkcd book\n")
+ self.assert_text("xkcd: volume 0", "h3")
self.click("li.checkout-link")
self.assert_text("Shopping Cart", "#page-title")
self.assert_element("div#umbrella")
@@ -17,5 +17,5 @@ def test_example_1(self):
self.click('a[rel="license"]')
self.assert_text("back to this page")
self.go_back()
- self.click("link=About")
- self.assert_text("xkcd.com", "h2")
+ self.click_link_text("About")
+ self.assert_exact_text("xkcd.com", "h2")
diff --git a/examples/translations/french_test_1.py b/examples/translations/french_test_1.py
index 5df0c54209d..3c2217a92ef 100755
--- a/examples/translations/french_test_1.py
+++ b/examples/translations/french_test_1.py
@@ -8,11 +8,11 @@ def test_exemple_1(self):
self.ouvrir("https://fr.wikipedia.org/wiki/")
self.vérifier_texte("Wikipédia") # noqa
self.vérifier_élément('[title="Visiter la page d’accueil"]')
- self.modifier_texte("#searchInput", "Crème brûlée")
+ self.taper("#searchInput", "Crème brûlée")
self.cliquer("#searchButton")
self.vérifier_texte("Crème brûlée", "#firstHeading")
self.vérifier_élément('img[alt*="Crème brûlée"]')
- self.modifier_texte("#searchInput", "Jardin des Tuileries")
+ self.taper("#searchInput", "Jardin des Tuileries")
self.cliquer("#searchButton")
self.vérifier_texte("Jardin des Tuileries", "#firstHeading")
self.vérifier_élément('img[alt*="Jardin des Tuileries"]')
diff --git a/examples/translations/italian_test_1.py b/examples/translations/italian_test_1.py
index 1067e716b7d..d370bc4590a 100755
--- a/examples/translations/italian_test_1.py
+++ b/examples/translations/italian_test_1.py
@@ -8,11 +8,11 @@ def test_esempio_1(self):
self.apri("https://it.wikipedia.org/wiki/")
self.verificare_testo("Wikipedia")
self.verificare_elemento('[title="Lingua italiana"]')
- self.aggiornare_testo("#searchInput", "Pizza")
+ self.digitare("#searchInput", "Pizza")
self.fare_clic("#searchButton")
self.verificare_testo("Pizza", "#firstHeading")
self.verificare_elemento('img[alt*="Pizza"]')
- self.aggiornare_testo("#searchInput", "Colosseo")
+ self.digitare("#searchInput", "Colosseo")
self.fare_clic("#searchButton")
self.verificare_testo("Colosseo", "#firstHeading")
self.verificare_elemento('img[alt*="Colosse"]')
diff --git a/examples/translations/japanese_test_1.py b/examples/translations/japanese_test_1.py
index 06284c33c66..6c5d6d36e23 100755
--- a/examples/translations/japanese_test_1.py
+++ b/examples/translations/japanese_test_1.py
@@ -8,14 +8,14 @@ def test_例1(self):
self.を開く("https://ja.wikipedia.org/wiki/")
self.テキストを確認する("ウィキペディア")
self.要素を確認する('[title="メインページに移動する"]')
- self.テキストを更新("#searchInput", "アニメ")
+ self.入力("#searchInput", "アニメ")
self.クリックして("#searchButton")
self.テキストを確認する("アニメ", "#firstHeading")
- self.テキストを更新("#searchInput", "寿司")
+ self.入力("#searchInput", "寿司")
self.クリックして("#searchButton")
self.テキストを確認する("寿司", "#firstHeading")
self.要素を確認する('img[alt="握り寿司"]')
- self.テキストを更新("#searchInput", "レゴランド・ジャパン")
+ self.入力("#searchInput", "レゴランド・ジャパン")
self.クリックして("#searchButton")
self.要素を確認する('img[alt="Legoland japan.jpg"]')
self.リンクテキストを確認する("名古屋城")
diff --git a/examples/translations/korean_test_1.py b/examples/translations/korean_test_1.py
index ecfdd77a68e..80d2ef0f891 100755
--- a/examples/translations/korean_test_1.py
+++ b/examples/translations/korean_test_1.py
@@ -8,12 +8,12 @@ def test_실시예_1(self):
self.열기("https://ko.wikipedia.org/wiki/")
self.텍스트_확인("위키백과")
self.요소_확인('[title="위키백과:소개"]')
- self.텍스트를_업데이트("#searchInput", "김치")
+ self.입력("#searchInput", "김치")
self.클릭("#searchButton")
self.텍스트_확인("김치", "#firstHeading")
self.요소_확인('img[alt="Various kimchi.jpg"]')
self.링크_텍스트_확인("한국 요리")
- self.텍스트를_업데이트("#searchInput", "비빔밥")
+ self.입력("#searchInput", "비빔밥")
self.클릭("#searchButton")
self.텍스트_확인("비빔밥", "#firstHeading")
self.요소_확인('img[alt="Dolsot-bibimbap.jpg"]')
diff --git a/examples/translations/portuguese_test_1.py b/examples/translations/portuguese_test_1.py
index 6884aca252a..0e877897b35 100755
--- a/examples/translations/portuguese_test_1.py
+++ b/examples/translations/portuguese_test_1.py
@@ -8,16 +8,16 @@ def test_exemplo_1(self):
self.abrir("https://pt.wikipedia.org/wiki/")
self.verificar_texto("Wikipédia")
self.verificar_elemento('[title="Língua portuguesa"]')
- self.atualizar_texto("#searchInput", "João Pessoa")
+ self.tipo("#searchInput", "João Pessoa")
self.clique("#searchButton")
self.verificar_texto("João Pessoa", "#firstHeading")
self.verificar_elemento('img[alt*="João Pessoa"]')
- self.atualizar_texto("#searchInput", "Florianópolis")
+ self.tipo("#searchInput", "Florianópolis")
self.clique("#searchButton")
self.verificar_texto("Florianópolis", "h1#firstHeading")
self.verificar_elemento('img[alt*="Avenida Beira Mar"]')
self.voltar()
self.verificar_verdade("João" in self.obter_url_atual())
- self.atualizar_texto("#searchInput", "Moqueca\n")
+ self.tipo("#searchInput", "Moqueca\n")
self.verificar_texto("Moqueca", "#firstHeading")
self.verificar_texto_do_link("Culinária do Brasil")
diff --git a/examples/translations/russian_test_1.py b/examples/translations/russian_test_1.py
index 9ed2aa8aa6a..cb8a579542c 100755
--- a/examples/translations/russian_test_1.py
+++ b/examples/translations/russian_test_1.py
@@ -8,11 +8,11 @@ def test_пример_1(self):
self.открыть("https://ru.wikipedia.org/wiki/")
self.подтвердить_элемент('[title="Русский язык"]')
self.подтвердить_текст("Википедия", "h2.main-wikimedia-header")
- self.обновить_текст("#searchInput", "МГУ")
+ self.введите("#searchInput", "МГУ")
self.нажмите("#searchButton")
self.подтвердить_текст("университет", "#firstHeading")
self.подтвердить_элемент('img[alt="МГУ, вид с воздуха.jpg"]')
- self.обновить_текст("#searchInput", "приключения Шурика")
+ self.введите("#searchInput", "приключения Шурика")
self.нажмите("#searchButton")
self.подтвердить_текст("Операция «Ы» и другие приключения Шурика")
self.подтвердить_элемент('img[alt="Постер фильма"]')
diff --git a/examples/translations/spanish_test_1.py b/examples/translations/spanish_test_1.py
index e9edc93abe1..da5c4682085 100755
--- a/examples/translations/spanish_test_1.py
+++ b/examples/translations/spanish_test_1.py
@@ -7,12 +7,12 @@ class MiClaseDePrueba(CasoDePrueba):
def test_ejemplo_1(self):
self.abrir("https://es.wikipedia.org/wiki/")
self.verificar_texto("Wikipedia")
- self.verificar_elemento('[title="Visitar la página principal"]')
- self.actualizar_texto("#searchInput", "Parc d'Atraccions Tibidabo")
+ self.verificar_elemento('[title*="la página principal"]')
+ self.escriba("#searchInput", "Parc d'Atraccions Tibidabo")
self.haga_clic("#searchButton")
self.verificar_texto("Tibidabo", "#firstHeading")
self.verificar_elemento('img[alt*="Tibidabo"]')
- self.actualizar_texto("#searchInput", "Palma de Mallorca")
+ self.escriba("#searchInput", "Palma de Mallorca")
self.haga_clic("#searchButton")
self.verificar_texto("Palma de Mallorca", "#firstHeading")
self.verificar_elemento('img[alt*="Palma"]')
diff --git a/help_docs/chinese.md b/help_docs/chinese.md
index 67a9582d675..692981f2777 100644
--- a/help_docs/chinese.md
+++ b/help_docs/chinese.md
@@ -124,7 +124,7 @@ class MyTestClass(BaseCase):
self.click("link=About")
self.assert_text("xkcd.com", "h2")
self.open("://store.xkcd.com/collections/everything")
- self.update_text("input.search-input", "xkcd book\n")
+ self.type("input.search-input", "xkcd book\n")
self.assert_exact_text("xkcd: volume 0", "h3")
```
@@ -132,10 +132,12 @@ class MyTestClass(BaseCase):
* 如果你是CSS Selectors新手, 可以通过 [Flukeout](http://flukeout.github.io/) 游戏来帮助学习掌握.
* 在上述代码中可以看到以下相关的 ``SeleniumBase`` 方法:
+``from seleniumbase import BaseCase``:
+
```python
self.open(URL) # 打开页面
self.click(SELECTOR) # 点击页面元素
-self.update_text(SELECTOR, TEXT) # 输入文字 (添加 "\n" 在"TEXT"的末尾来进行换行.)
+self.type(SELECTOR, TEXT) # 输入文字 (添加 "\n" 在"TEXT"的末尾来进行换行.)
self.assert_element(SELECTOR) # 断言元素是否存在并可见
self.assert_text(TEXT) # 断言文本是否存在并可见 (可以选择某个元素选择器)
self.assert_title(PAGE_TITLE) # 断言标题是否存在并可见
@@ -155,6 +157,55 @@ self.switch_to_window(WINDOW_NUMBER) # 切换不同的 window/tab
self.save_screenshot(FILE_NAME) # 保存当前页面的截图
```
+[chinese_test_1.py](https://github.com/seleniumbase/SeleniumBase/blob/master/examples/translations/chinese_test_1.py):
+```python
+from seleniumbase.translate.chinese import 硒测试用例
+
+class 我的测试类(硒测试用例):
+
+ def test_例子1(self):
+ self.开启网址("https://xkcd.in/comic?lg=cn&id=353")
+ self.断言标题("Python - XKCD中文站")
+ self.断言元素("#content div.comic-body")
+ self.断言文本("上漫画")
+ self.单击("div.nextLink")
+ self.断言文本("老妈的逆袭", "#content h1")
+ self.单击链接文本("下一篇")
+ self.断言文本("敲桌子", "#content h1")
+ self.断言文本("有时候无聊就是最棒的乐趣")
+ self.回去()
+ self.单击链接文本("兰德尔·门罗")
+ self.断言文本("兰德尔·门罗", "#firstHeading")
+ self.更新文本("#searchInput", "程式设计")
+ self.单击("#searchButton")
+ self.断言文本("程序设计", "#firstHeading")
+```
+
+``from seleniumbase.translate.chinese import 硒测试用例``:
+
+```python
+self.开启(URL) # 打开页面
+self.单击(SELECTOR) # 点击页面元素
+self.输入文本(SELECTOR, TEXT) # 输入文字 (添加 "\n" 在"TEXT"的末尾来进行换行.)
+self.断言元素(SELECTOR) # 断言元素是否存在并可见
+self.断言文本(TEXT) # 断言文本是否存在并可见 (可以选择某个元素选择器)
+self.断言标题(PAGE_TITLE) # 断言标题是否存在并可见
+self.检查断开的链接() # 断言不存在404错误,若存在则断言失败
+self.检查JS错误() # 断言不存在js错误 (Chrome-ONLY)
+self.执行脚本(JAVASCRIPT) # 在页面中执行js脚本
+self.回去() # 返回到上一个url链接页面
+self.获取文本(SELECTOR) # 获取元素的文本
+self.获取属性(SELECTOR, ATTRIBUTE) # 获取某个定位元素的指定元素属性的属性值
+self.元素是否可见(SELECTOR) # 判断元素是否在页面上可见
+self.文本是否显示(TEXT) # 判断文本是否在页面上可见(可提供 SELECTOR)
+self.悬停并单击(HOVER_SELECTOR, CLICK_SELECTOR) # 鼠标移动在指定元素上后点击另一个元素
+self.按文本选择选项(DROPDOWN_SELECTOR, OPTION_TEXT) # 选择下拉框中内容
+self.切换到帧(FRAME_NAME) # 切换 webdriver control 到页面上指定 iframe
+self.切换到默认内容() # 切换 webdriver control out 到当前的 iframe
+self.切换到窗口(WINDOW_NUMBER) # 切换不同的 window/tab
+self.保存截图(FILE_NAME) # 保存当前页面的截图
+```
+
完整的 SeleniumBase methods, 可见: Method Summary
了解更多信息:
@@ -166,7 +217,7 @@ SeleniumBase 自动化控制 WebDriver 操作 web browsers(浏览器),在运行
SeleniumBase 使用简单简约的语法, 例如:
```python
-self.update_text("input", "dogs\n")
+self.type("input", "dogs\n")
```
上述相似的代码在 Webdriver中变现的不是特别好:
@@ -524,10 +575,10 @@ self.click("div#my_id")
输入文本
-self.update_text(selector, text) # 用指定的值更新来自指定元素的文本。如果元素丢失或文本字段不可编辑,则引发异常。例如:
+self.type(selector, text) # 用指定的值更新来自指定元素的文本。如果元素丢失或文本字段不可编辑,则引发异常。例如:
```python
-self.update_text("input#id_value", "2012")
+self.type("input#id_value", "2012")
```
您也可以使用self.add_text()或WebDriver .send_keys()命令,但是如果文本框中已经有文本,这些命令不会首先清除文本框
如果您想键入特殊的键,这也很容易。这里有一个例子:
diff --git a/help_docs/method_summary.md b/help_docs/method_summary.md
index e6df0b52624..b965d3a5b52 100755
--- a/help_docs/method_summary.md
+++ b/help_docs/method_summary.md
@@ -23,7 +23,7 @@ self.double_click(selector, by=By.CSS_SELECTOR, timeout=None)
self.click_chain(selectors_list, by=By.CSS_SELECTOR, timeout=None, spacing=0)
-self.update_text(selector, new_value, by=By.CSS_SELECTOR, timeout=None, retry=False)
+self.update_text(selector, text, by=By.CSS_SELECTOR, timeout=None, retry=False)
# Duplicates: self.type(selector, text, by=By.CSS_SELECTOR, timeout=None, retry=False)
# self.input(selector, text, by=By.CSS_SELECTOR, timeout=None, retry=False)
# self.write(selector, text, by=By.CSS_SELECTOR, timeout=None, retry=False)
@@ -195,7 +195,7 @@ self.bring_to_front(selector, by=By.CSS_SELECTOR)
self.highlight_click(selector, by=By.CSS_SELECTOR, loops=3, scroll=True)
-self.highlight_update_text(selector, new_value, by=By.CSS_SELECTOR, loops=3, scroll=True)
+self.highlight_update_text(selector, text, by=By.CSS_SELECTOR, loops=3, scroll=True)
self.highlight(selector, by=By.CSS_SELECTOR, loops=4, scroll=True)
@@ -251,6 +251,7 @@ self.get_link_status_code(link, allow_redirects=False, timeout=5)
self.assert_link_status_code_is_not_404(link)
self.assert_no_404_errors(multithreaded=True)
+# Duplicates: self.assert_no_broken_links(multithreaded=True)
self.print_unique_links_with_status_codes()
@@ -302,11 +303,12 @@ self.convert_xpath_to_css(xpath)
self.convert_to_css_selector(selector, by)
-self.set_value(selector, new_value, by=By.CSS_SELECTOR, timeout=None)
+self.set_value(selector, text, by=By.CSS_SELECTOR, timeout=None)
-self.js_update_text(selector, new_value, by=By.CSS_SELECTOR, timeout=None)
+self.js_update_text(selector, text, by=By.CSS_SELECTOR, timeout=None)
+# Duplicates: self.js_type(selector, text, by=By.CSS_SELECTOR, timeout=None)
-self.jquery_update_text(selector, new_value, by=By.CSS_SELECTOR, timeout=None)
+self.jquery_update_text(selector, text, by=By.CSS_SELECTOR, timeout=None)
self.set_time_limit(time_limit)
diff --git a/integrations/node_js/my_first_test.py b/integrations/node_js/my_first_test.py
index d1332597186..cb109e525f7 100755
--- a/integrations/node_js/my_first_test.py
+++ b/integrations/node_js/my_first_test.py
@@ -4,14 +4,14 @@
class MyTestClass(BaseCase):
def test_basic(self):
+ self.open("https://store.xkcd.com/search")
+ self.type('input[name="q"]', "xkcd book\n")
+ self.assert_text("xkcd: volume 0", "h3")
self.open("https://xkcd.com/353/")
self.assert_title("xkcd: Python")
self.assert_element('img[alt="Python"]')
self.click('a[rel="license"]')
self.assert_text("free to copy and reuse")
self.go_back()
- self.click("link=About")
- self.assert_text("xkcd.com", "h2")
- self.open("://store.xkcd.com/collections/everything")
- self.update_text("input.search-input", "xkcd book\n")
- self.assert_exact_text("xkcd: volume 0", "h3")
+ self.click_link_text("About")
+ self.assert_exact_text("xkcd.com", "h2")
diff --git a/requirements.txt b/requirements.txt
index cae97abfad7..a676600c7eb 100755
--- a/requirements.txt
+++ b/requirements.txt
@@ -16,7 +16,7 @@ pluggy==0.13.1
attrs>=19.3.0
pytest==4.6.11;python_version<"3.5"
pytest==5.4.3;python_version>="3.5"
-pytest-cov==2.9.0
+pytest-cov==2.10.0
pytest-forked==1.1.3
pytest-html==1.22.1;python_version<"3.6"
pytest-html==2.0.1;python_version>="3.6"
@@ -41,9 +41,9 @@ coverage==5.1
pyotp==2.3.0
boto==2.49.0
cffi==1.14.0
-rich==2.0.0;python_version>="3.6" and python_version<"4.0"
+rich==2.1.0;python_version>="3.6" and python_version<"4.0"
flake8==3.7.9;python_version<"3.5"
-flake8==3.8.2;python_version>="3.5"
+flake8==3.8.3;python_version>="3.5"
pyflakes==2.1.1;python_version<"3.5"
pyflakes==2.2.0;python_version>="3.5"
certifi>=2020.4.5.2
diff --git a/seleniumbase/config/proxy_list.py b/seleniumbase/config/proxy_list.py
index 213c0f97707..3835f52538c 100755
--- a/seleniumbase/config/proxy_list.py
+++ b/seleniumbase/config/proxy_list.py
@@ -20,13 +20,10 @@
"""
PROXY_LIST = {
- "example1": "142.93.130.169:8118", # (Example) - set your own proxy here
- "example2": "51.91.212.159:3128", # (Example) - set your own proxy here
- "example3": "149.129.238.254:3128", # (Example) - set your own proxy here
- "example4": "82.200.233.4:3128", # (Example) - set your own proxy here
- "example5": "46.218.155.194:3128", # (Example) - set your own proxy here
- "example6": "45.77.222.251:3128", # (Example) - set your own proxy here
- "example7": "51.178.220.168:3128", # (Example) - set your own proxy here
+ "example1": "104.154.143.77:3128", # (Example) - set your own proxy here
+ "example2": "105.112.8.53:3128", # (Example) - set your own proxy here
+ "example3": "82.200.233.4:3128", # (Example) - set your own proxy here
+ "example4": "176.53.40.222:3128", # (Example) - set your own proxy here
"proxy1": None,
"proxy2": None,
"proxy3": None,
diff --git a/seleniumbase/console_scripts/ReadMe.md b/seleniumbase/console_scripts/ReadMe.md
index 14e921067ca..05706822236 100755
--- a/seleniumbase/console_scripts/ReadMe.md
+++ b/seleniumbase/console_scripts/ReadMe.md
@@ -4,20 +4,28 @@
SeleniumBase console scripts help you get things done more easily, such as installing web drivers, creating a test directory with necessary configuration files, converting old WebDriver unittest scripts into SeleniumBase code, translating tests into multiple languages, and using the Selenium Grid.
-Type ``seleniumbase`` on the command line to use console scripts.
-You can also use the simplified name: ``sbase`` instead.
+* Usage: ``seleniumbase [COMMAND] [PARAMETERS]``
+
+* (simplified): ``sbase [COMMAND] [PARAMETERS]``
+
+* To list all commands: ``seleniumbase --help``
(For running tests, [use pytest with SeleniumBase](https://github.com/seleniumbase/SeleniumBase/blob/master/help_docs/customizing_test_runs.md). )
### install
* Usage:
-``seleniumbase install [DRIVER_NAME]``
- (Drivers: ``chromedriver``, ``geckodriver``, ``edgedriver``,
- ``iedriver``, ``operadriver``)
+``sbase install [DRIVER_NAME] [VERSION]``
+ (Drivers: ``chromedriver``, ``geckodriver``, ``edgedriver``,
+ ``iedriver``, ``operadriver``)
+ (Versions: ``latest`` or a specific driver version.
+ If none specified, installs the default version.)
-* Example:
-``seleniumbase install chromedriver``
+* Examples:
+``sbase install chromedriver``
+
+* Options:
+ ``latest``:
* Output:
Installs the specified webdriver.
@@ -30,22 +38,50 @@ Installs the specified webdriver.
### mkdir
* Usage:
-``seleniumbase mkdir [DIRECTORY_NAME]``
+``sbase mkdir [DIRECTORY_NAME]``
* Example:
-``seleniumbase mkdir browser_tests``
+``sbase mkdir browser_tests``
* Output:
Creates a new folder for running SeleniumBase scripts.
The new folder contains default config files,
-sample tests for helping new users get started, and
-Python boilerplates for setting up customized
+sample tests for helping new users get started,
+and Python boilerplates for setting up customized
test frameworks.
+### mkfile
+
+* Usage:
+``sbase mkfile [FILE_NAME.py] [OPTIONS]``
+
+* Example:
+``sbase mkfile new_test.py``
+
+* Options:
+``-b`` / ``--basic`` (Basic boilerplate / single-line test)
+
+* Language Options:
+``--en`` / ``--English`` | ``--zh`` / ``--Chinese``
+``--nl`` / ``--Dutch`` | ``--fr`` / ``--French``
+``--it`` / ``--Italian`` | ``--ja`` / ``--Japanese``
+``--ko`` / ``--Korean`` | ``--pt`` / ``--Portuguese``
+``--ru`` / ``--Russian`` | ``--es`` / ``--Spanish``
+
+* Output:
+Creates a new SeleniumBase test file with boilerplate code.
+If the file already exists, an error is raised.
+By default, uses English mode and creates a
+boilerplate with the 5 most common SeleniumBase
+methods, which are "open", "click", "update_text",
+"assert_element", and "assert_text". If using the
+basic boilerplate option, only the "open" method
+is included.
+
### convert
* Usage:
-``seleniumbase convert [PYTHON_WEBDRIVER_UNITTEST_FILE]``
+``sbase convert [PYTHON_WEBDRIVER_UNITTEST_FILE]``
* Output:
Converts a Selenium IDE exported WebDriver unittest file
@@ -57,7 +93,7 @@ See: http://www.katalon.com/automation-recorder
### translate
* Usage:
-``seleniumbase translate [SB_FILE].py [LANGUAGE] [ACTION]``
+``sbase translate [SB_FILE].py [LANGUAGE] [ACTION]``
* Languages:
``--en`` / ``--English`` | ``--zh`` / ``--Chinese``
@@ -89,7 +125,7 @@ plus the 2-letter language code of the new language.
### extract-objects
* Usage:
-``seleniumbase extract-objects [SB_PYTHON_FILE]``
+``sbase extract-objects [SB_PYTHON_FILE]``
* Output:
Creates page objects based on selectors found in a
@@ -99,7 +135,7 @@ seleniumbase Python file and saves those objects to the
### inject-objects
* Usage:
-``seleniumbase inject-objects [SB_PYTHON_FILE] [OPTIONS]``
+``sbase inject-objects [SB_PYTHON_FILE] [OPTIONS]``
* Options:
``-c``, ``--comments`` (Add object selectors to the comments.)
@@ -112,7 +148,7 @@ the selected seleniumbase Python file.
### objectify
* Usage:
-``seleniumbase objectify [SB_PYTHON_FILE] [OPTIONS]``
+``sbase objectify [SB_PYTHON_FILE] [OPTIONS]``
* Options:
``-c``, ``--comments`` (Add object selectors to the comments.)
@@ -127,7 +163,7 @@ have been replaced with variable names defined in
### revert-objects
* Usage:
-``seleniumbase revert-objects [SB_PYTHON_FILE] [OPTIONS]``
+``sbase revert-objects [SB_PYTHON_FILE] [OPTIONS]``
* Options:
``-c``, ``--comments`` (Keep existing comments for the lines.)
@@ -141,11 +177,11 @@ selectors stored in the "page_objects.py" file.
### download
* Usage:
-``seleniumbase download [ITEM]``
+``sbase download [ITEM]``
(Options: server)
* Example:
-``seleniumbase download server``
+``sbase download server``
* Output:
Downloads the specified item.
@@ -154,7 +190,7 @@ Downloads the specified item.
### grid-hub
* Usage:
-``seleniumbase grid-hub {start|stop}``
+``sbase grid-hub {start|stop}``
* Options:
``-v``, ``--verbose`` (Increases verbosity of logging output.)
@@ -169,7 +205,7 @@ You can start, restart, or stop the Grid Hub server.
### grid-node
* Usage:
-``seleniumbase grid-node {start|stop} [OPTIONS]``
+``sbase grid-node {start|stop} [OPTIONS]``
* Options:
``--hub=HUB_IP`` (The Grid Hub IP Address to connect to.) (Default: ``127.0.0.1``)
diff --git a/seleniumbase/console_scripts/run.py b/seleniumbase/console_scripts/run.py
index 698f11abd3f..c05c1585d41 100644
--- a/seleniumbase/console_scripts/run.py
+++ b/seleniumbase/console_scripts/run.py
@@ -8,6 +8,7 @@
Examples:
sbase install chromedriver
sbase mkdir browser_tests
+sbase mkfile new_test.py
sbase convert my_old_webdriver_unittest.py
sbase print my_first_test.py -n
sbase translate my_first_test.py --zh -p
@@ -24,16 +25,6 @@
import colorama
import sys
-from seleniumbase.common import obfuscate
-from seleniumbase.common import unobfuscate
-from seleniumbase.console_scripts import logo_helper
-from seleniumbase.console_scripts import objectify
-from seleniumbase.console_scripts import sb_install
-from seleniumbase.console_scripts import sb_mkdir
-from seleniumbase.utilities.selenium_grid import download_selenium_server
-from seleniumbase.utilities.selenium_grid import grid_hub
-from seleniumbase.utilities.selenium_grid import grid_node
-from seleniumbase.utilities.selenium_ide import convert_ide
def show_usage():
@@ -56,17 +47,19 @@ def show_usage():
def show_basic_usage():
+ from seleniumbase.console_scripts import logo_helper
seleniumbase_logo = logo_helper.get_seleniumbase_logo()
print(seleniumbase_logo)
print("%s" % get_version()[0:1])
print("")
sc = ("")
sc += ('Usage: "seleniumbase [COMMAND] [PARAMETERS]"\n')
- sc += ('(short name): "sbase [COMMAND] [PARAMETERS]"\n')
+ sc += ('(simplified): "sbase [COMMAND] [PARAMETERS]"\n')
sc += ("\n")
sc += ("Commands:\n")
sc += (" install [DRIVER_NAME] [OPTIONS]\n")
- sc += (" mkdir [NEW_TEST_DIRECTORY_NAME]\n")
+ sc += (" mkdir [DIRECTORY_NAME]\n")
+ sc += (" mkfile [FILE_NAME.py]\n")
sc += (" convert [PYTHON_WEBDRIVER_UNITTEST_FILE]\n")
sc += (" print [FILE] [OPTIONS]\n")
sc += (" translate [SB_PYTHON_FILE] [LANGUAGE] [ACTION]\n")
@@ -90,7 +83,11 @@ def show_basic_usage():
def show_install_usage():
- print(" ** install **")
+ c2 = colorama.Fore.BLUE + colorama.Back.LIGHTGREEN_EX
+ c3 = colorama.Fore.BLUE + colorama.Back.LIGHTYELLOW_EX
+ cr = colorama.Style.RESET_ALL
+ sc = (" " + c2 + "** " + c3 + "install" + c2 + " **" + cr)
+ print(sc)
print("")
print(" Usage:")
print(" seleniumbase install [DRIVER_NAME] [OPTIONS]")
@@ -103,12 +100,12 @@ def show_install_usage():
print(' Use "latest" for the latest version.')
print(" -p OR --path Also copy the driver to /usr/local/bin")
print(" Example:")
- print(" seleniumbase install chromedriver")
- print(" seleniumbase install geckodriver")
- print(" seleniumbase install chromedriver 83.0.4103.39")
- print(" seleniumbase install chromedriver latest")
- print(" seleniumbase install chromedriver -p")
- print(" seleniumbase install chromedriver latest -p")
+ print(" sbase install chromedriver")
+ print(" sbase install geckodriver")
+ print(" sbase install chromedriver 83.0.4103.39")
+ print(" sbase install chromedriver latest")
+ print(" sbase install chromedriver -p")
+ print(" sbase install chromedriver latest -p")
print(" Output:")
print(" Installs the chosen webdriver to seleniumbase/drivers/")
print(" (chromedriver is required for Chrome automation)")
@@ -120,24 +117,64 @@ def show_install_usage():
def show_mkdir_usage():
- print(" ** mkdir **")
+ c2 = colorama.Fore.BLUE + colorama.Back.LIGHTGREEN_EX
+ c3 = colorama.Fore.BLUE + colorama.Back.LIGHTYELLOW_EX
+ cr = colorama.Style.RESET_ALL
+ sc = (" " + c2 + "** " + c3 + "mkdir" + c2 + " **" + cr)
+ print(sc)
print("")
print(" Usage:")
print(" seleniumbase mkdir [DIRECTORY_NAME]")
print(" OR: sbase mkdir [DIRECTORY_NAME]")
print(" Example:")
- print(" seleniumbase mkdir browser_tests")
+ print(" sbase mkdir browser_tests")
print(" Output:")
- print(" Creates a new folder for running SeleniumBase scripts.")
+ print(" Creates a new folder for running SBase scripts.")
print(" The new folder contains default config files,")
- print(" sample tests for helping new users get started, and")
- print(" Python boilerplates for setting up customized")
+ print(" sample tests for helping new users get started,")
+ print(" and Python boilerplates for setting up customized")
print(" test frameworks.")
print("")
+def show_mkfile_usage():
+ c2 = colorama.Fore.BLUE + colorama.Back.LIGHTGREEN_EX
+ c3 = colorama.Fore.BLUE + colorama.Back.LIGHTYELLOW_EX
+ cr = colorama.Style.RESET_ALL
+ sc = (" " + c2 + "** " + c3 + "mkfile" + c2 + " **" + cr)
+ print(sc)
+ print("")
+ print(" Usage:")
+ print(" seleniumbase mkfile [FILE_NAME.py]")
+ print(" OR: sbase mkfile [FILE_NAME.py]")
+ print(" Example:")
+ print(" sbase mkfile new_test.py")
+ print(" Options:")
+ print(" -b / --basic (Basic boilerplate / single-line test)")
+ print(" Language Options:")
+ print(" --en / --English | --zh / --Chinese")
+ print(" --nl / --Dutch | --fr / --French")
+ print(" --it / --Italian | --ja / --Japanese")
+ print(" --ko / --Korean | --pt / --Portuguese")
+ print(" --ru / --Russian | --es / --Spanish")
+ print(" Output:")
+ print(" Creates a new SBase test file with boilerplate code.")
+ print(" If the file already exists, an error is raised.")
+ print(" By default, uses English mode and creates a")
+ print(" boilerplate with the 5 most common SeleniumBase")
+ print(' methods, which are "open", "click", "update_text",')
+ print(' "assert_element", and "assert_text". If using the')
+ print(' basic boilerplate option, only the "open" method')
+ print(' is included.')
+ print("")
+
+
def show_convert_usage():
- print(" ** convert **")
+ c2 = colorama.Fore.BLUE + colorama.Back.LIGHTGREEN_EX
+ c3 = colorama.Fore.BLUE + colorama.Back.LIGHTYELLOW_EX
+ cr = colorama.Style.RESET_ALL
+ sc = (" " + c2 + "** " + c3 + "convert" + c2 + " **" + cr)
+ print(sc)
print("")
print(" Usage:")
print(" seleniumbase convert [PYTHON_WEBDRIVER_UNITTEST_FILE]")
@@ -152,7 +189,12 @@ def show_convert_usage():
def show_print_usage():
- print(" ** print **")
+ c2 = colorama.Fore.BLUE + colorama.Back.LIGHTGREEN_EX
+ c3 = colorama.Fore.BLUE + colorama.Back.LIGHTYELLOW_EX
+ cr = colorama.Style.RESET_ALL
+ sc = (" " + c2 + "** " + c3 + "print" + c2 + " **" + cr)
+ print(sc)
+ print("")
print(" Usage:")
print(" seleniumbase print [FILE] [OPTIONS]")
print(" OR: sbase print [FILE] [OPTIONS]")
@@ -166,7 +208,12 @@ def show_print_usage():
def show_translate_usage():
- print(" ** translate **")
+ c2 = colorama.Fore.BLUE + colorama.Back.LIGHTGREEN_EX
+ c3 = colorama.Fore.BLUE + colorama.Back.LIGHTYELLOW_EX
+ cr = colorama.Style.RESET_ALL
+ sc = (" " + c2 + "** " + c3 + "translate" + c2 + " **" + cr)
+ print(sc)
+ print("")
print(" Usage:")
print(" seleniumbase translate [SB_FILE.py] [LANGUAGE] [ACTION]")
print(" OR: sbase translate [SB_FILE.py] [LANGUAGE] [ACTION]")
@@ -196,7 +243,11 @@ def show_translate_usage():
def show_extract_objects_usage():
- print(" ** extract-objects **")
+ c2 = colorama.Fore.BLUE + colorama.Back.LIGHTGREEN_EX
+ c3 = colorama.Fore.BLUE + colorama.Back.LIGHTYELLOW_EX
+ cr = colorama.Style.RESET_ALL
+ sc = (" " + c2 + "** " + c3 + "extract-objects" + c2 + " **" + cr)
+ print(sc)
print("")
print(" Usage:")
print(" seleniumbase extract-objects [SELENIUMBASE_PYTHON_FILE]")
@@ -209,7 +260,11 @@ def show_extract_objects_usage():
def show_inject_objects_usage():
- print(" ** inject-objects **")
+ c2 = colorama.Fore.BLUE + colorama.Back.LIGHTGREEN_EX
+ c3 = colorama.Fore.BLUE + colorama.Back.LIGHTYELLOW_EX
+ cr = colorama.Style.RESET_ALL
+ sc = (" " + c2 + "** " + c3 + "inject-objects" + c2 + " **" + cr)
+ print(sc)
print("")
print(" Usage:")
print(" seleniumbase inject-objects [SELENIUMBASE_PYTHON_FILE]")
@@ -225,7 +280,11 @@ def show_inject_objects_usage():
def show_objectify_usage():
- print(" ** objectify **")
+ c2 = colorama.Fore.BLUE + colorama.Back.LIGHTGREEN_EX
+ c3 = colorama.Fore.BLUE + colorama.Back.LIGHTYELLOW_EX
+ cr = colorama.Style.RESET_ALL
+ sc = (" " + c2 + "** " + c3 + "objectify" + c2 + " **" + cr)
+ print(sc)
print("")
print(" Usage:")
print(" seleniumbase objectify [SELENIUMBASE_PYTHON_FILE]")
@@ -244,7 +303,11 @@ def show_objectify_usage():
def show_revert_objects_usage():
- print(" ** revert-objects **")
+ c2 = colorama.Fore.BLUE + colorama.Back.LIGHTGREEN_EX
+ c3 = colorama.Fore.BLUE + colorama.Back.LIGHTYELLOW_EX
+ cr = colorama.Style.RESET_ALL
+ sc = (" " + c2 + "** " + c3 + "revert-objects" + c2 + " **" + cr)
+ print(sc)
print("")
print(" Usage:")
print(" seleniumbase revert-objects [SELENIUMBASE_PYTHON_FILE]")
@@ -261,7 +324,11 @@ def show_revert_objects_usage():
def show_encrypt_usage():
- print(" ** encrypt OR obfuscate **")
+ c2 = colorama.Fore.BLUE + colorama.Back.LIGHTGREEN_EX
+ c3 = colorama.Fore.BLUE + colorama.Back.LIGHTYELLOW_EX
+ cr = colorama.Style.RESET_ALL
+ sc = (" " + c2 + "** " + c3 + "encrypt OR obfuscate" + c2 + " **" + cr)
+ print(sc)
print("")
print(" Usage:")
print(" seleniumbase encrypt || seleniumbase obfuscate")
@@ -274,7 +341,11 @@ def show_encrypt_usage():
def show_decrypt_usage():
- print(" ** decrypt OR unobfuscate **")
+ c2 = colorama.Fore.BLUE + colorama.Back.LIGHTGREEN_EX
+ c3 = colorama.Fore.BLUE + colorama.Back.LIGHTYELLOW_EX
+ cr = colorama.Style.RESET_ALL
+ sc = (" " + c2 + "** " + c3 + "decrypt OR unobfuscate" + c2 + " **" + cr)
+ print(sc)
print("")
print(" Usage:")
print(" seleniumbase decrypt || seleniumbase unobfuscate")
@@ -287,7 +358,11 @@ def show_decrypt_usage():
def show_download_usage():
- print(" ** download **")
+ c2 = colorama.Fore.BLUE + colorama.Back.LIGHTGREEN_EX
+ c3 = colorama.Fore.BLUE + colorama.Back.LIGHTYELLOW_EX
+ cr = colorama.Style.RESET_ALL
+ sc = (" " + c2 + "** " + c3 + "download" + c2 + " **" + cr)
+ print(sc)
print("")
print(" Usage:")
print(" seleniumbase download server")
@@ -299,7 +374,11 @@ def show_download_usage():
def show_grid_hub_usage():
- print(" ** grid-hub **")
+ c2 = colorama.Fore.BLUE + colorama.Back.LIGHTGREEN_EX
+ c3 = colorama.Fore.BLUE + colorama.Back.LIGHTYELLOW_EX
+ cr = colorama.Style.RESET_ALL
+ sc = (" " + c2 + "** " + c3 + "grid-hub" + c2 + " **" + cr)
+ print(sc)
print("")
print(" Usage:")
print(" seleniumbase grid-hub {start|stop}")
@@ -319,7 +398,11 @@ def show_grid_hub_usage():
def show_grid_node_usage():
- print(" ** grid-node **")
+ c2 = colorama.Fore.BLUE + colorama.Back.LIGHTGREEN_EX
+ c3 = colorama.Fore.BLUE + colorama.Back.LIGHTYELLOW_EX
+ cr = colorama.Style.RESET_ALL
+ sc = (" " + c2 + "** " + c3 + "grid-node" + c2 + " **" + cr)
+ print(sc)
print("")
print(" Usage:")
print(" seleniumbase grid-node {start|stop} [OPTIONS]")
@@ -354,11 +437,16 @@ def show_version_info():
def show_detailed_help():
+ c2 = colorama.Fore.BLUE + colorama.Back.LIGHTGREEN_EX
+ c3 = colorama.Fore.BLUE + colorama.Back.LIGHTYELLOW_EX
+ c6 = colorama.Back.CYAN
+ cr = colorama.Style.RESET_ALL
show_basic_usage()
- print("More Info:")
- print("")
+ print(c6 + " " + c2 + " Commands: " + c6 + " ")
+ print(cr)
show_install_usage()
show_mkdir_usage()
+ show_mkfile_usage()
show_convert_usage()
show_print_usage()
show_translate_usage()
@@ -371,8 +459,6 @@ def show_detailed_help():
show_download_usage()
show_grid_hub_usage()
show_grid_node_usage()
- c3 = colorama.Fore.BLUE + colorama.Back.LIGHTYELLOW_EX
- cr = colorama.Style.RESET_ALL
print('* (Use "' + c3 + 'pytest' + cr + '" for running tests) *\n')
@@ -393,18 +479,28 @@ def main():
if command == "install":
if len(command_args) >= 1:
+ from seleniumbase.console_scripts import sb_install
sb_install.main()
else:
show_basic_usage()
show_install_usage()
elif command == "mkdir":
if len(command_args) >= 1:
+ from seleniumbase.console_scripts import sb_mkdir
sb_mkdir.main()
else:
show_basic_usage()
show_mkdir_usage()
+ elif command == "mkfile":
+ if len(command_args) >= 1:
+ from seleniumbase.console_scripts import sb_mkfile
+ sb_mkfile.main()
+ else:
+ show_basic_usage()
+ show_mkfile_usage()
elif command == "convert":
if len(command_args) == 1:
+ from seleniumbase.utilities.selenium_ide import convert_ide
convert_ide.main()
else:
show_basic_usage()
@@ -442,54 +538,64 @@ def main():
show_translate_usage()
elif command == "extract-objects" or command == "extract_objects":
if len(command_args) >= 1:
+ from seleniumbase.console_scripts import objectify
objectify.extract_objects()
else:
show_basic_usage()
show_extract_objects_usage()
elif command == "inject-objects" or command == "inject_objects":
if len(command_args) >= 1:
+ from seleniumbase.console_scripts import objectify
objectify.inject_objects()
else:
show_basic_usage()
show_inject_objects_usage()
elif command == "objectify":
if len(command_args) >= 1:
+ from seleniumbase.console_scripts import objectify
objectify.objectify()
else:
show_basic_usage()
show_objectify_usage()
elif command == "revert-objects" or command == "revert_objects":
if len(command_args) >= 1:
+ from seleniumbase.console_scripts import objectify
objectify.revert_objects()
else:
show_basic_usage()
show_revert_objects_usage()
elif command == "encrypt" or command == "obfuscate":
if len(command_args) >= 0:
+ from seleniumbase.common import obfuscate
obfuscate.main()
else:
show_basic_usage()
show_encrypt_usage()
elif command == "decrypt" or command == "unobfuscate":
if len(command_args) >= 0:
+ from seleniumbase.common import unobfuscate
unobfuscate.main()
else:
show_basic_usage()
show_decrypt_usage()
elif command == "download":
if len(command_args) >= 1 and command_args[0].lower() == "server":
+ from seleniumbase.utilities.selenium_grid import (
+ download_selenium_server)
download_selenium_server.main(force_download=True)
else:
show_basic_usage()
show_download_usage()
elif command == "grid-hub" or command == "grid_hub":
if len(command_args) >= 1:
+ from seleniumbase.utilities.selenium_grid import grid_hub
grid_hub.main()
else:
show_basic_usage()
show_grid_hub_usage()
elif command == "grid-node" or command == "grid_node":
if len(command_args) >= 1:
+ from seleniumbase.utilities.selenium_grid import grid_node
grid_node.main()
else:
show_basic_usage()
@@ -509,6 +615,10 @@ def main():
print("")
show_mkdir_usage()
return
+ elif command_args[0] == "mkfile":
+ print("")
+ show_mkfile_usage()
+ return
elif command_args[0] == "convert":
print("")
show_convert_usage()
diff --git a/seleniumbase/console_scripts/sb_mkdir.py b/seleniumbase/console_scripts/sb_mkdir.py
index 0b2c98877cc..2f753d08b53 100755
--- a/seleniumbase/console_scripts/sb_mkdir.py
+++ b/seleniumbase/console_scripts/sb_mkdir.py
@@ -2,360 +2,355 @@
Creates a new folder for running SeleniumBase scripts.
Usage:
-seleniumbase mkdir [DIRECTORY_NAME]
+ seleniumbase mkdir [DIRECTORY_NAME]
+ OR sbase mkdir [DIRECTORY_NAME]
+
+Example:
+ sbase mkdir browser_tests
+
Output:
-Creates a new folder for running SeleniumBase 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.
+ 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.
"""
import codecs
+import colorama
import os
import sys
-def invalid_run_command():
+def invalid_run_command(msg=None):
exp = (" ** mkdir **\n\n")
exp += " Usage:\n"
exp += " seleniumbase mkdir [DIRECTORY_NAME]\n"
+ exp += " OR sbase mkdir [DIRECTORY_NAME]\n"
exp += " Example:\n"
- exp += " seleniumbase mkdir browser_tests\n"
+ exp += " sbase mkdir browser_tests\n"
exp += " Output:\n"
- exp += " Creates a new folder for running SeleniumBase scripts.\n"
+ exp += " Creates a new folder for running SBase scripts.\n"
exp += " The new folder contains default config files,\n"
- exp += " sample tests for helping new users get started, and\n"
- exp += " Python boilerplates for setting up customized\n"
+ exp += " sample tests for helping new users get started,\n"
+ exp += " and Python boilerplates for setting up customized\n"
exp += " test frameworks.\n"
- print("")
- raise Exception('INVALID RUN COMMAND!\n\n%s' % exp)
+ if not msg:
+ raise Exception('INVALID RUN COMMAND!\n\n%s' % exp)
+ else:
+ raise Exception('INVALID RUN COMMAND!\n\n%s\n%s\n' % (exp, msg))
def main():
- num_args = len(sys.argv)
- if sys.argv[0].split('/')[-1].lower() == "seleniumbase" or (
- sys.argv[0].split('\\')[-1].lower() == "seleniumbase") or (
- sys.argv[0].split('/')[-1].lower() == "sbase") or (
- sys.argv[0].split('\\')[-1].lower() == "sbase"):
- if num_args < 3 or num_args > 3:
- invalid_run_command()
- else:
+ colorama.init(autoreset=True)
+ c5 = colorama.Fore.RED + colorama.Back.LIGHTYELLOW_EX
+ cr = colorama.Style.RESET_ALL
+ error_msg = None
+ command_args = sys.argv[2:]
+ if len(command_args) != 1:
invalid_run_command()
- dir_name = sys.argv[num_args - 1]
+ dir_name = command_args[0]
if len(str(dir_name)) < 2:
- raise Exception('Directory name length must be at least 2 '
- 'characters long!')
- if os.path.exists(os.getcwd() + '/' + dir_name):
- raise Exception('Directory "%s" already exists '
- 'in the current path!\n' % dir_name)
- else:
- os.mkdir(dir_name)
+ error_msg = (
+ 'Directory name length must be at least 2 characters long!')
+ elif "/" in str(dir_name) or "\\" in str(dir_name):
+ error_msg = (
+ 'Directory name must not include slashes ("/", "\\")!')
+ elif os.path.exists(os.getcwd() + '/' + dir_name):
+ error_msg = (
+ 'Directory "%s" already exists in the current path!\n'
+ '' % dir_name)
+ if error_msg:
+ error_msg = c5 + error_msg + cr
+ invalid_run_command(error_msg)
+
+ os.mkdir(dir_name)
- data = []
- data.append("[pytest]")
- data.append("addopts = --capture=no --ignore conftest.py "
- "-p no:cacheprovider")
- data.append("filterwarnings =")
- data.append(" ignore::pytest.PytestWarning")
- data.append(" ignore:.*U.*mode is deprecated:DeprecationWarning")
- data.append("junit_family = legacy")
- data.append("python_files = test_*.py *_test.py *_tests.py *_suite.py")
- data.append("python_classes = Test* *Test* *Test *Tests *Suite")
- data.append("python_functions = test_*")
- data.append("markers =")
- data.append(" marker1: custom marker")
- data.append(" marker2: custom marker")
- data.append(" marker3: custom marker")
- data.append(" marker_test_suite: custom marker")
- data.append(" expected_failure: custom marker")
- data.append(" local: custom marker")
- data.append(" remote: custom marker")
- data.append(" offline: custom marker")
- data.append(" develop: custom marker")
- data.append(" qa: custom marker")
- data.append(" ready: custom marker")
- data.append(" master: custom marker")
- data.append(" release: custom marker")
- data.append(" staging: custom marker")
- data.append(" production: custom marker")
- data.append("")
- file_path = "%s/%s" % (dir_name, "pytest.ini")
- file = codecs.open(file_path, "w+", "utf-8")
- file.writelines("\r\n".join(data))
- file.close()
+ data = []
+ data.append("[pytest]")
+ data.append("addopts = --capture=no --ignore conftest.py "
+ "-p no:cacheprovider")
+ data.append("filterwarnings =")
+ data.append(" ignore::pytest.PytestWarning")
+ data.append(" ignore:.*U.*mode is deprecated:DeprecationWarning")
+ data.append("junit_family = legacy")
+ data.append("python_files = test_*.py *_test.py *_tests.py *_suite.py")
+ data.append("python_classes = Test* *Test* *Test *Tests *Suite")
+ data.append("python_functions = test_*")
+ data.append("markers =")
+ data.append(" marker1: custom marker")
+ data.append(" marker2: custom marker")
+ data.append(" marker3: custom marker")
+ data.append(" marker_test_suite: custom marker")
+ data.append(" expected_failure: custom marker")
+ data.append(" local: custom marker")
+ data.append(" remote: custom marker")
+ data.append(" offline: custom marker")
+ data.append(" develop: custom marker")
+ data.append(" qa: custom marker")
+ data.append(" ready: custom marker")
+ data.append(" master: custom marker")
+ data.append(" release: custom marker")
+ data.append(" staging: custom marker")
+ data.append(" production: custom marker")
+ data.append("")
+ file_path = "%s/%s" % (dir_name, "pytest.ini")
+ file = codecs.open(file_path, "w+", "utf-8")
+ file.writelines("\r\n".join(data))
+ file.close()
- data = []
- data.append("[nosetests]")
- data.append("nocapture=1")
- data.append("logging-level=INFO")
- data.append("")
- data.append("[bdist_wheel]")
- data.append("universal=1")
- file_path = "%s/%s" % (dir_name, "setup.cfg")
- file = codecs.open(file_path, "w+", "utf-8")
- file.writelines("\r\n".join(data))
- file.close()
+ data = []
+ data.append("[nosetests]")
+ data.append("nocapture=1")
+ data.append("logging-level=INFO")
+ data.append("")
+ data.append("[bdist_wheel]")
+ data.append("universal=1")
+ file_path = "%s/%s" % (dir_name, "setup.cfg")
+ file = codecs.open(file_path, "w+", "utf-8")
+ file.writelines("\r\n".join(data))
+ file.close()
- data = []
- data.append("from seleniumbase import BaseCase")
- data.append("")
- data.append("")
- data.append("class MyTestClass(BaseCase):")
- data.append("")
- data.append(" def test_basic(self):")
- data.append(' self.open("https://xkcd.com/353/")')
- data.append(' self.assert_title("xkcd: Python")')
- data.append(" self.assert_element('img[alt=\"Python\"]')")
- data.append(" self.click('a[rel=\"license\"]')")
- data.append(' self.assert_text("free to copy and reuse")')
- data.append(' self.go_back()')
- data.append(' self.click("link=About")')
- data.append(' self.assert_text("xkcd.com", "h2")')
- data.append(' self.open('
- '"://store.xkcd.com/collections/everything")')
- data.append(
- ' self.update_text("input.search-input", "xkcd book\\n")')
- data.append(' self.assert_text("xkcd: volume 0", "h3")')
- data.append("")
- file_path = "%s/%s" % (dir_name, "my_first_test.py")
- file = codecs.open(file_path, "w+", "utf-8")
- file.writelines("\r\n".join(data))
- file.close()
+ data = []
+ data.append("from seleniumbase import BaseCase")
+ data.append("")
+ data.append("")
+ data.append("class MyTestClass(BaseCase):")
+ data.append("")
+ data.append(" def test_basic(self):")
+ data.append(' self.open("https://store.xkcd.com/search")')
+ data.append(" self.type('input[name=\"q\"]', \"xkcd book\\n\")")
+ data.append(' self.assert_text("xkcd: volume 0", "h3")')
+ data.append(' self.open("https://xkcd.com/353/")')
+ data.append(' self.assert_title("xkcd: Python")')
+ data.append(" self.assert_element('img[alt=\"Python\"]')")
+ data.append(" self.click('a[rel=\"license\"]')")
+ data.append(' self.assert_text("free to copy and reuse")')
+ data.append(' self.go_back()')
+ data.append(' self.click("link=About")')
+ data.append(' self.assert_exact_text("xkcd.com", "h2")')
+ data.append("")
+ file_path = "%s/%s" % (dir_name, "my_first_test.py")
+ file = codecs.open(file_path, "w+", "utf-8")
+ file.writelines("\r\n".join(data))
+ file.close()
- data = []
- data.append("from seleniumbase import BaseCase")
- data.append("")
- data.append("")
- data.append("class MyTestClass(BaseCase):")
- data.append("")
- data.append(" def test_demo_site(self):")
- data.append(' self.open('
- '"https://seleniumbase.io/demo_page.html")')
- data.append(' self.assert_title("Web Testing Page")')
- data.append(' self.assert_element("tbody#tbodyId")')
- data.append(' self.assert_text("Demo Page", "h1")')
- data.append(' self.update_text("#myTextInput", '
- '"This is Automated")')
- data.append(' self.update_text("textarea.area1", '
- '"Testing Time!\\n")')
- data.append(" self.update_text('[name=\"preText2\"]', "
- "\"Typing Text!\")")
- data.append(' self.assert_text("Automation Practice", "h3")')
- data.append(' self.hover_and_click("#myDropdown", '
- '"#dropOption2")')
- data.append(' self.assert_text("Link Two Selected", "h3")')
- data.append(' self.assert_text("This Text is Green", "#pText")')
- data.append(' self.click("#myButton")')
- data.append(' self.assert_text("This Text is Purple", '
- '"#pText")')
- data.append(" self.assert_element('svg[name=\"svgName\"]')")
- data.append(" self.assert_element('progress[value=\"50\"]')")
- data.append(' self.press_right_arrow("#myslider", times=5)')
- data.append(" self.assert_element('progress[value=\"100\"]')")
- data.append(" self.assert_element('meter[value=\"0.25\"]')")
- data.append(' self.select_option_by_text("#mySelect", '
- '"Set to 75%")')
- data.append(" self.assert_element('meter[value=\"0.75\"]')")
- data.append(' self.assert_false(self.is_element_visible('
- '"img"))')
- data.append(' self.switch_to_frame("#myFrame1")')
- data.append(' self.assert_true(self.is_element_visible("img"))')
- data.append(' self.switch_to_default_content()')
- data.append(' self.assert_false(self.is_text_visible('
- '"iFrame Text"))')
- data.append(' self.switch_to_frame("#myFrame2")')
- data.append(' self.assert_true(self.is_text_visible('
- '"iFrame Text"))')
- data.append(' self.switch_to_default_content()')
- data.append(' self.assert_false(self.is_selected('
- '"#radioButton2"))')
- data.append(' self.click("#radioButton2")')
- data.append(' self.assert_true(self.is_selected('
- '"#radioButton2"))')
- data.append(' self.assert_false(self.is_selected('
- '"#checkBox1"))')
- data.append(' self.click("#checkBox1")')
- data.append(' self.assert_true(self.is_selected("#checkBox1"))')
- data.append(' self.assert_false(self.is_selected('
- '"#checkBox2"))')
- data.append(' self.assert_false(self.is_selected('
- '"#checkBox3"))')
- data.append(' self.assert_false(self.is_selected('
- '"#checkBox4"))')
- data.append(' self.click_visible_elements('
- '"input.checkBoxClassB")')
- data.append(' self.assert_true(self.is_selected("#checkBox2"))')
- data.append(' self.assert_true(self.is_selected("#checkBox3"))')
- data.append(' self.assert_true(self.is_selected("#checkBox4"))')
- data.append(' self.assert_false(self.is_element_visible('
- '".fBox"))')
- data.append(' self.switch_to_frame("#myFrame3")')
- data.append(' self.assert_true(self.is_element_visible('
- '".fBox"))')
- data.append(' self.assert_false(self.is_selected(".fBox"))')
- data.append(' self.click(".fBox")')
- data.append(' self.assert_true(self.is_selected(".fBox"))')
- data.append(' self.switch_to_default_content()')
- data.append(' self.assert_link_text("seleniumbase.com")')
- data.append(' self.assert_link_text("SeleniumBase on GitHub")')
- data.append(' self.assert_link_text("seleniumbase.io")')
- data.append(' self.click_link_text("SeleniumBase Demo Page")')
- data.append(' self.assert_exact_text("Demo Page", "h1")')
- data.append("")
- file_path = "%s/%s" % (dir_name, "test_demo_site.py")
- file = codecs.open(file_path, "w+", "utf-8")
- file.writelines("\r\n".join(data))
- file.close()
+ data = []
+ data.append("from seleniumbase import BaseCase")
+ data.append("")
+ data.append("")
+ data.append("class MyTestClass(BaseCase):")
+ data.append("")
+ data.append(" def test_demo_site(self):")
+ data.append(' self.open("https://seleniumbase.io/demo_page.html")')
+ data.append(' self.assert_title("Web Testing Page")')
+ data.append(' self.assert_element("tbody#tbodyId")')
+ data.append(' self.assert_text("Demo Page", "h1")')
+ data.append(' self.type("#myTextInput", "This is Automated")')
+ data.append(' self.type("textarea.area1", "Testing Time!\\n")')
+ data.append(" self.type('[name=\"preText2\"]', \"Typing Text!\")")
+ data.append(' self.assert_text("Automation Practice", "h3")')
+ data.append(' self.hover_and_click("#myDropdown", "#dropOption2")')
+ data.append(' self.assert_text("Link Two Selected", "h3")')
+ data.append(' self.assert_text("This Text is Green", "#pText")')
+ data.append(' self.click("#myButton")')
+ data.append(' self.assert_text("This Text is Purple", "#pText")')
+ data.append(" self.assert_element('svg[name=\"svgName\"]')")
+ data.append(" self.assert_element('progress[value=\"50\"]')")
+ data.append(' self.press_right_arrow("#myslider", times=5)')
+ data.append(" self.assert_element('progress[value=\"100\"]')")
+ data.append(" self.assert_element('meter[value=\"0.25\"]')")
+ data.append(' self.select_option_by_text("#mySelect", '
+ '"Set to 75%")')
+ data.append(" self.assert_element('meter[value=\"0.75\"]')")
+ data.append(' self.assert_false(self.is_element_visible("img"))')
+ data.append(' self.switch_to_frame("#myFrame1")')
+ data.append(' self.assert_true(self.is_element_visible("img"))')
+ data.append(' self.switch_to_default_content()')
+ data.append(' self.assert_false(self.is_text_visible('
+ '"iFrame Text"))')
+ data.append(' self.switch_to_frame("#myFrame2")')
+ data.append(' self.assert_true(self.is_text_visible('
+ '"iFrame Text"))')
+ data.append(' self.switch_to_default_content()')
+ data.append(' self.assert_false(self.is_selected("#radioButton2"))')
+ data.append(' self.click("#radioButton2")')
+ data.append(' self.assert_true(self.is_selected("#radioButton2"))')
+ data.append(' self.assert_false(self.is_selected("#checkBox1"))')
+ data.append(' self.click("#checkBox1")')
+ data.append(' self.assert_true(self.is_selected("#checkBox1"))')
+ data.append(' self.assert_false(self.is_selected("#checkBox2"))')
+ data.append(' self.assert_false(self.is_selected("#checkBox3"))')
+ data.append(' self.assert_false(self.is_selected("#checkBox4"))')
+ data.append(' self.click_visible_elements("input.checkBoxClassB")')
+ data.append(' self.assert_true(self.is_selected("#checkBox2"))')
+ data.append(' self.assert_true(self.is_selected("#checkBox3"))')
+ data.append(' self.assert_true(self.is_selected("#checkBox4"))')
+ data.append(' self.assert_false(self.is_element_visible(".fBox"))')
+ data.append(' self.switch_to_frame("#myFrame3")')
+ data.append(' self.assert_true(self.is_element_visible(".fBox"))')
+ data.append(' self.assert_false(self.is_selected(".fBox"))')
+ data.append(' self.click(".fBox")')
+ data.append(' self.assert_true(self.is_selected(".fBox"))')
+ data.append(' self.switch_to_default_content()')
+ data.append(' self.assert_link_text("seleniumbase.com")')
+ data.append(' self.assert_link_text("SeleniumBase on GitHub")')
+ data.append(' self.assert_link_text("seleniumbase.io")')
+ data.append(' self.click_link_text("SeleniumBase Demo Page")')
+ data.append(' self.assert_exact_text("Demo Page", "h1")')
+ data.append("")
+ file_path = "%s/%s" % (dir_name, "test_demo_site.py")
+ file = codecs.open(file_path, "w+", "utf-8")
+ file.writelines("\r\n".join(data))
+ file.close()
- data = []
- data.append("from seleniumbase import BaseCase")
- data.append("from parameterized import parameterized")
- data.append("")
- data.append("")
- data.append("class GoogleTestClass(BaseCase):")
- data.append("")
- data.append(" @parameterized.expand([")
- data.append(' ["pypi", "pypi.org"],')
- data.append(' ["wikipedia", "wikipedia.org"],')
- data.append(' ["seleniumbase", "seleniumbase/SeleniumBase"],')
- data.append(" ])")
- data.append(" def test_parameterized_google_search("
- "self, search_term, expected_text):")
- data.append(" self.open('https://google.com/ncr')")
- data.append(" self.update_text('input[title=\"Search\"]', "
- "search_term + '\\n')")
- data.append(" self.assert_element('#result-stats')")
- data.append(" self.assert_text(expected_text, '#search')")
- data.append("")
- file_path = "%s/%s" % (dir_name, "parameterized_test.py")
- file = codecs.open(file_path, "w+", "utf-8")
- file.writelines("\r\n".join(data))
- file.close()
+ data = []
+ data.append("from seleniumbase import BaseCase")
+ data.append("from parameterized import parameterized")
+ data.append("")
+ data.append("")
+ data.append("class GoogleTestClass(BaseCase):")
+ data.append("")
+ data.append(" @parameterized.expand([")
+ data.append(' ["pypi", "pypi.org"],')
+ data.append(' ["wikipedia", "wikipedia.org"],')
+ data.append(' ["seleniumbase", "seleniumbase/SeleniumBase"],')
+ data.append(" ])")
+ data.append(" def test_parameterized_google_search("
+ "self, search_term, expected_text):")
+ data.append(" self.open('https://google.com/ncr')")
+ data.append(" self.type('input[title=\"Search\"]', "
+ "search_term + '\\n')")
+ data.append(" self.assert_element('#result-stats')")
+ data.append(" self.assert_text(expected_text, '#search')")
+ data.append("")
+ file_path = "%s/%s" % (dir_name, "parameterized_test.py")
+ file = codecs.open(file_path, "w+", "utf-8")
+ file.writelines("\r\n".join(data))
+ file.close()
- dir_name_2 = dir_name + "/" + "boilerplates"
- os.mkdir(dir_name_2)
+ dir_name_2 = dir_name + "/" + "boilerplates"
+ os.mkdir(dir_name_2)
- data = []
- data.append("")
- file_path = "%s/%s" % (dir_name_2, "__init__.py")
- file = codecs.open(file_path, "w+", "utf-8")
- file.writelines("\r\n".join(data))
- file.close()
+ data = []
+ data.append("")
+ file_path = "%s/%s" % (dir_name_2, "__init__.py")
+ file = codecs.open(file_path, "w+", "utf-8")
+ file.writelines("\r\n".join(data))
+ file.close()
- data = []
- data.append("from seleniumbase import BaseCase")
- data.append("")
- data.append("")
- data.append("class BaseTestCase(BaseCase):")
- data.append("")
- data.append(" def setUp(self):")
- data.append(" super(BaseTestCase, self).setUp()")
- data.append(" # << Add custom code AFTER the super() line >>")
- data.append("")
- data.append(" def tearDown(self):")
- data.append(" self.save_teardown_screenshot()")
- data.append(" # << Add custom code BEFORE the super() line >>")
- data.append(" super(BaseTestCase, self).tearDown()")
- data.append("")
- data.append(" def login(self):")
- data.append(" # <<< Placeholder. Add your code here. >>>")
- data.append(" pass")
- data.append("")
- data.append(" def example_method(self):")
- data.append(" # <<< Placeholder. Add your code here. >>>")
- data.append(" pass")
- data.append("")
- file_path = "%s/%s" % (dir_name_2, "base_test_case.py")
- file = codecs.open(file_path, "w+", "utf-8")
- file.writelines("\r\n".join(data))
- file.close()
+ data = []
+ data.append("from seleniumbase import BaseCase")
+ data.append("")
+ data.append("")
+ data.append("class BaseTestCase(BaseCase):")
+ data.append("")
+ data.append(" def setUp(self):")
+ data.append(" super(BaseTestCase, self).setUp()")
+ data.append(" # << Add custom code AFTER the super() line >>")
+ data.append("")
+ data.append(" def tearDown(self):")
+ data.append(" self.save_teardown_screenshot()")
+ data.append(" # << Add custom code BEFORE the super() line >>")
+ data.append(" super(BaseTestCase, self).tearDown()")
+ data.append("")
+ data.append(" def login(self):")
+ data.append(" # <<< Placeholder. Add your code here. >>>")
+ data.append(" pass")
+ data.append("")
+ data.append(" def example_method(self):")
+ data.append(" # <<< Placeholder. Add your code here. >>>")
+ data.append(" pass")
+ data.append("")
+ file_path = "%s/%s" % (dir_name_2, "base_test_case.py")
+ file = codecs.open(file_path, "w+", "utf-8")
+ file.writelines("\r\n".join(data))
+ file.close()
- data = []
- data.append("class Page(object):")
- data.append(' html = "html"')
- data.append("")
- file_path = "%s/%s" % (dir_name_2, "page_objects.py")
- file = codecs.open(file_path, "w+", "utf-8")
- file.writelines("\r\n".join(data))
- file.close()
+ data = []
+ data.append("class Page(object):")
+ data.append(' html = "html"')
+ data.append("")
+ file_path = "%s/%s" % (dir_name_2, "page_objects.py")
+ file = codecs.open(file_path, "w+", "utf-8")
+ file.writelines("\r\n".join(data))
+ file.close()
- data = []
- data.append("from .base_test_case import BaseTestCase")
- data.append("from .page_objects import Page")
- data.append("")
- data.append("")
- data.append("class MyTestClass(BaseTestCase):")
- data.append("")
- data.append(" def test_boilerplate(self):")
- data.append(" self.login()")
- data.append(" self.example_method()")
- data.append(" self.assert_element(Page.html)")
- data.append("")
- file_path = "%s/%s" % (dir_name_2, "boilerplate_test.py")
- file = codecs.open(file_path, "w+", "utf-8")
- file.writelines("\r\n".join(data))
- file.close()
+ data = []
+ data.append("from .base_test_case import BaseTestCase")
+ data.append("from .page_objects import Page")
+ data.append("")
+ data.append("")
+ data.append("class MyTestClass(BaseTestCase):")
+ data.append("")
+ data.append(" def test_boilerplate(self):")
+ data.append(" self.login()")
+ data.append(" self.example_method()")
+ data.append(" self.assert_element(Page.html)")
+ data.append("")
+ file_path = "%s/%s" % (dir_name_2, "boilerplate_test.py")
+ file = codecs.open(file_path, "w+", "utf-8")
+ file.writelines("\r\n".join(data))
+ file.close()
- dir_name_3 = dir_name_2 + "/" + "samples"
- os.mkdir(dir_name_3)
+ dir_name_3 = dir_name_2 + "/" + "samples"
+ os.mkdir(dir_name_3)
- data = []
- data.append("")
- file_path = "%s/%s" % (dir_name_3, "__init__.py")
- file = codecs.open(file_path, "w+", "utf-8")
- file.writelines("\r\n".join(data))
- file.close()
+ data = []
+ data.append("")
+ file_path = "%s/%s" % (dir_name_3, "__init__.py")
+ file = codecs.open(file_path, "w+", "utf-8")
+ file.writelines("\r\n".join(data))
+ file.close()
- data = []
- data.append("from seleniumbase import BaseCase")
- data.append("from .google_objects import HomePage, ResultsPage")
- data.append("")
- data.append("")
- data.append("class GoogleTests(BaseCase):")
- data.append("")
- data.append(" def test_google_dot_com(self):")
- data.append(" self.open('https://google.com/ncr')")
- data.append(
- " self.update_text(HomePage.search_box, 'github')")
- data.append(" self.assert_element(HomePage.list_box)")
- data.append(" self.assert_element(HomePage.search_button)")
- data.append(
- " self.assert_element(HomePage.feeling_lucky_button)")
- data.append(" self.click(HomePage.search_button)")
- data.append(
- " self.assert_text('github.com', "
- "ResultsPage.search_results)")
- data.append(" self.assert_element(ResultsPage.images_link)")
- data.append("")
- file_path = "%s/%s" % (dir_name_3, "google_test.py")
- file = codecs.open(file_path, "w+", "utf-8")
- file.writelines("\r\n".join(data))
- file.close()
+ data = []
+ data.append("from seleniumbase import BaseCase")
+ data.append("from .google_objects import HomePage, ResultsPage")
+ data.append("")
+ data.append("")
+ data.append("class GoogleTests(BaseCase):")
+ data.append("")
+ data.append(" def test_google_dot_com(self):")
+ data.append(" self.open('https://google.com/ncr')")
+ data.append(" self.type(HomePage.search_box, 'github')")
+ data.append(" self.assert_element(HomePage.list_box)")
+ data.append(" self.assert_element(HomePage.search_button)")
+ data.append(
+ " self.assert_element(HomePage.feeling_lucky_button)")
+ data.append(" self.click(HomePage.search_button)")
+ data.append(
+ " self.assert_text('github.com', "
+ "ResultsPage.search_results)")
+ data.append(" self.assert_element(ResultsPage.images_link)")
+ data.append("")
+ file_path = "%s/%s" % (dir_name_3, "google_test.py")
+ file = codecs.open(file_path, "w+", "utf-8")
+ file.writelines("\r\n".join(data))
+ file.close()
- data = []
- data.append("class HomePage(object):")
- data.append(" dialog_box = '[role=\"dialog\"] div'")
- data.append(" search_box = 'input[title=\"Search\"]'")
- data.append(" list_box = '[role=\"listbox\"]'")
- data.append(" search_button = 'input[value=\"Google Search\"]'")
- data.append(
- " feeling_lucky_button = "
- "'''input[value=\"I'm Feeling Lucky\"]'''")
- data.append("")
- data.append("")
- data.append("class ResultsPage(object):")
- data.append(" google_logo = 'img[alt=\"Google\"]'")
- data.append(" images_link = 'link=Images'")
- data.append(" search_results = 'div#center_col'")
- data.append("")
- file_path = "%s/%s" % (dir_name_3, "google_objects.py")
- file = codecs.open(file_path, "w+", "utf-8")
- file.writelines("\r\n".join(data))
- file.close()
- print('''\n* Directory "%s" was created with config files '''
- '''and sample tests! *\n''' % dir_name)
+ data = []
+ data.append("class HomePage(object):")
+ data.append(" dialog_box = '[role=\"dialog\"] div'")
+ data.append(" search_box = 'input[title=\"Search\"]'")
+ data.append(" list_box = '[role=\"listbox\"]'")
+ data.append(" search_button = 'input[value=\"Google Search\"]'")
+ data.append(
+ " feeling_lucky_button = "
+ "'''input[value=\"I'm Feeling Lucky\"]'''")
+ data.append("")
+ data.append("")
+ data.append("class ResultsPage(object):")
+ data.append(" google_logo = 'img[alt=\"Google\"]'")
+ data.append(" images_link = 'link=Images'")
+ data.append(" search_results = 'div#center_col'")
+ data.append("")
+ file_path = "%s/%s" % (dir_name_3, "google_objects.py")
+ file = codecs.open(file_path, "w+", "utf-8")
+ file.writelines("\r\n".join(data))
+ file.close()
+ print('''\n* Directory "%s" was created with config files '''
+ '''and sample tests! *\n''' % dir_name)
if __name__ == "__main__":
- main()
+ invalid_run_command()
diff --git a/seleniumbase/console_scripts/sb_mkfile.py b/seleniumbase/console_scripts/sb_mkfile.py
new file mode 100755
index 00000000000..92a78b02a5c
--- /dev/null
+++ b/seleniumbase/console_scripts/sb_mkfile.py
@@ -0,0 +1,265 @@
+# -*- coding: utf-8 -*-
+"""
+Creates a new SeleniumBase test file with boilerplate code.
+
+Usage:
+ seleniumbase mkfile [FILE_NAME.py] [OPTIONS]
+ or sbase mkfile [FILE_NAME.py] [OPTIONS]
+
+Example:
+ sbase mkfile new_test.py
+
+Options:
+ -b / --basic (Basic boilerplate / single-line test)
+
+Language Options:
+ --en / --English | --zh / --Chinese
+ --nl / --Dutch | --fr / --French
+ --it / --Italian | --ja / --Japanese
+ --ko / --Korean | --pt / --Portuguese
+ --ru / --Russian | --es / --Spanish
+
+Output:
+ Creates a new SBase test file with boilerplate code.
+ If the file already exists, an error is raised.
+ By default, uses English mode and creates a
+ boilerplate with the 5 most common SeleniumBase
+ methods, which are "open", "click", "update_text",
+ "assert_element", and "assert_text". If using the
+ basic boilerplate option, only the "open" method
+ is included.
+"""
+
+import codecs
+import colorama
+import os
+import sys
+
+
+def invalid_run_command(msg=None):
+ exp = (" ** mkfile **\n\n")
+ exp += " Usage:\n"
+ exp += " seleniumbase mkfile [FILE_NAME.py] [OPTIONS]\n"
+ exp += " OR sbase mkfile [FILE_NAME.py] [OPTIONS]\n"
+ exp += " Example:\n"
+ exp += " sbase mkfile new_test.py\n"
+ exp += " Options:\n"
+ exp += " -b / --basic (Basic boilerplate / single-line test)\n"
+ exp += " Language Options:\n"
+ exp += " --en / --English | --zh / --Chinese\n"
+ exp += " --nl / --Dutch | --fr / --French\n"
+ exp += " --it / --Italian | --ja / --Japanese\n"
+ exp += " --ko / --Korean | --pt / --Portuguese\n"
+ exp += " --ru / --Russian | --es / --Spanish\n"
+ exp += " Output:\n"
+ exp += " Creates a new SBase test file with boilerplate code.\n"
+ exp += " If the file already exists, an error is raised.\n"
+ exp += " By default, uses English mode and creates a\n"
+ exp += " boilerplate with the 5 most common SeleniumBase\n"
+ exp += ' methods, which are "open", "click", "update_text",\n'
+ exp += ' "assert_element", and "assert_text". If using the\n'
+ exp += ' basic boilerplate option, only the "open" method\n'
+ exp += ' is included.\n'
+ if not msg:
+ raise Exception('INVALID RUN COMMAND!\n\n%s' % exp)
+ else:
+ raise Exception('INVALID RUN COMMAND!\n\n%s\n%s\n' % (exp, msg))
+
+
+def main():
+ colorama.init(autoreset=True)
+ c1 = colorama.Fore.BLUE + colorama.Back.LIGHTCYAN_EX
+ c5 = colorama.Fore.RED + colorama.Back.LIGHTYELLOW_EX
+ c7 = colorama.Fore.BLACK + colorama.Back.MAGENTA
+ cr = colorama.Style.RESET_ALL
+ basic = False
+ help_me = False
+ error_msg = None
+ invalid_cmd = None
+ language = "English"
+
+ command_args = sys.argv[2:]
+ file_name = command_args[0]
+ if not file_name.endswith(".py"):
+ error_msg = 'File Name must end with ".py"!'
+ elif "*" in file_name or len(str(file_name)) < 4:
+ error_msg = 'Invalid File Name!'
+ elif "/" in str(file_name) or "\\" in str(file_name):
+ error_msg = 'File must be created in the current directory!'
+ elif os.path.exists(os.getcwd() + '/' + file_name):
+ error_msg = (
+ 'File "%s" already exists in the current path!' % file_name)
+ if error_msg:
+ error_msg = c5 + error_msg + cr
+ invalid_run_command(error_msg)
+
+ if len(command_args) >= 2:
+ options = command_args[1:]
+ for option in options:
+ option = option.lower()
+ if option == "help" or option == "--help":
+ help_me = True
+ elif option == "-b" or option == "--basic":
+ basic = True
+ elif option == "--en" or option == "--english":
+ language = "English"
+ elif option == "--zh" or option == "--chinese":
+ language = "Chinese"
+ elif option == "--nl" or option == "--dutch":
+ language = "Dutch"
+ elif option == "--fr" or option == "--french":
+ language = "French"
+ elif option == "--it" or option == "--italian":
+ language = "Italian"
+ elif option == "--ja" or option == "--japanese":
+ language = "Japanese"
+ elif option == "--ko" or option == "--korean":
+ language = "Korean"
+ elif option == "--pt" or option == "--portuguese":
+ language = "Portuguese"
+ elif option == "--ru" or option == "--russian":
+ language = "Russian"
+ elif option == "--es" or option == "--spanish":
+ language = "Spanish"
+ else:
+ invalid_cmd = "\n===> INVALID OPTION: >> %s <<\n" % option
+ invalid_cmd = invalid_cmd.replace('>> ', ">>" + c5 + " ")
+ invalid_cmd = invalid_cmd.replace(' <<', " " + cr + "<<")
+ invalid_cmd = invalid_cmd.replace('>>', c7 + ">>" + cr)
+ invalid_cmd = invalid_cmd.replace('<<', c7 + "<<" + cr)
+ help_me = True
+ break
+ if help_me:
+ invalid_run_command(invalid_cmd)
+
+ if language != "English" and sys.version_info[0] == 2:
+ print("")
+ msg = 'Multi-language support for "sbase mkfile" '
+ msg += 'is not available on Python 2!'
+ msg = "\n" + c5 + msg + cr
+ msg += '\nPlease run in "English" mode or upgrade to Python 3!\n'
+ raise Exception(msg)
+
+ dir_name = os.getcwd()
+ file_path = "%s/%s" % (dir_name, file_name)
+
+ body = "html > body"
+ para = "body p"
+ hello = "Hello"
+ goodbye = "Goodbye"
+ class_name = "MyTestClass"
+ if language == "Chinese":
+ hello = "你好"
+ goodbye = "再见"
+ class_name = "我的测试类"
+ elif language == "Dutch":
+ hello = "Hallo"
+ goodbye = "Dag"
+ class_name = "MijnTestklasse"
+ elif language == "French":
+ hello = "Bonjour"
+ goodbye = "Au revoir"
+ class_name = "MaClasseDeTest"
+ elif language == "Italian":
+ hello = "Ciao"
+ goodbye = "Addio"
+ class_name = "MiaClasseDiTest"
+ elif language == "Japanese":
+ hello = "こんにちは"
+ goodbye = "さようなら"
+ class_name = "私のテストクラス"
+ elif language == "Korean":
+ hello = "여보세요"
+ goodbye = "안녕"
+ class_name = "테스트_클래스"
+ elif language == "Portuguese":
+ hello = "Olá"
+ goodbye = "Tchau"
+ class_name = "MinhaClasseDeTeste"
+ elif language == "Russian":
+ hello = "Привет"
+ goodbye = "До свидания"
+ class_name = "МойТестовыйКласс"
+ elif language == "Spanish":
+ hello = "Hola"
+ goodbye = "Adiós"
+ class_name = "MiClaseDePrueba"
+ url = ""
+ if basic:
+ url = "about:blank"
+ elif language not in ["English", "Dutch", "French", "Italian"]:
+ url = "data:text/html,%s " % hello
+ else:
+ url = "data:text/html,
%s
" % hello
+
+ import_line = "from seleniumbase import BaseCase"
+ parent_class = "BaseCase"
+ class_line = "class MyTestClass(BaseCase):"
+ if language != "English":
+ from seleniumbase.translate.master_dict import MD_F
+ import_line = MD_F.get_import_line(language)
+ parent_class = MD_F.get_lang_parent_class(language)
+ class_line = "class %s(%s):" % (class_name, parent_class)
+
+ data = []
+ data.append("%s" % import_line)
+ data.append("")
+ data.append("")
+ data.append("%s" % class_line)
+ data.append("")
+ data.append(" def test_base(self):")
+ data.append(' self.open("%s")' % url)
+ if not basic:
+ data.append(' self.assert_element("%s") # selector' % body)
+ data.append(' self.assert_text("%s", "%s")'
+ ' # text, selector' % (hello, para))
+ data.append(' self.type("input", "%s")'
+ ' # selector, text' % goodbye)
+ data.append(' self.click("%s") # selector' % para)
+ data.append("")
+
+ new_data = []
+ if language == "English":
+ new_data = data
+ else:
+ from seleniumbase.translate.master_dict import MD
+ from seleniumbase.translate.master_dict import MD_L_Codes
+ md = MD.md
+ lang_codes = MD_L_Codes.lang
+ nl_code = lang_codes[language]
+ dl_code = lang_codes["English"]
+ for line in data:
+ found_swap = False
+ replace_count = line.count("self.") # Total possible replacements
+ for key in md.keys():
+ original = "self." + md[key][dl_code] + "("
+ if original in line:
+ replacement = "self." + md[key][nl_code] + "("
+ new_line = line.replace(original, replacement)
+ found_swap = True
+ replace_count -= 1
+ if replace_count == 0:
+ break # Done making replacements
+ else:
+ # There might be another method to replace in the line.
+ # Example: self.assert_true("Name" in self.get_title())
+ line = new_line
+ continue
+ if found_swap:
+ if new_line.endswith(" # noqa"): # Remove flake8 skip
+ new_line = new_line[0:-len(" # noqa")]
+ new_data.append(new_line)
+ continue
+ new_data.append(line)
+ data = new_data
+ file = codecs.open(file_path, "w+", "utf-8")
+ file.writelines("\r\n".join(data))
+ file.close()
+ success = (
+ '\n' + c1 + '* Test file: "' + file_name + '" was created! *'
+ '' + cr + '\n')
+ print(success)
+
+
+if __name__ == "__main__":
+ invalid_run_command()
diff --git a/seleniumbase/console_scripts/sb_print.py b/seleniumbase/console_scripts/sb_print.py
index a9fb85771b6..80476ffbbde 100755
--- a/seleniumbase/console_scripts/sb_print.py
+++ b/seleniumbase/console_scripts/sb_print.py
@@ -37,19 +37,9 @@ def invalid_run_command(msg=None):
def sc_ranges():
# Get the ranges of special characters of Chinese, Japanese, and Korean.
special_char_ranges = ([
- {"from": ord(u"\u3300"), "to": ord(u"\u33ff")},
- {"from": ord(u"\ufe30"), "to": ord(u"\ufe4f")},
- {"from": ord(u"\uf900"), "to": ord(u"\ufaff")},
- {"from": ord(u"\U0002F800"), "to": ord(u"\U0002fa1f")},
- {'from': ord(u'\u3040'), 'to': ord(u'\u309f')},
- {"from": ord(u"\u30a0"), "to": ord(u"\u30ff")},
- {"from": ord(u"\u2e80"), "to": ord(u"\u2eff")},
- {"from": ord(u"\u4e00"), "to": ord(u"\u9fff")},
- {"from": ord(u"\u3400"), "to": ord(u"\u4dbf")},
- {"from": ord(u"\U00020000"), "to": ord(u"\U0002a6df")},
- {"from": ord(u"\U0002a700"), "to": ord(u"\U0002b73f")},
- {"from": ord(u"\U0002b740"), "to": ord(u"\U0002b81f")},
- {"from": ord(u"\U0002b820"), "to": ord(u"\U0002ceaf")}
+ {"from": ord(u"\u4e00"), "to": ord(u"\u9FFF")},
+ {"from": ord(u"\u3040"), "to": ord(u"\u30ff")},
+ {"from": ord(u"\uac00"), "to": ord(u"\ud7a3")}
])
return special_char_ranges
@@ -165,6 +155,8 @@ def main():
if is_python_file:
new_sb_lines = []
for line in code_lines:
+ if line.endswith(" # noqa") and line.count(" # noqa") == 1:
+ line = line.replace(" # noqa", "")
line_length2 = len(line) # Normal Python string length used
line_length = get_width(line) # Special characters count 2X
if line_length > code_width:
@@ -254,6 +246,54 @@ def main():
else:
new_sb_lines.append(line)
continue
+ elif line.count('("') == 1:
+ whitespace = line_length2 - len(line.lstrip())
+ new_ws = line[0:whitespace] + " "
+ line1 = line.split('("')[0] + '('
+ line2 = new_ws + '"' + line.split('("')[1]
+ if not ('):') in line2:
+ new_sb_lines.append(line1)
+ if get_width(line2) + w > console_width:
+ if line2.count('" in self.') == 1:
+ line2a = line2.split(
+ '" in self.')[0] + '" in'
+ line2b = new_ws + "self." + (
+ line2.split('" in self.')[1])
+ new_sb_lines.append(line2a)
+ new_sb_lines.append(line2b)
+ continue
+ new_sb_lines.append(line2)
+ elif get_width(line2) + 4 + w <= console_width:
+ line2 = " " + line2
+ new_sb_lines.append(line1)
+ new_sb_lines.append(line2)
+ else:
+ new_sb_lines.append(line)
+ continue
+ elif line.count("('") == 1:
+ whitespace = line_length2 - len(line.lstrip())
+ new_ws = line[0:whitespace] + " "
+ line1 = line.split("('")[0] + '('
+ line2 = new_ws + "'" + line.split("('")[1]
+ if not ('):') in line2:
+ new_sb_lines.append(line1)
+ if get_width(line2) + w > console_width:
+ if line2.count("' in self.") == 1:
+ line2a = line2.split(
+ "' in self.")[0] + "' in"
+ line2b = new_ws + "self." + (
+ line2.split("' in self.")[1])
+ new_sb_lines.append(line2a)
+ new_sb_lines.append(line2b)
+ continue
+ new_sb_lines.append(line2)
+ elif get_width(line2) + 4 + w <= console_width:
+ line2 = " " + line2
+ new_sb_lines.append(line1)
+ new_sb_lines.append(line2)
+ else:
+ new_sb_lines.append(line)
+ continue
elif line.count('= "') == 1 and line.count('://') == 1:
whitespace = line_length2 - len(line.lstrip())
new_ws = line[0:whitespace] + " "
diff --git a/seleniumbase/core/browser_launcher.py b/seleniumbase/core/browser_launcher.py
index 7e3c36f29f2..f4c6f87bce4 100755
--- a/seleniumbase/core/browser_launcher.py
+++ b/seleniumbase/core/browser_launcher.py
@@ -4,7 +4,6 @@
import random
import re
import sys
-import threading
import time
import urllib3
import warnings
@@ -15,7 +14,6 @@
from seleniumbase.config import settings
from seleniumbase.core import download_helper
from seleniumbase.core import proxy_helper
-from seleniumbase.core import capabilities_parser
from seleniumbase.fixtures import constants
from seleniumbase.fixtures import page_utils
from seleniumbase import drivers # webdriver storage folder for SeleniumBase
@@ -106,6 +104,7 @@ def _add_chrome_proxy_extension(
proxy_helper.create_proxy_zip(proxy_string, proxy_user, proxy_pass)
else:
# Pytest multi-threaded test
+ import threading
lock = threading.Lock()
with lock:
time.sleep(random.uniform(0.02, 0.15))
@@ -421,6 +420,7 @@ def get_remote_driver(
desired_caps = {}
extra_caps = {}
if cap_file:
+ from seleniumbase.core import capabilities_parser
desired_caps = capabilities_parser.get_desired_capabilities(cap_file)
if cap_string:
try:
diff --git a/seleniumbase/fixtures/base_case.py b/seleniumbase/fixtures/base_case.py
index e76fb1cf3c1..17d2fa7bf1e 100755
--- a/seleniumbase/fixtures/base_case.py
+++ b/seleniumbase/fixtures/base_case.py
@@ -11,7 +11,7 @@ class MyTestClass(BaseCase):
def test_anything(self):
# Write your code here. Example:
self.open("https://github.com/")
- self.update_text("input.header-search-input", "SeleniumBase\n")
+ self.type("input.header-search-input", "SeleniumBase\n")
self.click('a[href="/seleniumbase/SeleniumBase"]')
self.assert_element("div.repository-content")
....
@@ -32,7 +32,6 @@ def test_anything(self):
import time
import urllib3
import unittest
-import uuid
from selenium.common.exceptions import (StaleElementReferenceException,
MoveTargetOutOfBoundsException,
WebDriverException)
@@ -40,17 +39,11 @@ def test_anything(self):
from selenium.webdriver.common.by import By
from selenium.webdriver.common.keys import Keys
from selenium.webdriver.remote.remote_connection import LOGGER
-from selenium.webdriver.support.ui import Select
from seleniumbase import config as sb_config
from seleniumbase.common import decorators
from seleniumbase.config import settings
-from seleniumbase.core.testcase_manager import TestcaseDataPayload
-from seleniumbase.core.testcase_manager import TestcaseManager
-from seleniumbase.core import download_helper
from seleniumbase.core import log_helper
-from seleniumbase.core import settings_parser
from seleniumbase.core import tour_helper
-from seleniumbase.core import visual_helper
from seleniumbase.fixtures import constants
from seleniumbase.fixtures import js_utils
from seleniumbase.fixtures import page_actions
@@ -89,6 +82,7 @@ def __init__(self, *args, **kwargs):
self.__device_height = None
self.__device_pixel_ratio = None
# Requires self._* instead of self.__* for external class use
+ self._language = "English"
self._html_report_extra = [] # (Used by pytest_plugin.py)
self._default_driver = None
self._drivers_list = []
@@ -252,7 +246,7 @@ def click_chain(self, selectors_list, by=By.CSS_SELECTOR,
if spacing > 0:
time.sleep(spacing)
- def update_text(self, selector, new_value, by=By.CSS_SELECTOR,
+ def update_text(self, selector, text, by=By.CSS_SELECTOR,
timeout=None, retry=False):
""" This method updates an element's text field with new text.
Has multiple parts:
@@ -263,7 +257,7 @@ def update_text(self, selector, new_value, by=By.CSS_SELECTOR,
* Hits Enter/Submit (if the text ends in "\n").
@Params
selector - the selector of the text field
- new_value - the new value to type into the text field
+ text - the new text to type into the text field
by - the type of selector to search by (Default: CSS Selector)
timeout - how long to wait for the selector to be visible
retry - if True, use JS if the Selenium text update fails
@@ -293,16 +287,15 @@ def update_text(self, selector, new_value, by=By.CSS_SELECTOR,
pass # Clearing the text field first isn't critical
self.__demo_mode_pause_if_active(tiny=True)
pre_action_url = self.driver.current_url
- if type(new_value) is int or type(new_value) is float:
- new_value = str(new_value)
+ if type(text) is int or type(text) is float:
+ text = str(text)
try:
- if not new_value.endswith('\n'):
- element.send_keys(new_value)
+ if not text.endswith('\n'):
+ element.send_keys(text)
if settings.WAIT_FOR_RSC_ON_PAGE_LOADS:
self.wait_for_ready_state_complete()
else:
- new_value = new_value[:-1]
- element.send_keys(new_value)
+ element.send_keys(text[:-1])
element.send_keys(Keys.RETURN)
if settings.WAIT_FOR_RSC_ON_PAGE_LOADS:
self.wait_for_ready_state_complete()
@@ -312,21 +305,20 @@ def update_text(self, selector, new_value, by=By.CSS_SELECTOR,
element = self.wait_for_element_visible(
selector, by=by, timeout=timeout)
element.clear()
- if not new_value.endswith('\n'):
- element.send_keys(new_value)
+ if not text.endswith('\n'):
+ element.send_keys(text)
else:
- new_value = new_value[:-1]
- element.send_keys(new_value)
+ element.send_keys(text[:-1])
element.send_keys(Keys.RETURN)
if settings.WAIT_FOR_RSC_ON_PAGE_LOADS:
self.wait_for_ready_state_complete()
except Exception:
exc_message = self.__get_improved_exception_message()
raise Exception(exc_message)
- if (retry and element.get_attribute('value') != new_value and (
- not new_value.endswith('\n'))):
+ if (retry and element.get_attribute('value') != text and (
+ not text.endswith('\n'))):
logging.debug('update_text() is falling back to JavaScript!')
- self.set_value(selector, new_value, by=by)
+ self.set_value(selector, text, by=by)
if self.demo_mode:
if self.driver.current_url != pre_action_url:
self.__demo_mode_pause_if_active()
@@ -353,8 +345,7 @@ def add_text(self, selector, text, by=By.CSS_SELECTOR, timeout=None):
if not text.endswith('\n'):
element.send_keys(text)
else:
- text = text[:-1]
- element.send_keys(text)
+ element.send_keys(text[:-1])
element.send_keys(Keys.RETURN)
if settings.WAIT_FOR_RSC_ON_PAGE_LOADS:
self.wait_for_ready_state_complete()
@@ -366,8 +357,7 @@ def add_text(self, selector, text, by=By.CSS_SELECTOR, timeout=None):
if not text.endswith('\n'):
element.send_keys(text)
else:
- text = text[:-1]
- element.send_keys(text)
+ element.send_keys(text[:-1])
element.send_keys(Keys.RETURN)
if settings.WAIT_FOR_RSC_ON_PAGE_LOADS:
self.wait_for_ready_state_complete()
@@ -382,6 +372,31 @@ def add_text(self, selector, text, by=By.CSS_SELECTOR, timeout=None):
elif self.slow_mode:
self.__slow_mode_pause_if_active()
+ def type(self, selector, text, by=By.CSS_SELECTOR,
+ timeout=None, retry=False):
+ """ Same as self.update_text()
+ This method updates an element's text field with new text.
+ Has multiple parts:
+ * Waits for the element to be visible.
+ * Waits for the element to be interactive.
+ * Clears the text field.
+ * Types in the new text.
+ * Hits Enter/Submit (if the text ends in "\n").
+ @Params
+ selector - the selector of the text field
+ text - the new text to type into the text field
+ by - the type of selector to search by (Default: CSS Selector)
+ timeout - how long to wait for the selector to be visible
+ retry - if True, use JS if the Selenium text update fails
+ DO NOT confuse self.type() with Python type()! They are different!
+ """
+ if not timeout:
+ timeout = settings.LARGE_TIMEOUT
+ if self.timeout_multiplier and timeout == settings.LARGE_TIMEOUT:
+ timeout = self.__get_new_timeout(timeout)
+ selector, by = self.__recalculate_selector(selector, by)
+ self.update_text(selector, text, by=by, timeout=timeout, retry=retry)
+
def submit(self, selector, by=By.CSS_SELECTOR):
""" Alternative to self.driver.find_element_by_*(SELECTOR).submit() """
selector, by = self.__recalculate_selector(selector, by)
@@ -1281,6 +1296,7 @@ def __select_option(self, dropdown_selector, option,
""" Selects an HTML option by specification.
Option specifications are by "text", "index", or "value".
Defaults to "text" if option_by is unspecified or unknown. """
+ from selenium.webdriver.support.ui import Select
if not timeout:
timeout = settings.SMALL_TIMEOUT
if self.timeout_multiplier and timeout == settings.SMALL_TIMEOUT:
@@ -1947,11 +1963,11 @@ def highlight_click(self, selector, by=By.CSS_SELECTOR,
self.highlight(selector, by=by, loops=loops, scroll=scroll)
self.click(selector, by=by)
- def highlight_update_text(self, selector, new_value, by=By.CSS_SELECTOR,
+ def highlight_update_text(self, selector, text, by=By.CSS_SELECTOR,
loops=3, scroll=True):
if not self.demo_mode:
self.highlight(selector, by=by, loops=loops, scroll=scroll)
- self.update_text(selector, new_value, by=by)
+ self.update_text(selector, text, by=by)
def highlight(self, selector, by=By.CSS_SELECTOR,
loops=None, scroll=True):
@@ -2347,7 +2363,11 @@ def assert_no_404_errors(self, multithreaded=True):
for link in links:
self.assert_link_status_code_is_not_404(link)
if self.demo_mode:
- messenger_post = ("ASSERT NO 404 ERRORS")
+ a_t = "ASSERT NO 404 ERRORS"
+ if self._language != "English":
+ from seleniumbase.fixtures.words import SD
+ a_t = SD.translate_assert_no_404_errors(self._language)
+ messenger_post = ("%s" % a_t)
self.__highlight_with_assert_success(messenger_post, "html")
def print_unique_links_with_status_codes(self):
@@ -2563,6 +2583,7 @@ def save_data_as(self, data, file_name, destination_folder=None):
def get_downloads_folder(self):
""" Returns the OS path of the Downloads Folder.
(Works with Chrome and Firefox only, for now.) """
+ from seleniumbase.core import download_helper
return download_helper.get_downloads_folder()
def get_path_of_downloaded_file(self, file):
@@ -2647,7 +2668,11 @@ def assert_title(self, title):
"does not match the actual page title [%s]!"
"" % (expected, actual))
if self.demo_mode:
- messenger_post = ("ASSERT TITLE = {%s}" % title)
+ a_t = "ASSERT TITLE"
+ if self._language != "English":
+ from seleniumbase.fixtures.words import SD
+ a_t = SD.translate_assert_title(self._language)
+ messenger_post = ("%s: {%s}" % (a_t, title))
self.__highlight_with_assert_success(messenger_post, "html")
def assert_no_js_errors(self):
@@ -2678,7 +2703,11 @@ def assert_no_js_errors(self):
"JavaScript errors found on %s => %s" % (current_url, errors))
if self.demo_mode:
if (self.browser == 'chrome' or self.browser == 'edge'):
- messenger_post = ("ASSERT NO JS ERRORS")
+ a_t = "ASSERT NO JS ERRORS"
+ if self._language != "English":
+ from seleniumbase.fixtures.words import SD
+ a_t = SD.translate_assert_no_js_errors(self._language)
+ messenger_post = ("%s" % a_t)
self.__highlight_with_assert_success(messenger_post, "html")
def __activate_html_inspector(self):
@@ -2783,7 +2812,7 @@ def convert_to_css_selector(self, selector, by):
"Exception: Could not convert {%s}(by=%s) to CSS_SELECTOR!" % (
selector, by))
- def set_value(self, selector, new_value, by=By.CSS_SELECTOR, timeout=None):
+ def set_value(self, selector, text, by=By.CSS_SELECTOR, timeout=None):
""" This method uses JavaScript to update a text field. """
if not timeout:
timeout = settings.LARGE_TIMEOUT
@@ -2795,14 +2824,16 @@ def set_value(self, selector, new_value, by=By.CSS_SELECTOR, timeout=None):
self.__demo_mode_highlight_if_active(orginal_selector, by)
if not self.demo_mode:
self.scroll_to(orginal_selector, by=by, timeout=timeout)
- value = re.escape(new_value)
+ if type(text) is int or type(text) is float:
+ text = str(text)
+ value = re.escape(text)
value = self.__escape_quotes_if_needed(value)
css_selector = re.escape(css_selector)
css_selector = self.__escape_quotes_if_needed(css_selector)
script = ("""document.querySelector('%s').value='%s';"""
% (css_selector, value))
self.execute_script(script)
- if new_value.endswith('\n'):
+ if text.endswith('\n'):
element = self.wait_for_element_present(
orginal_selector, by=by, timeout=timeout)
element.send_keys(Keys.RETURN)
@@ -2810,21 +2841,60 @@ def set_value(self, selector, new_value, by=By.CSS_SELECTOR, timeout=None):
self.wait_for_ready_state_complete()
self.__demo_mode_pause_if_active()
- def js_update_text(self, selector, new_value, by=By.CSS_SELECTOR,
+ def js_update_text(self, selector, text, by=By.CSS_SELECTOR,
timeout=None):
- """ Same as self.set_value() """
+ """ JavaScript + send_keys are used to update a text field.
+ Performs self.set_value() and triggers event listeners.
+ If text ends in "\n", set_value() presses RETURN after.
+ Works faster than send_keys() alone due to the JS call.
+ """
if not timeout:
timeout = settings.LARGE_TIMEOUT
if self.timeout_multiplier and timeout == settings.LARGE_TIMEOUT:
timeout = self.__get_new_timeout(timeout)
+ selector, by = self.__recalculate_selector(selector, by)
+ if type(text) is int or type(text) is float:
+ text = str(text)
self.set_value(
- selector, new_value, by=by, timeout=timeout)
+ selector, text, by=by, timeout=timeout)
+ if not text.endswith('\n'):
+ try:
+ element = page_actions.wait_for_element_present(
+ self.driver, selector, by, timeout=0.2)
+ element.send_keys(" \b")
+ except Exception:
+ pass
- def jquery_update_text(self, selector, new_value, by=By.CSS_SELECTOR,
+ def js_type(self, selector, text, by=By.CSS_SELECTOR,
+ timeout=None):
+ """ Same as self.js_update_text()
+ JavaScript + send_keys are used to update a text field.
+ Performs self.set_value() and triggers event listeners.
+ If text ends in "\n", set_value() presses RETURN after.
+ Works faster than send_keys() alone due to the JS call.
+ """
+ if not timeout:
+ timeout = settings.LARGE_TIMEOUT
+ if self.timeout_multiplier and timeout == settings.LARGE_TIMEOUT:
+ timeout = self.__get_new_timeout(timeout)
+ selector, by = self.__recalculate_selector(selector, by)
+ if type(text) is int or type(text) is float:
+ text = str(text)
+ self.set_value(
+ selector, text, by=by, timeout=timeout)
+ if not text.endswith('\n'):
+ try:
+ element = page_actions.wait_for_element_present(
+ self.driver, selector, by, timeout=0.2)
+ element.send_keys(" \b")
+ except Exception:
+ pass
+
+ def jquery_update_text(self, selector, text, by=By.CSS_SELECTOR,
timeout=None):
""" This method uses jQuery to update a text field.
- If the new_value string ends with the newline character,
- WebDriver will finish the call, which simulates pressing
+ If the text string ends with the newline character,
+ Selenium finishes the call, which simulates pressing
{Enter/Return} after the text is entered. """
if not timeout:
timeout = settings.LARGE_TIMEOUT
@@ -2838,12 +2908,12 @@ def jquery_update_text(self, selector, new_value, by=By.CSS_SELECTOR,
selector = self.convert_to_css_selector(selector, by=by)
selector = self.__make_css_match_first_element_only(selector)
selector = self.__escape_quotes_if_needed(selector)
- new_value = re.escape(new_value)
- new_value = self.__escape_quotes_if_needed(new_value)
+ text = re.escape(text)
+ text = self.__escape_quotes_if_needed(text)
update_text_script = """jQuery('%s').val('%s')""" % (
- selector, new_value)
+ selector, text)
self.safe_execute_script(update_text_script)
- if new_value.endswith('\n'):
+ if text.endswith('\n'):
element.send_keys('\n')
self.__demo_mode_pause_if_active()
@@ -2936,46 +3006,36 @@ def get_session_storage_items(self):
# Duplicates (Avoids name confusion when migrating from other frameworks.)
def open_url(self, url):
- """ Same as open() - Original saved for backwards compatibility. """
+ """ Same as self.open() """
self.open(url)
def visit(self, url):
- """ Same as open() - Some test frameworks use this method name. """
+ """ Same as self.open() """
self.open(url)
def visit_url(self, url):
- """ Same as open() - Some test frameworks use this method name. """
+ """ Same as self.open() """
self.open(url)
def goto(self, url):
- """ Same as open() - Some test frameworks use this method name. """
+ """ Same as self.open() """
self.open(url)
def go_to(self, url):
- """ Same as open() - Some test frameworks use this method name. """
+ """ Same as self.open() """
self.open(url)
def reload(self):
- """ Same as refresh_page() """
+ """ Same as self.refresh_page() """
self.refresh_page()
def reload_page(self):
- """ Same as refresh_page() """
+ """ Same as self.refresh_page() """
self.refresh_page()
- def type(self, selector, text, by=By.CSS_SELECTOR,
- timeout=None, retry=False):
- """ Same as update_text() """
- if not timeout:
- timeout = settings.LARGE_TIMEOUT
- if self.timeout_multiplier and timeout == settings.LARGE_TIMEOUT:
- timeout = self.__get_new_timeout(timeout)
- selector, by = self.__recalculate_selector(selector, by)
- self.update_text(selector, text, by=by, timeout=timeout, retry=retry)
-
def input(self, selector, text, by=By.CSS_SELECTOR,
timeout=None, retry=False):
- """ Same as update_text() """
+ """ Same as self.update_text() """
if not timeout:
timeout = settings.LARGE_TIMEOUT
if self.timeout_multiplier and timeout == settings.LARGE_TIMEOUT:
@@ -2985,7 +3045,7 @@ def input(self, selector, text, by=By.CSS_SELECTOR,
def write(self, selector, text, by=By.CSS_SELECTOR,
timeout=None, retry=False):
- """ Same as update_text() """
+ """ Same as self.update_text() """
if not timeout:
timeout = settings.LARGE_TIMEOUT
if self.timeout_multiplier and timeout == settings.LARGE_TIMEOUT:
@@ -2994,7 +3054,7 @@ def write(self, selector, text, by=By.CSS_SELECTOR,
self.update_text(selector, text, by=by, timeout=timeout, retry=retry)
def send_keys(self, selector, text, by=By.CSS_SELECTOR, timeout=None):
- """ Same as add_text() """
+ """ Same as self.add_text() """
if not timeout:
timeout = settings.LARGE_TIMEOUT
if self.timeout_multiplier and timeout == settings.LARGE_TIMEOUT:
@@ -3048,6 +3108,10 @@ def assert_element_not_present(self, selector, by=By.CSS_SELECTOR,
self.wait_for_element_absent(selector, by=by, timeout=timeout)
return True
+ def assert_no_broken_links(self, multithreaded=True):
+ """ Same as self.assert_no_404_errors() """
+ self.assert_no_404_errors(multithreaded=multithreaded)
+
def wait(self, seconds):
""" Same as self.sleep() - Some JS frameworks use this method name. """
self.sleep(seconds)
@@ -3823,7 +3887,11 @@ def assert_element(self, selector, by=By.CSS_SELECTOR, timeout=None):
if self.demo_mode:
selector, by = self.__recalculate_selector(selector, by)
- messenger_post = "ASSERT %s: %s" % (by, selector)
+ a_t = "ASSERT"
+ if self._language != "English":
+ from seleniumbase.fixtures.words import SD
+ a_t = SD.translate_assert(self._language)
+ messenger_post = "%s %s: %s" % (a_t, by.upper(), selector)
self.__highlight_with_assert_success(messenger_post, selector, by)
return True
@@ -3903,8 +3971,14 @@ def assert_text(self, text, selector="html", by=By.CSS_SELECTOR,
if self.demo_mode:
selector, by = self.__recalculate_selector(selector, by)
- messenger_post = ("ASSERT TEXT {%s} in %s: %s"
- % (text, by, selector))
+ a_t = "ASSERT TEXT"
+ i_n = "in"
+ if self._language != "English":
+ from seleniumbase.fixtures.words import SD
+ a_t = SD.translate_assert_text(self._language)
+ i_n = SD.translate_in(self._language)
+ messenger_post = ("%s: {%s} %s %s: %s"
+ % (a_t, text, i_n, by.upper(), selector))
self.__highlight_with_assert_success(messenger_post, selector, by)
return True
@@ -3924,8 +3998,14 @@ def assert_exact_text(self, text, selector="html", by=By.CSS_SELECTOR,
if self.demo_mode:
selector, by = self.__recalculate_selector(selector, by)
- messenger_post = ("ASSERT EXACT TEXT {%s} in %s: %s"
- % (text, by, selector))
+ a_t = "ASSERT EXACT TEXT"
+ i_n = "in"
+ if self._language != "English":
+ from seleniumbase.fixtures.words import SD
+ a_t = SD.translate_assert_exact_text(self._language)
+ i_n = SD.translate_in(self._language)
+ messenger_post = ("%s: {%s} %s %s: %s"
+ % (a_t, text, i_n, by.upper(), selector))
self.__highlight_with_assert_success(messenger_post, selector, by)
return True
@@ -4009,7 +4089,11 @@ def assert_link_text(self, link_text, timeout=None):
timeout = self.__get_new_timeout(timeout)
self.wait_for_link_text_visible(link_text, timeout=timeout)
if self.demo_mode:
- messenger_post = ("ASSERT LINK TEXT {%s}." % link_text)
+ a_t = "ASSERT LINK TEXT"
+ if self._language != "English":
+ from seleniumbase.fixtures.words import SD
+ a_t = SD.translate_assert_link_text(self._language)
+ messenger_post = ("%s: {%s}" % (a_t, link_text))
self.__highlight_with_assert_success(
messenger_post, link_text, by=By.LINK_TEXT)
return True
@@ -4041,8 +4125,11 @@ def assert_partial_link_text(self, partial_link_text, timeout=None):
timeout = self.__get_new_timeout(timeout)
self.wait_for_partial_link_text(partial_link_text, timeout=timeout)
if self.demo_mode:
- messenger_post = (
- "ASSERT PARTIAL LINK TEXT {%s}." % partial_link_text)
+ a_t = "ASSERT PARTIAL LINK TEXT"
+ if self._language != "English":
+ from seleniumbase.fixtures.words import SD
+ a_t = SD.translate_assert_link_text(self._language)
+ messenger_post = ("%s: {%s}" % (a_t, partial_link_text))
self.__highlight_with_assert_success(
messenger_post, partial_link_text, by=By.PARTIAL_LINK_TEXT)
return True
@@ -4301,6 +4388,7 @@ def check_window(self, name="default", level=0, baseline=False):
if not name or len(name) < 1:
name = "default"
name = str(name)
+ from seleniumbase.core import visual_helper
visual_helper.visual_baseline_folder_setup()
baseline_dir = constants.VisualBaseline.STORAGE_FOLDER
visual_baseline_path = baseline_dir + "/" + test_id + "/" + name
@@ -4874,38 +4962,6 @@ def __highlight_with_jquery_2(self, message, selector, o_bs):
# Deprecated Methods (Replace these if they're still in your code!)
- @decorators.deprecated(
- "scroll_click() is deprecated. Use self.click() - It scrolls for you!")
- def scroll_click(self, selector, by=By.CSS_SELECTOR):
- # DEPRECATED - self.click() now scrolls to the element before clicking.
- # self.scroll_to(selector, by=by) # Redundant
- self.click(selector, by=by)
-
- @decorators.deprecated(
- "update_text_value() is deprecated. Use self.update_text() instead!")
- def update_text_value(self, selector, new_value, by=By.CSS_SELECTOR,
- timeout=None, retry=False):
- # DEPRECATED - self.update_text() should be used instead.
- if not timeout:
- timeout = settings.LARGE_TIMEOUT
- if self.timeout_multiplier and timeout == settings.LARGE_TIMEOUT:
- timeout = self.__get_new_timeout(timeout)
- if page_utils.is_xpath_selector(selector):
- by = By.XPATH
- self.update_text(
- selector, new_value, by=by, timeout=timeout, retry=retry)
-
- @decorators.deprecated(
- "jquery_update_text_value() is deprecated. Use jquery_update_text()")
- def jquery_update_text_value(self, selector, new_value, by=By.CSS_SELECTOR,
- timeout=None):
- # DEPRECATED - self.jquery_update_text() should be used instead.
- if not timeout:
- timeout = settings.LARGE_TIMEOUT
- if self.timeout_multiplier and timeout == settings.LARGE_TIMEOUT:
- timeout = self.__get_new_timeout(timeout)
- self.jquery_update_text(selector, new_value, by=by, timeout=timeout)
-
@decorators.deprecated(
"jq_format() is deprecated. Use re.escape() instead!")
def jq_format(self, code):
@@ -4996,11 +5052,16 @@ def setUp(self, masterqa_mode=False):
# Use Selenium Grid (Use --server="127.0.0.1" for a local Grid)
self.use_grid = True
if self.with_db_reporting:
+ import getpass
+ import uuid
from seleniumbase.core.application_manager import (
ApplicationManager)
from seleniumbase.core.testcase_manager import (
ExecutionQueryPayload)
- import getpass
+ from seleniumbase.core.testcase_manager import (
+ TestcaseDataPayload)
+ from seleniumbase.core.testcase_manager import (
+ TestcaseManager)
self.execution_guid = str(uuid.uuid4())
self.testcase_guid = None
self.execution_start_time = 0
@@ -5059,6 +5120,7 @@ def setUp(self, masterqa_mode=False):
# Parse the settings file
if self.settings_file:
+ from seleniumbase.core import settings_parser
settings_parser.set_settings(self.settings_file)
# Mobile Emulator device metrics: CSS Width, CSS Height, & Pixel-Ratio
@@ -5204,6 +5266,7 @@ def __set_last_page_source(self):
self.__last_page_source = None
def __insert_test_result(self, state, err):
+ from seleniumbase.core.testcase_manager import TestcaseDataPayload
data_payload = TestcaseDataPayload()
data_payload.runtime = int(time.time() * 1000) - self.case_start_time
data_payload.guid = self.testcase_guid
@@ -5440,6 +5503,7 @@ def tearDown(self):
self.execution_guid, runtime)
if self.with_s3_logging and has_exception:
""" If enabled, upload logs to S3 during test exceptions. """
+ import uuid
from seleniumbase.core.s3_manager import S3LoggingBucket
s3_bucket = S3LoggingBucket()
guid = str(uuid.uuid4().hex)
@@ -5458,6 +5522,10 @@ def tearDown(self):
logging.info(
"\n\n*** Log files uploaded: ***\n%s\n" % index_file)
if self.with_db_reporting:
+ from seleniumbase.core.testcase_manager import (
+ TestcaseDataPayload)
+ from seleniumbase.core.testcase_manager import (
+ TestcaseManager)
self.testcase_manager = TestcaseManager(self.database_env)
data_payload = TestcaseDataPayload()
data_payload.guid = self.testcase_guid
diff --git a/seleniumbase/fixtures/js_utils.py b/seleniumbase/fixtures/js_utils.py
index 28a4014b4ef..a8e8884e1c6 100755
--- a/seleniumbase/fixtures/js_utils.py
+++ b/seleniumbase/fixtures/js_utils.py
@@ -9,7 +9,6 @@
from seleniumbase import config as sb_config
from seleniumbase.common import decorators
from seleniumbase.config import settings
-from seleniumbase.core import style_sheet
from seleniumbase.fixtures import constants
from seleniumbase.fixtures import shared_utils
@@ -233,7 +232,10 @@ def highlight_with_js(driver, selector, loops, o_bs):
script = ("""document.querySelector('%s').style.boxShadow =
'0px 0px 6px 6px rgba(128, 128, 128, 0.5)';"""
% selector)
- driver.execute_script(script)
+ try:
+ driver.execute_script(script)
+ except Exception:
+ return
for n in range(loops):
script = ("""document.querySelector('%s').style.boxShadow =
'0px 0px 6px 6px rgba(255, 0, 0, 1)';"""
@@ -490,6 +492,7 @@ def activate_messenger(driver):
add_js_link(driver, messenger_js)
add_js_link(driver, msgr_theme_flat_js)
add_js_link(driver, msgr_theme_future_js)
+ from seleniumbase.core import style_sheet
add_css_style(driver, style_sheet.messenger_style)
for x in range(int(settings.MINI_TIMEOUT * 10.0)):
@@ -609,7 +612,10 @@ def highlight_with_js_2(driver, message, selector, o_bs, msg_dur):
script = ("""document.querySelector('%s').style.boxShadow =
'0px 0px 6px 6px rgba(128, 128, 128, 0.5)';"""
% selector)
- driver.execute_script(script)
+ try:
+ driver.execute_script(script)
+ except Exception:
+ return
time.sleep(0.0181)
script = ("""document.querySelector('%s').style.boxShadow =
'0px 0px 6px 6px rgba(205, 30, 0, 1)';"""
@@ -644,7 +650,10 @@ def highlight_with_jquery_2(driver, message, selector, o_bs, msg_dur):
selector = "body"
script = """jQuery('%s').css('box-shadow',
'0px 0px 6px 6px rgba(128, 128, 128, 0.5)');""" % selector
- safe_execute_script(driver, script)
+ try:
+ safe_execute_script(driver, script)
+ except Exception:
+ return
time.sleep(0.0181)
script = """jQuery('%s').css('box-shadow',
'0px 0px 6px 6px rgba(205, 30, 0, 1)');""" % selector
diff --git a/seleniumbase/fixtures/page_actions.py b/seleniumbase/fixtures/page_actions.py
index 304d46cee79..d65ca4cc694 100755
--- a/seleniumbase/fixtures/page_actions.py
+++ b/seleniumbase/fixtures/page_actions.py
@@ -23,7 +23,6 @@
import os
import sys
import time
-import traceback
from selenium.common.exceptions import StaleElementReferenceException
from selenium.common import exceptions as selenium_exceptions
from selenium.webdriver.common.by import By
@@ -582,6 +581,7 @@ def save_test_failure_data(driver, name, browser_type, folder=None):
Saves failure data to the current directory (or to a subfolder if provided)
If the folder provided doesn't exist, it will get created.
"""
+ import traceback
if folder:
abs_path = os.path.abspath('.')
file_path = abs_path + "/%s" % folder
diff --git a/seleniumbase/fixtures/words.py b/seleniumbase/fixtures/words.py
new file mode 100755
index 00000000000..549163fab0d
--- /dev/null
+++ b/seleniumbase/fixtures/words.py
@@ -0,0 +1,117 @@
+# -*- coding: utf-8 -*-
+''' Small Dictionary '''
+
+
+class SD:
+
+ def translate_in(language):
+ words = {}
+ words["English"] = "in"
+ words["Chinese"] = "在"
+ words["Dutch"] = "in"
+ words["French"] = "dans"
+ words["Italian"] = "nel"
+ words["Japanese"] = "に"
+ words["Korean"] = "에"
+ words["Portuguese"] = "no"
+ words["Russian"] = "в"
+ words["Spanish"] = "en"
+ return words[language]
+
+ def translate_assert(language):
+ words = {}
+ words["English"] = "ASSERT"
+ words["Chinese"] = "断言"
+ words["Dutch"] = "CONTROLEREN"
+ words["French"] = "VÉRIFIER"
+ words["Italian"] = "VERIFICARE"
+ words["Japanese"] = "検証"
+ words["Korean"] = "확인"
+ words["Portuguese"] = "VERIFICAR"
+ words["Russian"] = "ПОДТВЕРДИТЬ"
+ words["Spanish"] = "VERIFICAR"
+ return words[language]
+
+ def translate_assert_text(language):
+ words = {}
+ words["English"] = "ASSERT TEXT"
+ words["Chinese"] = "断言文本"
+ words["Dutch"] = "CONTROLEREN TEKST"
+ words["French"] = "VÉRIFIER TEXTE"
+ words["Italian"] = "VERIFICARE TESTO"
+ words["Japanese"] = "テキストを確認する"
+ words["Korean"] = "텍스트 확인"
+ words["Portuguese"] = "VERIFICAR TEXTO"
+ words["Russian"] = "ПОДТВЕРДИТЬ ТЕКСТ"
+ words["Spanish"] = "VERIFICAR TEXTO"
+ return words[language]
+
+ def translate_assert_exact_text(language):
+ words = {}
+ words["English"] = "ASSERT EXACT TEXT"
+ words["Chinese"] = "确切断言文本"
+ words["Dutch"] = "CONTROLEREN EXACTE TEKST"
+ words["French"] = "VÉRIFIER EXACTEMENT TEXTE"
+ words["Italian"] = "VERIFICARE TESTO ESATTO"
+ words["Japanese"] = "正確なテキストを確認する"
+ words["Korean"] = "정확한 텍스트를 확인하는"
+ words["Portuguese"] = "VERIFICAR TEXTO EXATO"
+ words["Russian"] = "ПОДТВЕРДИТЬ ТЕКСТ ТОЧНО"
+ words["Spanish"] = "VERIFICAR TEXTO EXACTO"
+ return words[language]
+
+ def translate_assert_link_text(language):
+ words = {}
+ words["English"] = "ASSERT LINK TEXT"
+ words["Chinese"] = "断言链接文本"
+ words["Dutch"] = "CONTROLEREN LINKTEKST"
+ words["French"] = "VÉRIFIER TEXTE DU LIEN"
+ words["Italian"] = "VERIFICARE TESTO DEL COLLEGAMENTO"
+ words["Japanese"] = "リンクテキストを確認する"
+ words["Korean"] = "링크 텍스트 확인"
+ words["Portuguese"] = "VERIFICAR TEXTO DO LINK"
+ words["Russian"] = "ПОДТВЕРДИТЬ ССЫЛКУ"
+ words["Spanish"] = "VERIFICAR TEXTO DEL ENLACE"
+ return words[language]
+
+ def translate_assert_title(language):
+ words = {}
+ words["English"] = "ASSERT TITLE"
+ words["Chinese"] = "断言标题"
+ words["Dutch"] = "CONTROLEREN TITEL"
+ words["French"] = "VÉRIFIER TITRE"
+ words["Italian"] = "VERIFICARE TITOLO"
+ words["Japanese"] = "タイトルを確認"
+ words["Korean"] = "제목 확인"
+ words["Portuguese"] = "VERIFICAR TÍTULO"
+ words["Russian"] = "ПОДТВЕРДИТЬ НАЗВАНИЕ"
+ words["Spanish"] = "VERIFICAR TÍTULO"
+ return words[language]
+
+ def translate_assert_no_404_errors(language):
+ words = {}
+ words["English"] = "ASSERT NO 404 ERRORS"
+ words["Chinese"] = "检查断开的链接"
+ words["Dutch"] = "CONTROLEREN OP GEBROKEN LINKS"
+ words["French"] = "VÉRIFIER LES LIENS ROMPUS"
+ words["Italian"] = "VERIFICARE I COLLEGAMENTI"
+ words["Japanese"] = "リンク切れを確認する"
+ words["Korean"] = "끊어진 링크 확인"
+ words["Portuguese"] = "VERIFICAR SE HÁ LINKS QUEBRADOS"
+ words["Russian"] = "ПРОВЕРИТЬ ОШИБКИ 404"
+ words["Spanish"] = "VERIFICAR SI HAY ENLACES ROTOS"
+ return words[language]
+
+ def translate_assert_no_js_errors(language):
+ words = {}
+ words["English"] = "ASSERT NO JS ERRORS"
+ words["Chinese"] = "检查JS错误"
+ words["Dutch"] = "CONTROLEREN OP JS FOUTEN"
+ words["French"] = "VÉRIFIER LES ERREURS JS"
+ words["Italian"] = "CONTROLLA ERRORI JS"
+ words["Japanese"] = "JSエラーを確認する"
+ words["Korean"] = "JS 오류 확인"
+ words["Portuguese"] = "VERIFICAR SE HÁ ERROS JS"
+ words["Russian"] = "ПРОВЕРИТЬ ОШИБКИ JS"
+ words["Spanish"] = "VERIFICAR SI HAY ERRORES JS"
+ return words[language]
diff --git a/seleniumbase/plugins/pytest_plugin.py b/seleniumbase/plugins/pytest_plugin.py
index 2d9c0d7f5c2..d7112f91ef3 100644
--- a/seleniumbase/plugins/pytest_plugin.py
+++ b/seleniumbase/plugins/pytest_plugin.py
@@ -385,7 +385,7 @@ def pytest_addoption(parser):
dest='devtools',
default=False,
help="""Using this opens Chrome's DevTools.""")
- parser.addoption('--reuse_session', '--reuse-session',
+ parser.addoption('--rs', '--reuse_session', '--reuse-session',
action="store_true",
dest='reuse_session',
default=False,
diff --git a/seleniumbase/translate/chinese.py b/seleniumbase/translate/chinese.py
index 81796d7b0dc..10cd2a83b2b 100755
--- a/seleniumbase/translate/chinese.py
+++ b/seleniumbase/translate/chinese.py
@@ -5,6 +5,10 @@
class 硒测试用例(BaseCase): # noqa
+ def __init__(self, *args, **kwargs):
+ super(硒测试用例, self).__init__(*args, **kwargs)
+ self._language = "Chinese"
+
def 开启(self, *args, **kwargs):
# open(url)
return self.open(*args, **kwargs)
@@ -30,15 +34,19 @@ def 单击链接文本(self, *args, **kwargs):
return self.click_link_text(*args, **kwargs)
def 更新文本(self, *args, **kwargs):
- # update_text(selector, new_value)
+ # update_text(selector, text)
return self.update_text(*args, **kwargs)
+ def 输入文本(self, *args, **kwargs):
+ # type(selector, text) # Same as update_text()
+ return self.type(*args, **kwargs)
+
def 添加文本(self, *args, **kwargs):
- # add_text(selector, new_value)
+ # add_text(selector, text)
return self.add_text(*args, **kwargs)
def 获取文本(self, *args, **kwargs):
- # get_text(selector, new_value)
+ # get_text(selector, text)
return self.get_text(*args, **kwargs)
def 断言文本(self, *args, **kwargs):
@@ -169,6 +177,14 @@ def JS单击(self, *args, **kwargs):
# js_click(selector)
return self.js_click(*args, **kwargs)
+ def JS更新文本(self, *args, **kwargs):
+ # js_update_text(selector, text)
+ return self.js_update_text(*args, **kwargs)
+
+ def JS输入文本(self, *args, **kwargs):
+ # js_type(selector, text)
+ return self.js_type(*args, **kwargs)
+
def 检查HTML(self, *args, **kwargs):
# inspect_html()
return self.inspect_html(*args, **kwargs)
@@ -362,12 +378,8 @@ def 设置所有属性(self, *args, **kwargs):
# set_attributes(selector, attribute, value)
return self.set_attributes(*args, **kwargs)
- def 输入文字(self, *args, **kwargs):
- # input(selector, new_value) # Same as update_text()
- return self.input(*args, **kwargs)
-
- def 写文字(self, *args, **kwargs):
- # write(selector, new_value) # Same as update_text()
+ def 写文本(self, *args, **kwargs):
+ # write(selector, text) # Same as update_text()
return self.write(*args, **kwargs)
def 设置消息主题(self, *args, **kwargs):
diff --git a/seleniumbase/translate/dutch.py b/seleniumbase/translate/dutch.py
index 9245d10f704..07abd179b7f 100755
--- a/seleniumbase/translate/dutch.py
+++ b/seleniumbase/translate/dutch.py
@@ -5,6 +5,10 @@
class Testgeval(BaseCase):
+ def __init__(self, *args, **kwargs):
+ super(Testgeval, self).__init__(*args, **kwargs)
+ self._language = "Dutch"
+
def openen(self, *args, **kwargs):
# open(url)
return self.open(*args, **kwargs)
@@ -30,15 +34,19 @@ def klik_linktekst(self, *args, **kwargs):
return self.click_link_text(*args, **kwargs)
def tekst_bijwerken(self, *args, **kwargs):
- # update_text(selector, new_value)
+ # update_text(selector, text)
return self.update_text(*args, **kwargs)
+ def typ(self, *args, **kwargs):
+ # type(selector, text) # Same as update_text()
+ return self.type(*args, **kwargs)
+
def tekst_toevoegen(self, *args, **kwargs):
- # add_text(selector, new_value)
+ # add_text(selector, text)
return self.add_text(*args, **kwargs)
def tekst_ophalen(self, *args, **kwargs):
- # get_text(selector, new_value)
+ # get_text(selector, text)
return self.get_text(*args, **kwargs)
def controleren_tekst(self, *args, **kwargs):
@@ -169,6 +177,14 @@ def js_klik(self, *args, **kwargs):
# js_click(selector)
return self.js_click(*args, **kwargs)
+ def js_tekst_bijwerken(self, *args, **kwargs):
+ # js_update_text(selector, text)
+ return self.js_update_text(*args, **kwargs)
+
+ def js_typ(self, *args, **kwargs):
+ # js_type(selector, text)
+ return self.js_type(*args, **kwargs)
+
def html_inspecteren(self, *args, **kwargs):
# inspect_html()
return self.inspect_html(*args, **kwargs)
@@ -362,12 +378,8 @@ def kenmerken_instellen(self, *args, **kwargs):
# set_attributes(selector, attribute, value)
return self.set_attributes(*args, **kwargs)
- def voer(self, *args, **kwargs):
- # input(selector, new_value) # Same as update_text()
- return self.input(*args, **kwargs)
-
def schrijven(self, *args, **kwargs):
- # write(selector, new_value) # Same as update_text()
+ # write(selector, text) # Same as update_text()
return self.write(*args, **kwargs)
def kenmerk_thema_van_bericht(self, *args, **kwargs):
diff --git a/seleniumbase/translate/french.py b/seleniumbase/translate/french.py
index f959edbf3e0..7189d439a68 100755
--- a/seleniumbase/translate/french.py
+++ b/seleniumbase/translate/french.py
@@ -5,6 +5,10 @@
class CasDeBase(BaseCase):
+ def __init__(self, *args, **kwargs):
+ super(CasDeBase, self).__init__(*args, **kwargs)
+ self._language = "French"
+
def ouvrir(self, *args, **kwargs):
# open(url)
return self.open(*args, **kwargs)
@@ -30,15 +34,19 @@ def cliquer_texte_du_lien(self, *args, **kwargs):
return self.click_link_text(*args, **kwargs)
def modifier_texte(self, *args, **kwargs):
- # update_text(selector, new_value)
+ # update_text(selector, text)
return self.update_text(*args, **kwargs)
+ def taper(self, *args, **kwargs):
+ # type(selector, text) # Same as update_text()
+ return self.type(*args, **kwargs)
+
def ajouter_texte(self, *args, **kwargs):
- # add_text(selector, new_value)
+ # add_text(selector, text)
return self.add_text(*args, **kwargs)
def obtenir_texte(self, *args, **kwargs):
- # get_text(selector, new_value)
+ # get_text(selector, text)
return self.get_text(*args, **kwargs)
def vérifier_texte(self, *args, **kwargs): # noqa
@@ -169,6 +177,14 @@ def js_clic(self, *args, **kwargs):
# js_click(selector)
return self.js_click(*args, **kwargs)
+ def js_modifier_texte(self, *args, **kwargs):
+ # js_update_text(selector, text)
+ return self.js_update_text(*args, **kwargs)
+
+ def js_taper(self, *args, **kwargs):
+ # js_type(selector, text)
+ return self.js_type(*args, **kwargs)
+
def vérifier_html(self, *args, **kwargs):
# inspect_html()
return self.inspect_html(*args, **kwargs)
@@ -362,12 +378,8 @@ def définir_attributs(self, *args, **kwargs):
# set_attributes(selector, attribute, value)
return self.set_attributes(*args, **kwargs)
- def taper(self, *args, **kwargs):
- # input(selector, new_value) # Same as update_text()
- return self.input(*args, **kwargs)
-
def écriver(self, *args, **kwargs):
- # write(selector, new_value) # Same as update_text()
+ # write(selector, text) # Same as update_text()
return self.write(*args, **kwargs)
def définir_thème_du_message(self, *args, **kwargs):
diff --git a/seleniumbase/translate/italian.py b/seleniumbase/translate/italian.py
index 6f692e9f925..9c0d80f422d 100755
--- a/seleniumbase/translate/italian.py
+++ b/seleniumbase/translate/italian.py
@@ -5,6 +5,10 @@
class CasoDiProva(BaseCase):
+ def __init__(self, *args, **kwargs):
+ super(CasoDiProva, self).__init__(*args, **kwargs)
+ self._language = "Italian"
+
def apri(self, *args, **kwargs):
# open(url)
return self.open(*args, **kwargs)
@@ -30,15 +34,19 @@ def fare_clic_testo_del_collegamento(self, *args, **kwargs):
return self.click_link_text(*args, **kwargs)
def aggiornare_testo(self, *args, **kwargs):
- # update_text(selector, new_value)
+ # update_text(selector, text)
return self.update_text(*args, **kwargs)
+ def digitare(self, *args, **kwargs):
+ # type(selector, text) # Same as update_text()
+ return self.type(*args, **kwargs)
+
def aggiungi_testo(self, *args, **kwargs):
- # add_text(selector, new_value)
+ # add_text(selector, text)
return self.add_text(*args, **kwargs)
def ottenere_testo(self, *args, **kwargs):
- # get_text(selector, new_value)
+ # get_text(selector, text)
return self.get_text(*args, **kwargs)
def verificare_testo(self, *args, **kwargs):
@@ -169,6 +177,14 @@ def js_fare_clic(self, *args, **kwargs):
# js_click(selector)
return self.js_click(*args, **kwargs)
+ def js_aggiornare_testo(self, *args, **kwargs):
+ # js_update_text(selector, text)
+ return self.js_update_text(*args, **kwargs)
+
+ def js_digitare(self, *args, **kwargs):
+ # js_type(selector, text)
+ return self.js_type(*args, **kwargs)
+
def controlla_html(self, *args, **kwargs):
# inspect_html()
return self.inspect_html(*args, **kwargs)
@@ -362,12 +378,8 @@ def impostare_gli_attributi(self, *args, **kwargs):
# set_attributes(selector, attribute, value)
return self.set_attributes(*args, **kwargs)
- def digitare(self, *args, **kwargs):
- # input(selector, new_value) # Same as update_text()
- return self.input(*args, **kwargs)
-
def scrivere(self, *args, **kwargs):
- # write(selector, new_value) # Same as update_text()
+ # write(selector, text) # Same as update_text()
return self.write(*args, **kwargs)
def impostare_tema_del_messaggio(self, *args, **kwargs):
diff --git a/seleniumbase/translate/japanese.py b/seleniumbase/translate/japanese.py
index af04a5f177c..23907e22cec 100755
--- a/seleniumbase/translate/japanese.py
+++ b/seleniumbase/translate/japanese.py
@@ -5,6 +5,10 @@
class セレニウムテストケース(BaseCase): # noqa
+ def __init__(self, *args, **kwargs):
+ super(セレニウムテストケース, self).__init__(*args, **kwargs)
+ self._language = "Japanese"
+
def を開く(self, *args, **kwargs):
# open(url)
return self.open(*args, **kwargs)
@@ -30,15 +34,19 @@ def リンクテキストをクリックします(self, *args, **kwargs):
return self.click_link_text(*args, **kwargs)
def テキストを更新(self, *args, **kwargs):
- # update_text(selector, new_value)
+ # update_text(selector, text)
return self.update_text(*args, **kwargs)
+ def 入力(self, *args, **kwargs):
+ # type(selector, text) # Same as update_text()
+ return self.type(*args, **kwargs)
+
def テキストを追加(self, *args, **kwargs):
- # add_text(selector, new_value)
+ # add_text(selector, text)
return self.add_text(*args, **kwargs)
def テキストを取得(self, *args, **kwargs):
- # get_text(selector, new_value)
+ # get_text(selector, text)
return self.get_text(*args, **kwargs)
def テキストを確認する(self, *args, **kwargs):
@@ -169,6 +177,14 @@ def JSクリックして(self, *args, **kwargs):
# js_click(selector)
return self.js_click(*args, **kwargs)
+ def JSテキストを更新(self, *args, **kwargs):
+ # js_update_text(selector, text)
+ return self.js_update_text(*args, **kwargs)
+
+ def JS入力(self, *args, **kwargs):
+ # js_type(selector, text)
+ return self.js_type(*args, **kwargs)
+
def HTMLをチェック(self, *args, **kwargs):
# inspect_html()
return self.inspect_html(*args, **kwargs)
@@ -362,12 +378,8 @@ def すべての属性を設定(self, *args, **kwargs):
# set_attributes(selector, attribute, value)
return self.set_attributes(*args, **kwargs)
- def 入力(self, *args, **kwargs):
- # input(selector, new_value) # Same as update_text()
- return self.input(*args, **kwargs)
-
def 書く(self, *args, **kwargs):
- # write(selector, new_value) # Same as update_text()
+ # write(selector, text) # Same as update_text()
return self.write(*args, **kwargs)
def メッセージのスタイルを設定する(self, *args, **kwargs):
diff --git a/seleniumbase/translate/korean.py b/seleniumbase/translate/korean.py
index f0366d91cfc..07b81d1ad84 100755
--- a/seleniumbase/translate/korean.py
+++ b/seleniumbase/translate/korean.py
@@ -5,6 +5,10 @@
class 셀레늄_테스트_케이스(BaseCase): # noqa
+ def __init__(self, *args, **kwargs):
+ super(셀레늄_테스트_케이스, self).__init__(*args, **kwargs)
+ self._language = "Korean"
+
def 열기(self, *args, **kwargs):
# open(url)
return self.open(*args, **kwargs)
@@ -30,15 +34,19 @@ def 링크_텍스트를_클릭합니다(self, *args, **kwargs):
return self.click_link_text(*args, **kwargs)
def 텍스트를_업데이트(self, *args, **kwargs):
- # update_text(selector, new_value)
+ # update_text(selector, text)
return self.update_text(*args, **kwargs)
+ def 입력(self, *args, **kwargs):
+ # type(selector, text) # Same as update_text()
+ return self.type(*args, **kwargs)
+
def 텍스트를_추가(self, *args, **kwargs):
- # add_text(selector, new_value)
+ # add_text(selector, text)
return self.add_text(*args, **kwargs)
def 텍스트를_검색(self, *args, **kwargs):
- # get_text(selector, new_value)
+ # get_text(selector, text)
return self.get_text(*args, **kwargs)
def 텍스트_확인(self, *args, **kwargs):
@@ -169,6 +177,14 @@ def JS_클릭(self, *args, **kwargs):
# js_click(selector)
return self.js_click(*args, **kwargs)
+ def JS_텍스트를_업데이트(self, *args, **kwargs):
+ # js_update_text(selector, text)
+ return self.js_update_text(*args, **kwargs)
+
+ def JS_입력(self, *args, **kwargs):
+ # js_type(selector, text)
+ return self.js_type(*args, **kwargs)
+
def HTML_확인(self, *args, **kwargs):
# inspect_html()
return self.inspect_html(*args, **kwargs)
@@ -362,12 +378,8 @@ def 모든_특성_설정(self, *args, **kwargs):
# set_attributes(selector, attribute, value)
return self.set_attributes(*args, **kwargs)
- def 입력(self, *args, **kwargs):
- # input(selector, new_value) # Same as update_text()
- return self.input(*args, **kwargs)
-
def 쓰다(self, *args, **kwargs):
- # write(selector, new_value) # Same as update_text()
+ # write(selector, text) # Same as update_text()
return self.write(*args, **kwargs)
def 메시지_테마_설정(self, *args, **kwargs):
diff --git a/seleniumbase/translate/master_dict.py b/seleniumbase/translate/master_dict.py
index 0daa8ee63b3..47319ae6104 100755
--- a/seleniumbase/translate/master_dict.py
+++ b/seleniumbase/translate/master_dict.py
@@ -1,17 +1,19 @@
-
-# Master Dictionary
-
-# Translations
-# 0: English
-# 1: Chinese
-# 2: Dutch
-# 3: French
-# 4: Italian
-# 5: Japanese
-# 6: Korean
-# 7: Portuguese
-# 8: Russian
-# 9: Spanish
+# -*- coding: utf-8 -*-
+"""
+Master Dictionary
+
+Translations
+0: English
+1: Chinese
+2: Dutch
+3: French
+4: Italian
+5: Japanese
+6: Korean
+7: Portuguese
+8: Russian
+9: Spanish
+"""
class MD_F:
@@ -729,6 +731,30 @@ class MD:
md["js_click"][8] = "JS_нажмите"
md["js_click"][9] = "js_haga_clic"
+ md["js_update_text"] = ["*"] * num_langs
+ md["js_update_text"][0] = "js_update_text"
+ md["js_update_text"][1] = "JS更新文本"
+ md["js_update_text"][2] = "js_tekst_bijwerken"
+ md["js_update_text"][3] = "js_modifier_texte"
+ md["js_update_text"][4] = "js_aggiornare_testo"
+ md["js_update_text"][5] = "JSテキストを更新"
+ md["js_update_text"][6] = "JS_텍스트를_업데이트"
+ md["js_update_text"][7] = "js_atualizar_texto"
+ md["js_update_text"][8] = "JS_обновить_текст"
+ md["js_update_text"][9] = "js_actualizar_texto"
+
+ md["js_type"] = ["*"] * num_langs
+ md["js_type"][0] = "js_type"
+ md["js_type"][1] = "JS输入文本"
+ md["js_type"][2] = "js_typ"
+ md["js_type"][3] = "js_taper"
+ md["js_type"][4] = "js_digitare"
+ md["js_type"][5] = "JS入力"
+ md["js_type"][6] = "JS_입력"
+ md["js_type"][7] = "js_tipo"
+ md["js_type"][8] = "JS_введите"
+ md["js_type"][9] = "js_escriba"
+
md["inspect_html"] = ["*"] * num_langs
md["inspect_html"][0] = "inspect_html"
md["inspect_html"][1] = "检查HTML"
@@ -1306,21 +1332,21 @@ class MD:
md["set_attributes"][8] = "набор_атрибутов"
md["set_attributes"][9] = "establecer_atributos"
- md["input"] = ["*"] * num_langs
- md["input"][0] = "input"
- md["input"][1] = "输入文字"
- md["input"][2] = "voer"
- md["input"][3] = "taper"
- md["input"][4] = "digitare"
- md["input"][5] = "入力"
- md["input"][6] = "입력"
- md["input"][7] = "entrada"
- md["input"][8] = "введите"
- md["input"][9] = "entrada"
+ md["type"] = ["*"] * num_langs
+ md["type"][0] = "type"
+ md["type"][1] = "输入文本"
+ md["type"][2] = "typ"
+ md["type"][3] = "taper"
+ md["type"][4] = "digitare"
+ md["type"][5] = "入力"
+ md["type"][6] = "입력"
+ md["type"][7] = "tipo"
+ md["type"][8] = "введите"
+ md["type"][9] = "escriba"
md["write"] = ["*"] * num_langs
md["write"][0] = "write"
- md["write"][1] = "写文字"
+ md["write"][1] = "写文本"
md["write"][2] = "schrijven"
md["write"][3] = "écriver"
md["write"][4] = "scrivere"
@@ -1477,18 +1503,18 @@ class MD:
################
# Duplicates
- # "type" -> duplicate of "input"
- md["type"] = ["*"] * num_langs
- md["type"][0] = "type"
- md["type"][1] = "输入文字"
- md["type"][2] = "voer"
- md["type"][3] = "taper"
- md["type"][4] = "digitare"
- md["type"][5] = "入力"
- md["type"][6] = "입력"
- md["type"][7] = "entrada"
- md["type"][8] = "введите"
- md["type"][9] = "entrada"
+ # "input" -> duplicate of "type"
+ md["input"] = ["*"] * num_langs
+ md["input"][0] = "input"
+ md["input"][1] = "输入文本"
+ md["input"][2] = "typ"
+ md["input"][3] = "taper"
+ md["input"][4] = "digitare"
+ md["input"][5] = "入力"
+ md["input"][6] = "입력"
+ md["input"][7] = "tipo"
+ md["input"][8] = "введите"
+ md["input"][9] = "escriba"
# "goto" -> duplicate of "visit"
md["goto"] = ["*"] * num_langs
@@ -1620,6 +1646,45 @@ class MD:
md["is_checked"][8] = "выбран"
md["is_checked"][9] = "está_seleccionado"
+ # "wait_for_text_visible" -> duplicate of "wait_for_text"
+ md["wait_for_text_visible"] = ["*"] * num_langs
+ md["wait_for_text_visible"][0] = "wait_for_text_visible"
+ md["wait_for_text_visible"][1] = "等待文本"
+ md["wait_for_text_visible"][2] = "wachten_op_tekst"
+ md["wait_for_text_visible"][3] = "attendre_le_texte"
+ md["wait_for_text_visible"][4] = "attendere_il_testo"
+ md["wait_for_text_visible"][5] = "テキストを待つ"
+ md["wait_for_text_visible"][6] = "텍스트가_나타날_때까지_기다립니다"
+ md["wait_for_text_visible"][7] = "aguardar_o_texto"
+ md["wait_for_text_visible"][8] = "ждать_текста"
+ md["wait_for_text_visible"][9] = "espera_el_texto"
+
+ # "assert_text_visible" -> duplicate of "assert_text"
+ md["assert_text_visible"] = ["*"] * num_langs
+ md["assert_text_visible"][0] = "assert_text_visible"
+ md["assert_text_visible"][1] = "断言文本"
+ md["assert_text_visible"][2] = "controleren_tekst"
+ md["assert_text_visible"][3] = "vérifier_texte"
+ md["assert_text_visible"][4] = "verificare_testo"
+ md["assert_text_visible"][5] = "テキストを確認する"
+ md["assert_text_visible"][6] = "텍스트_확인"
+ md["assert_text_visible"][7] = "verificar_texto"
+ md["assert_text_visible"][8] = "подтвердить_текст"
+ md["assert_text_visible"][9] = "verificar_texto"
+
+ # "assert_no_broken_links" -> duplicate of "assert_no_404_errors"
+ md["assert_no_broken_links"] = ["*"] * num_langs
+ md["assert_no_broken_links"][0] = "assert_no_broken_links"
+ md["assert_no_broken_links"][1] = "检查断开的链接"
+ md["assert_no_broken_links"][2] = "controleren_op_gebroken_links"
+ md["assert_no_broken_links"][3] = "vérifier_les_liens_rompus"
+ md["assert_no_broken_links"][4] = "verificare_i_collegamenti"
+ md["assert_no_broken_links"][5] = "リンク切れを確認する"
+ md["assert_no_broken_links"][6] = "끊어진_링크_확인"
+ md["assert_no_broken_links"][7] = "verificar_se_há_links_quebrados"
+ md["assert_no_broken_links"][8] = "проверить_ошибки_404"
+ md["assert_no_broken_links"][9] = "verificar_si_hay_enlaces_rotos"
+
# "block_ads" -> duplicate of "ad_block"
md["block_ads"] = ["*"] * num_langs
md["block_ads"][0] = "block_ads"
diff --git a/seleniumbase/translate/portuguese.py b/seleniumbase/translate/portuguese.py
index 31cf37cde9b..c85a11b819b 100755
--- a/seleniumbase/translate/portuguese.py
+++ b/seleniumbase/translate/portuguese.py
@@ -5,6 +5,10 @@
class CasoDeTeste(BaseCase):
+ def __init__(self, *args, **kwargs):
+ super(CasoDeTeste, self).__init__(*args, **kwargs)
+ self._language = "Portuguese"
+
def abrir(self, *args, **kwargs):
# open(url)
return self.open(*args, **kwargs)
@@ -30,15 +34,19 @@ def clique_texto_do_link(self, *args, **kwargs):
return self.click_link_text(*args, **kwargs)
def atualizar_texto(self, *args, **kwargs):
- # update_text(selector, new_value)
+ # update_text(selector, text)
return self.update_text(*args, **kwargs)
+ def tipo(self, *args, **kwargs):
+ # type(selector, text) # Same as update_text()
+ return self.type(*args, **kwargs)
+
def adicionar_texto(self, *args, **kwargs):
- # add_text(selector, new_value)
+ # add_text(selector, text)
return self.add_text(*args, **kwargs)
def obter_texto(self, *args, **kwargs):
- # get_text(selector, new_value)
+ # get_text(selector, text)
return self.get_text(*args, **kwargs)
def verificar_texto(self, *args, **kwargs):
@@ -169,6 +177,14 @@ def js_clique(self, *args, **kwargs):
# js_click(selector)
return self.js_click(*args, **kwargs)
+ def js_atualizar_texto(self, *args, **kwargs):
+ # js_update_text(selector, text)
+ return self.js_update_text(*args, **kwargs)
+
+ def js_tipo(self, *args, **kwargs):
+ # js_type(selector, text)
+ return self.js_type(*args, **kwargs)
+
def verificar_html(self, *args, **kwargs):
# inspect_html()
return self.inspect_html(*args, **kwargs)
@@ -362,12 +378,8 @@ def definir_atributos(self, *args, **kwargs):
# set_attributes(selector, attribute, value)
return self.set_attributes(*args, **kwargs)
- def entrada(self, *args, **kwargs):
- # input(selector, new_value) # Same as update_text()
- return self.input(*args, **kwargs)
-
def escreva(self, *args, **kwargs):
- # write(selector, new_value) # Same as update_text()
+ # write(selector, text) # Same as update_text()
return self.write(*args, **kwargs)
def definir_tema_da_mensagem(self, *args, **kwargs):
diff --git a/seleniumbase/translate/russian.py b/seleniumbase/translate/russian.py
index 842b4fbc998..11c20e5ea53 100755
--- a/seleniumbase/translate/russian.py
+++ b/seleniumbase/translate/russian.py
@@ -5,6 +5,10 @@
class ТестНаСелен(BaseCase): # noqa
+ def __init__(self, *args, **kwargs):
+ super(ТестНаСелен, self).__init__(*args, **kwargs)
+ self._language = "Russian"
+
def открыть(self, *args, **kwargs):
# open(url)
return self.open(*args, **kwargs)
@@ -30,15 +34,19 @@ def нажмите_ссылку(self, *args, **kwargs):
return self.click_link_text(*args, **kwargs)
def обновить_текст(self, *args, **kwargs):
- # update_text(selector, new_value)
+ # update_text(selector, text)
return self.update_text(*args, **kwargs)
+ def введите(self, *args, **kwargs):
+ # type(selector, text) # Same as update_text()
+ return self.type(*args, **kwargs)
+
def добавить_текст(self, *args, **kwargs):
- # add_text(selector, new_value)
+ # add_text(selector, text)
return self.add_text(*args, **kwargs)
def получить_текст(self, *args, **kwargs):
- # get_text(selector, new_value)
+ # get_text(selector, text)
return self.get_text(*args, **kwargs)
def подтвердить_текст(self, *args, **kwargs):
@@ -169,6 +177,14 @@ def JS_нажмите(self, *args, **kwargs):
# js_click(selector)
return self.js_click(*args, **kwargs)
+ def JS_обновить_текст(self, *args, **kwargs):
+ # js_update_text(selector, text)
+ return self.js_update_text(*args, **kwargs)
+
+ def JS_введите(self, *args, **kwargs):
+ # js_type(selector, text)
+ return self.js_type(*args, **kwargs)
+
def проверить_HTML(self, *args, **kwargs):
# inspect_html()
return self.inspect_html(*args, **kwargs)
@@ -362,12 +378,8 @@ def набор_атрибутов(self, *args, **kwargs):
# set_attributes(selector, attribute, value)
return self.set_attributes(*args, **kwargs)
- def введите(self, *args, **kwargs):
- # input(selector, new_value) # Same as update_text()
- return self.input(*args, **kwargs)
-
def написать(self, *args, **kwargs):
- # write(selector, new_value) # Same as update_text()
+ # write(selector, text) # Same as update_text()
return self.write(*args, **kwargs)
def набор_тему_сообщения(self, *args, **kwargs):
diff --git a/seleniumbase/translate/spanish.py b/seleniumbase/translate/spanish.py
index e9dbdc17bd6..cede5c00cf1 100755
--- a/seleniumbase/translate/spanish.py
+++ b/seleniumbase/translate/spanish.py
@@ -5,6 +5,10 @@
class CasoDePrueba(BaseCase):
+ def __init__(self, *args, **kwargs):
+ super(CasoDePrueba, self).__init__(*args, **kwargs)
+ self._language = "Spanish"
+
def abrir(self, *args, **kwargs):
# open(url)
return self.open(*args, **kwargs)
@@ -30,15 +34,19 @@ def haga_clic_texto_del_enlace(self, *args, **kwargs):
return self.click_link_text(*args, **kwargs)
def actualizar_texto(self, *args, **kwargs):
- # update_text(selector, new_value)
+ # update_text(selector, text)
return self.update_text(*args, **kwargs)
+ def escriba(self, *args, **kwargs):
+ # type(selector, text) # Same as update_text()
+ return self.type(*args, **kwargs)
+
def agregar_texto(self, *args, **kwargs):
- # add_text(selector, new_value)
+ # add_text(selector, text)
return self.add_text(*args, **kwargs)
def obtener_texto(self, *args, **kwargs):
- # get_text(selector, new_value)
+ # get_text(selector, text)
return self.get_text(*args, **kwargs)
def verificar_texto(self, *args, **kwargs):
@@ -169,6 +177,14 @@ def js_haga_clic(self, *args, **kwargs):
# js_click(selector)
return self.js_click(*args, **kwargs)
+ def js_actualizar_texto(self, *args, **kwargs):
+ # js_update_text(selector, text)
+ return self.js_update_text(*args, **kwargs)
+
+ def js_escriba(self, *args, **kwargs):
+ # js_type(selector, text)
+ return self.js_type(*args, **kwargs)
+
def comprobar_html(self, *args, **kwargs):
# inspect_html()
return self.inspect_html(*args, **kwargs)
@@ -362,12 +378,8 @@ def establecer_atributos(self, *args, **kwargs):
# set_attributes(selector, attribute, value)
return self.set_attributes(*args, **kwargs)
- def entrada(self, *args, **kwargs):
- # input(selector, new_value) # Same as update_text()
- return self.input(*args, **kwargs)
-
def escribir(self, *args, **kwargs):
- # write(selector, new_value) # Same as update_text()
+ # write(selector, text) # Same as update_text()
return self.write(*args, **kwargs)
def establecer_tema_del_mensaje(self, *args, **kwargs):
diff --git a/seleniumbase/translate/translator.py b/seleniumbase/translate/translator.py
index 77738a790f2..42266e2fd96 100755
--- a/seleniumbase/translate/translator.py
+++ b/seleniumbase/translate/translator.py
@@ -1,3 +1,4 @@
+# -*- coding: utf-8 -*-
"""
Translates a SeleniumBase Python file into a different language
@@ -75,19 +76,9 @@ def invalid_run_command(msg=None):
def sc_ranges():
# Get the ranges of special characters of Chinese, Japanese, and Korean.
special_char_ranges = ([
- {"from": ord(u"\u3300"), "to": ord(u"\u33ff")},
- {"from": ord(u"\ufe30"), "to": ord(u"\ufe4f")},
- {"from": ord(u"\uf900"), "to": ord(u"\ufaff")},
- {"from": ord(u"\U0002F800"), "to": ord(u"\U0002fa1f")},
- {'from': ord(u'\u3040'), 'to': ord(u'\u309f')},
- {"from": ord(u"\u30a0"), "to": ord(u"\u30ff")},
- {"from": ord(u"\u2e80"), "to": ord(u"\u2eff")},
- {"from": ord(u"\u4e00"), "to": ord(u"\u9fff")},
- {"from": ord(u"\u3400"), "to": ord(u"\u4dbf")},
- {"from": ord(u"\U00020000"), "to": ord(u"\U0002a6df")},
- {"from": ord(u"\U0002a700"), "to": ord(u"\U0002b73f")},
- {"from": ord(u"\U0002b740"), "to": ord(u"\U0002b81f")},
- {"from": ord(u"\U0002b820"), "to": ord(u"\U0002ceaf")}
+ {"from": ord(u"\u4e00"), "to": ord(u"\u9FFF")},
+ {"from": ord(u"\u3040"), "to": ord(u"\u30ff")},
+ {"from": ord(u"\uac00"), "to": ord(u"\ud7a3")}
])
return special_char_ranges
@@ -505,6 +496,8 @@ def main():
new_sb_lines = []
for line in seleniumbase_lines:
+ if line.endswith(" # noqa") and line.count(" # noqa") == 1:
+ line = line.replace(" # noqa", "")
line_length2 = len(line) # Normal Python string length used
line_length = get_width(line) # Special characters count 2X
if line_length > code_width:
@@ -594,6 +587,54 @@ def main():
else:
new_sb_lines.append(line)
continue
+ elif line.count('("') == 1:
+ whitespace = line_length2 - len(line.lstrip())
+ new_ws = line[0:whitespace] + " "
+ line1 = line.split('("')[0] + '('
+ line2 = new_ws + '"' + line.split('("')[1]
+ if not ('):') in line2:
+ new_sb_lines.append(line1)
+ if get_width(line2) + w > console_width:
+ if line2.count('" in self.') == 1:
+ line2a = line2.split(
+ '" in self.')[0] + '" in'
+ line2b = new_ws + "self." + (
+ line2.split('" in self.')[1])
+ new_sb_lines.append(line2a)
+ new_sb_lines.append(line2b)
+ continue
+ new_sb_lines.append(line2)
+ elif get_width(line2) + 4 + w <= console_width:
+ line2 = " " + line2
+ new_sb_lines.append(line1)
+ new_sb_lines.append(line2)
+ else:
+ new_sb_lines.append(line)
+ continue
+ elif line.count("('") == 1:
+ whitespace = line_length2 - len(line.lstrip())
+ new_ws = line[0:whitespace] + " "
+ line1 = line.split("('")[0] + '('
+ line2 = new_ws + "'" + line.split("('")[1]
+ if not ('):') in line2:
+ new_sb_lines.append(line1)
+ if get_width(line2) + w > console_width:
+ if line2.count("' in self.") == 1:
+ line2a = line2.split(
+ "' in self.")[0] + "' in"
+ line2b = new_ws + "self." + (
+ line2.split("' in self.")[1])
+ new_sb_lines.append(line2a)
+ new_sb_lines.append(line2b)
+ continue
+ new_sb_lines.append(line2)
+ elif get_width(line2) + 4 + w <= console_width:
+ line2 = " " + line2
+ new_sb_lines.append(line1)
+ new_sb_lines.append(line2)
+ else:
+ new_sb_lines.append(line)
+ continue
elif line.count('= "') == 1 and line.count('://') == 1:
whitespace = line_length2 - len(line.lstrip())
new_ws = line[0:whitespace] + " "
diff --git a/seleniumbase/utilities/selenium_ide/convert_ide.py b/seleniumbase/utilities/selenium_ide/convert_ide.py
index c688d6d49c7..33204a0af10 100755
--- a/seleniumbase/utilities/selenium_ide/convert_ide.py
+++ b/seleniumbase/utilities/selenium_ide/convert_ide.py
@@ -116,7 +116,7 @@ def main():
if len(line.strip()) == 0:
continue
- # If .clear(), skip because .update_text() already does this
+ # If .clear(), skip because self.type() already does this
if line.strip().endswith(".clear()"):
continue
@@ -195,7 +195,7 @@ def main():
if "\\[" in selector or "\\]" in selector or "\\." in selector:
raw = "r"
text = data.group(3)
- command = '''%sself.update_text(%s'%s', '%s')''' % (
+ command = '''%sself.type(%s'%s', '%s')''' % (
whitespace, raw, selector, text)
seleniumbase_lines.append(command)
continue
@@ -249,7 +249,7 @@ def main():
whitespace = data.group(1)
selector = '[name="%s"]' % data.group(2)
text = data.group(3)
- command = '''%sself.update_text('%s', '%s')''' % (
+ command = '''%sself.type('%s', '%s')''' % (
whitespace, selector, text)
seleniumbase_lines.append(command)
continue
@@ -302,7 +302,7 @@ def main():
whitespace = data.group(1)
selector = '%s' % data.group(2)
text = data.group(3)
- command = '''%sself.update_text('%s', '%s')''' % (
+ command = '''%sself.type('%s', '%s')''' % (
whitespace, selector, text)
if command.count('\\"') == command.count('"'):
command = command.replace('\\"', '"')
@@ -333,7 +333,7 @@ def main():
whitespace = data.group(1)
selector = '%s' % data.group(2)
text = data.group(3)
- command = '''%sself.update_text("%s", '%s')''' % (
+ command = '''%sself.type("%s", '%s')''' % (
whitespace, selector, text)
if command.count('\\"') == command.count('"'):
command = command.replace('\\"', '"')
@@ -680,7 +680,7 @@ def main():
data2 = re.match(regex_string, lines[line_num + 1])
if data2:
continue
- regex_string = (r'''^\s*self.update_text\(["|']'''
+ regex_string = (r'''^\s*self.type\(["|']'''
'' + selector + ''
'' + r'''["|'], [\S\s]+\)\s*$''')
data2 = re.match(regex_string, lines[line_num + 1])
diff --git a/setup.py b/setup.py
index 0de852c6579..afc7f23bf6e 100755
--- a/setup.py
+++ b/setup.py
@@ -54,7 +54,7 @@
setup(
name='seleniumbase',
- version='1.39.5',
+ version='1.40.0',
description='Fast, Easy, and Reliable Browser Automation & Testing.',
long_description=long_description,
long_description_content_type='text/markdown',
@@ -107,7 +107,7 @@
'attrs>=19.3.0',
'pytest==4.6.11;python_version<"3.5"',
'pytest==5.4.3;python_version>="3.5"',
- 'pytest-cov==2.9.0',
+ 'pytest-cov==2.10.0',
'pytest-forked==1.1.3',
'pytest-html==1.22.1;python_version<"3.6"',
'pytest-html==2.0.1;python_version>="3.6"',
@@ -133,9 +133,9 @@
'pyotp==2.3.0',
'boto==2.49.0',
'cffi==1.14.0',
- 'rich==2.0.0;python_version>="3.6" and python_version<"4.0"',
+ 'rich==2.1.0;python_version>="3.6" and python_version<"4.0"',
'flake8==3.7.9;python_version<"3.5"',
- 'flake8==3.8.2;python_version>="3.5"',
+ 'flake8==3.8.3;python_version>="3.5"',
'pyflakes==2.1.1;python_version<"3.5"',
'pyflakes==2.2.0;python_version>="3.5"',
'certifi>=2020.4.5.2',