Merge pull request #780 from seleniumbase/demo-mode-updates-and-more

Demo Mode updates and more
This commit is contained in:
Michael Mintz 2021-01-12 01:34:01 -05:00 committed by GitHub
commit e489ac299d
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
11 changed files with 75 additions and 48 deletions

View File

@ -1,5 +1,5 @@
regex>=2020.11.13
tqdm>=4.55.2
tqdm>=4.56.0
livereload==2.6.3;python_version>="3.6"
Markdown==3.3.3
readme-renderer==28.0

View File

@ -5,14 +5,14 @@ class MyChartMakerClass(BaseCase):
def test_seleniumbase_chart(self):
self.create_presentation(theme="league", transition="slide")
self.create_pie_chart(title="There are 4 core areas of SeleniumBase:")
self.add_data_point("Basic API (Test methods/functions)", 1)
self.add_data_point("Command-line Options (pytest Options)", 1)
self.create_pie_chart(title="The 4 core areas of SeleniumBase:")
self.add_data_point("Basic API (test methods)", 1)
self.add_data_point("Command-line options (pytest options)", 1)
self.add_data_point("The Console Scripts interface", 1)
self.add_data_point("Advanced API (Tours, Charts, & Presentations)", 1)
self.add_slide("<p>SeleniumBase core areas</p>" + self.extract_chart())
self.add_slide(
"<p>Basic API (Test methods/functions) Example</p>",
"<p>Basic API (test methods). Example test:</p>",
code=(
'from seleniumbase import BaseCase\n\n'
'class MyTestClass(BaseCase):\n\n'
@ -27,20 +27,23 @@ class MyChartMakerClass(BaseCase):
' self.click_link_text("comic #249")\n'
' self.assert_element(\'img[alt*="Chess"]\')\n'))
self.add_slide(
"<p>Command-line Options Example</p>",
"<p>Command-line options. Examples:</p>",
code=(
'$ pytest my_first_test.py\n'
'$ pytest test_swag_labs.py --mobile\n'
'$ pytest edge_test.py --browser=edge\n'
'$ pytest basic_test.py --headless\n'
'$ pytest my_first_test.py --demo\n'
'$ pytest my_first_test.py --demo --guest\n'
'$ pytest basic_test.py --slow\n'
'$ pytest -v -m marker2 --headless --save-screenshot\n'
'$ pytest test_suite.py --reuse-session --html=report.html\n'
'$ pytest basic_test.py --incognito\n'
'$ pytest parameterized_test.py --guest --reuse-session\n'))
'$ pytest parameterized_test.py --reuse-session\n'
'$ pytest test_suite.py --html=report.html --rs\n'
'$ pytest test_suite.py --dashboard --html=report.html\n'
'$ pytest github_test.py --demo --disable-csp\n'
'$ pytest test_suite.py -n=2 --rs --crumbs\n'
'$ pytest basic_test.py --incognito\n'))
self.add_slide(
"<p>Console scripts interface Example</p>",
"<p>The Console Scripts interface. Examples:</p>",
code=(
'$ sbase install chromedriver\n'
'$ sbase install chromedriver latest\n'
@ -57,7 +60,7 @@ class MyChartMakerClass(BaseCase):
'$ sbase grid-hub stop\n'
'$ sbase options\n'))
self.add_slide(
'<p>Advanced API (creating a presentation) Example</p>',
'<p>Advanced API. "Presenter" example:</p>',
code=(
'from seleniumbase import BaseCase\n\n'
'class MyPresenterClass(BaseCase):\n\n'

View File

@ -1,6 +1,6 @@
<h2><img src="https://seleniumbase.io/img/sb_icon.png" title="SeleniumBase" width="30" /> Creating a SeleniumBase Test Runner with NodeJS</h2>
<h2><img src="https://seleniumbase.io/img/sb_icon.png" title="SeleniumBase" width="30" /> Creating a Test Runner with NodeJS + Express</h2>
You can create a customized web app for running SeleniumBase tests by using NodeJS. (This tutorial assumes that you've already installed SeleniumBase by following the instructions from the [top-level ReadMe](https://github.com/seleniumbase/SeleniumBase/blob/master/README.md) file.)
You can create a customized web app for running SeleniumBase tests by using NodeJS and Express. (This tutorial assumes that you've already installed SeleniumBase by following the instructions from the [top-level ReadMe](https://github.com/seleniumbase/SeleniumBase/blob/master/README.md) file.)
<img src="https://seleniumbase.io/other/node_runner.png" title="Node Runner" />

View File

@ -1,5 +1,5 @@
# Project information
site_name: SeleniumBase
site_name: SeleniumBase / Docs
site_url: https://seleniumbase.io
site_author: Michael Mintz
site_description: A fast, reliable web automation framework for end-to-end testing (and RPA) with Python, pytest, and WebDriver.
@ -30,7 +30,7 @@ theme:
sticky_navigation: true
language: en
include_search_page: false
search_index_only: true
search_index_only: false
features:
- tabs
- instant
@ -53,7 +53,7 @@ plugins:
on_pre_build: docs.prepare:main
# Page tree
nav:
- SeleniumBase | README: README.md
- SeleniumBase / README: README.md
- Features List: help_docs/features_list.md
- Running Example Tests: examples/ReadMe.md
- Command Line Options: help_docs/customizing_test_runs.md
@ -104,6 +104,7 @@ nav:
- TinyMCE Demo Page: https://seleniumbase.io/other/tinymce
- Virtual Device Farm: https://seleniumbase.io/devices/
- Error Demo Page: https://seleniumbase.io/error_page/
- Presentations:
- Presenter Demo: https://seleniumbase.io/other/presenter.html
- Core Presentation: https://seleniumbase.io/other/core_presentation.html
- Chart Maker Demo: https://seleniumbase.io/other/chart_presentation.html

View File

@ -64,7 +64,7 @@ ipython==7.19.0;python_version>="3.7"
colorama==0.4.4
pathlib2==2.3.5;python_version<"3.5"
importlib-metadata==2.0.0;python_version<"3.6"
virtualenv>=20.2.2
virtualenv>=20.3.0
pymysql==0.10.1;python_version<"3.6"
pymysql==1.0.2;python_version>="3.6"
coverage==5.3.1
@ -76,7 +76,7 @@ toml==0.10.2
Pillow==6.2.2;python_version<"3.5"
Pillow==7.2.0;python_version>="3.5" and python_version<"3.6"
Pillow==8.1.0;python_version>="3.6"
rich==9.7.0;python_version>="3.6" and python_version<"4.0"
rich==9.8.0;python_version>="3.6" and python_version<"4.0"
zipp==1.2.0;python_version<"3.6"
zipp==3.4.0;python_version>="3.6"
flake8==3.7.9;python_version<"3.5"

View File

@ -1,2 +1,2 @@
# seleniumbase package
__version__ = "1.51.14"
__version__ = "1.52.0"

View File

@ -134,6 +134,8 @@ class BaseCase(unittest.TestCase):
timeout = settings.SMALL_TIMEOUT
if self.timeout_multiplier and timeout == settings.SMALL_TIMEOUT:
timeout = self.__get_new_timeout(timeout)
original_selector = selector
original_by = by
selector, by = self.__recalculate_selector(selector, by)
if page_utils.is_link_text_selector(selector) or by == By.LINK_TEXT:
if not self.is_link_text_visible(selector):
@ -148,7 +150,7 @@ class BaseCase(unittest.TestCase):
return
element = page_actions.wait_for_element_visible(
self.driver, selector, by, timeout=timeout)
self.__demo_mode_highlight_if_active(selector, by)
self.__demo_mode_highlight_if_active(original_selector, original_by)
if not self.demo_mode and not self.slow_mode:
self.__scroll_to_element(element, selector, by)
pre_action_url = self.driver.current_url
@ -226,10 +228,12 @@ class BaseCase(unittest.TestCase):
timeout = settings.SMALL_TIMEOUT
if self.timeout_multiplier and timeout == settings.SMALL_TIMEOUT:
timeout = self.__get_new_timeout(timeout)
original_selector = selector
original_by = by
selector, by = self.__recalculate_selector(selector, by)
element = page_actions.wait_for_element_visible(
self.driver, selector, by, timeout=timeout)
self.__demo_mode_highlight_if_active(selector, by)
self.__demo_mode_highlight_if_active(original_selector, original_by)
if not self.demo_mode and not self.slow_mode:
self.__scroll_to_element(element, selector, by)
pre_action_url = self.driver.current_url
@ -1289,13 +1293,15 @@ class BaseCase(unittest.TestCase):
"element {%s}!" % selector)
def hover_on_element(self, selector, by=By.CSS_SELECTOR):
original_selector = selector
original_by = by
selector, by = self.__recalculate_selector(selector, by)
if page_utils.is_xpath_selector(selector):
selector = self.convert_to_css_selector(selector, By.XPATH)
by = By.CSS_SELECTOR
self.wait_for_element_visible(
selector, by=by, timeout=settings.SMALL_TIMEOUT)
self.__demo_mode_highlight_if_active(selector, by)
self.__demo_mode_highlight_if_active(original_selector, original_by)
self.scroll_to(selector, by=by)
time.sleep(0.05) # Settle down from scrolling before hovering
if self.browser != "chrome":
@ -1339,6 +1345,8 @@ class BaseCase(unittest.TestCase):
timeout = settings.SMALL_TIMEOUT
if self.timeout_multiplier and timeout == settings.SMALL_TIMEOUT:
timeout = self.__get_new_timeout(timeout)
original_selector = hover_selector
original_by = hover_by
hover_selector, hover_by = self.__recalculate_selector(
hover_selector, hover_by)
hover_selector = self.convert_to_css_selector(
@ -1348,7 +1356,7 @@ class BaseCase(unittest.TestCase):
click_selector, click_by)
dropdown_element = self.wait_for_element_visible(
hover_selector, by=hover_by, timeout=timeout)
self.__demo_mode_highlight_if_active(hover_selector, hover_by)
self.__demo_mode_highlight_if_active(original_selector, original_by)
self.scroll_to(hover_selector, by=hover_by)
pre_action_url = self.driver.current_url
outdated_driver = False
@ -1400,6 +1408,8 @@ class BaseCase(unittest.TestCase):
timeout = settings.SMALL_TIMEOUT
if self.timeout_multiplier and timeout == settings.SMALL_TIMEOUT:
timeout = self.__get_new_timeout(timeout)
original_selector = hover_selector
original_by = hover_by
hover_selector, hover_by = self.__recalculate_selector(
hover_selector, hover_by)
hover_selector = self.convert_to_css_selector(
@ -1409,7 +1419,7 @@ class BaseCase(unittest.TestCase):
click_selector, click_by)
dropdown_element = self.wait_for_element_visible(
hover_selector, by=hover_by, timeout=timeout)
self.__demo_mode_highlight_if_active(hover_selector, hover_by)
self.__demo_mode_highlight_if_active(original_selector, original_by)
self.scroll_to(hover_selector, by=hover_by)
pre_action_url = self.driver.current_url
outdated_driver = False
@ -2239,7 +2249,7 @@ class BaseCase(unittest.TestCase):
(Default: 4. Each loop lasts for about 0.18s)
scroll - the option to scroll to the element first (Default: True)
"""
selector, by = self.__recalculate_selector(selector, by)
selector, by = self.__recalculate_selector(selector, by, xp_ok=False)
element = self.wait_for_element_visible(
selector, by=by, timeout=settings.SMALL_TIMEOUT)
if not loops:
@ -2464,7 +2474,7 @@ class BaseCase(unittest.TestCase):
def js_click(self, selector, by=By.CSS_SELECTOR, all_matches=False):
""" Clicks an element using JavaScript.
If "all_matches" is False, only the first match is clicked. """
selector, by = self.__recalculate_selector(selector, by)
selector, by = self.__recalculate_selector(selector, by, xp_ok=False)
if by == By.LINK_TEXT:
message = (
"Pure JavaScript doesn't support clicking by Link Text. "
@ -2504,7 +2514,7 @@ class BaseCase(unittest.TestCase):
def jquery_click(self, selector, by=By.CSS_SELECTOR):
""" Clicks an element using jQuery. Different from using pure JS. """
selector, by = self.__recalculate_selector(selector, by)
selector, by = self.__recalculate_selector(selector, by, xp_ok=False)
self.wait_for_element_present(
selector, by=by, timeout=settings.SMALL_TIMEOUT)
if self.is_element_visible(selector, by=by):
@ -2517,7 +2527,7 @@ class BaseCase(unittest.TestCase):
def jquery_click_all(self, selector, by=By.CSS_SELECTOR):
""" Clicks all matching elements using jQuery. """
selector, by = self.__recalculate_selector(selector, by)
selector, by = self.__recalculate_selector(selector, by, xp_ok=False)
self.wait_for_element_present(
selector, by=by, timeout=settings.SMALL_TIMEOUT)
if self.is_element_visible(selector, by=by):
@ -3137,7 +3147,7 @@ class BaseCase(unittest.TestCase):
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)
selector, by = self.__recalculate_selector(selector, by, xp_ok=False)
orginal_selector = selector
css_selector = self.convert_to_css_selector(selector, by=by)
self.__demo_mode_highlight_if_active(orginal_selector, by)
@ -3249,7 +3259,7 @@ class BaseCase(unittest.TestCase):
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)
selector, by = self.__recalculate_selector(selector, by, xp_ok=False)
element = self.wait_for_element_visible(
selector, by=by, timeout=timeout)
self.__demo_mode_highlight_if_active(selector, by)
@ -6063,8 +6073,10 @@ class BaseCase(unittest.TestCase):
pass
return False
def __recalculate_selector(self, selector, by):
# Use auto-detection to return the correct selector with "by" updated
def __recalculate_selector(self, selector, by, xp_ok=True):
""" Use autodetection to return the correct selector with "by" updated.
If "xp_ok" is False, don't call convert_css_to_xpath(), which is
used to make the ":contains()" selector valid outside JS calls. """
_type = type(selector) # First make sure the selector is a string
if _type is not str:
msg = 'Expecting a selector of type: "<class \'str\'>" (string)!'
@ -6081,9 +6093,10 @@ class BaseCase(unittest.TestCase):
name = page_utils.get_name_from_selector(selector)
selector = '[name="%s"]' % name
by = By.CSS_SELECTOR
if ":contains(" in selector and by == By.CSS_SELECTOR:
selector = self.convert_css_to_xpath(selector)
by = By.XPATH
if xp_ok:
if ":contains(" in selector and by == By.CSS_SELECTOR:
selector = self.convert_css_to_xpath(selector)
by = By.XPATH
return (selector, by)
def __looks_like_a_page_url(self, url):

View File

@ -90,7 +90,7 @@ class Messenger:
class Underscore:
VER = "1.10.2"
VER = "1.12.0"
MIN_JS = ("https://cdnjs.cloudflare.com/ajax/libs/"
"underscore.js/%s/underscore-min.js" % VER)

View File

@ -39,7 +39,7 @@ class ConvertibleToCssTranslator(GenericTranslator):
def xpath_class(self, class_selector):
xpath = self.xpath(class_selector.selector)
return self.xpath_attrib_equals(
return self.xpath_attrib_includes(
xpath, '@class', class_selector.class_name)
def xpath_descendant_combinator(self, left, right):

View File

@ -475,20 +475,30 @@ def activate_messenger(driver):
add_js_link(driver, underscore_js)
add_css_link(driver, spinner_css)
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)):
# Messenger needs a small amount of time to load & activate.
try:
driver.execute_script(msg_style)
wait_for_ready_state_complete(driver)
wait_for_angularjs(driver)
return
result = (driver.execute_script(
""" if (typeof Messenger === 'undefined') { return "U"; } """))
if result == "U":
time.sleep(0.01)
continue
else:
break
except Exception:
time.sleep(0.1)
time.sleep(0.01)
try:
driver.execute_script(msg_style)
add_js_link(driver, msgr_theme_flat_js)
add_js_link(driver, msgr_theme_future_js)
wait_for_ready_state_complete(driver)
wait_for_angularjs(driver)
return
except Exception:
time.sleep(0.1)
def set_messenger_theme(driver, theme="default", location="default",

View File

@ -49,7 +49,7 @@ if sys.argv[-1] == 'publish':
print("\n*** Installing twine: *** (Required for PyPI uploads)\n")
os.system("python -m pip install --upgrade 'twine>=1.15.0'")
print("\n*** Installing tqdm: *** (Required for PyPI uploads)\n")
os.system("python -m pip install --upgrade 'tqdm>=4.55.2'")
os.system("python -m pip install --upgrade 'tqdm>=4.56.0'")
print("\n*** Publishing The Release to PyPI: ***\n")
os.system('python -m twine upload dist/*') # Requires ~/.pypirc Keys
print("\n*** The Release was PUBLISHED SUCCESSFULLY to PyPI! :) ***\n")
@ -168,7 +168,7 @@ setup(
'colorama==0.4.4',
'pathlib2==2.3.5;python_version<"3.5"', # Sync with "virtualenv"
'importlib-metadata==2.0.0;python_version<"3.6"', # Sync "virtualenv"
'virtualenv>=20.2.2', # Sync with importlib-metadata and pathlib2
'virtualenv>=20.3.0', # Sync with importlib-metadata and pathlib2
'pymysql==0.10.1;python_version<"3.6"',
'pymysql==1.0.2;python_version>="3.6"',
'coverage==5.3.1',
@ -180,7 +180,7 @@ setup(
'Pillow==6.2.2;python_version<"3.5"',
'Pillow==7.2.0;python_version>="3.5" and python_version<"3.6"',
'Pillow==8.1.0;python_version>="3.6"',
'rich==9.7.0;python_version>="3.6" and python_version<"4.0"',
'rich==9.8.0;python_version>="3.6" and python_version<"4.0"',
'zipp==1.2.0;python_version<"3.6"',
'zipp==3.4.0;python_version>="3.6"',
'flake8==3.7.9;python_version<"3.5"',