Skip to content

Demo Mode updates and more #780

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 9 commits into from
Jan 12, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion docs/requirements.txt
Original file line number Diff line number Diff line change
@@ -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
Expand Down
25 changes: 14 additions & 11 deletions examples/presenter/core_presentation.py
Original file line number Diff line number Diff line change
Expand Up @@ -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'
Expand All @@ -27,20 +27,23 @@ def test_seleniumbase_chart(self):
' 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'
Expand All @@ -57,7 +60,7 @@ def test_seleniumbase_chart(self):
'$ 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'
Expand Down
4 changes: 2 additions & 2 deletions integrations/node_js/ReadMe.md
Original file line number Diff line number Diff line change
@@ -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" />

Expand Down
7 changes: 4 additions & 3 deletions mkdocs.yml
Original file line number Diff line number Diff line change
@@ -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.
Expand Down Expand Up @@ -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
Expand All @@ -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
Expand Down Expand Up @@ -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
Expand Down
4 changes: 2 additions & 2 deletions requirements.txt
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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"
Expand Down
2 changes: 1 addition & 1 deletion seleniumbase/__version__.py
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
# seleniumbase package
__version__ = "1.51.14"
__version__ = "1.52.0"
45 changes: 29 additions & 16 deletions seleniumbase/fixtures/base_case.py
Original file line number Diff line number Diff line change
Expand Up @@ -134,6 +134,8 @@ def click(self, selector, by=By.CSS_SELECTOR, timeout=None, delay=0):
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):
Expand All @@ -148,7 +150,7 @@ def click(self, selector, by=By.CSS_SELECTOR, timeout=None, delay=0):
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
Expand Down Expand Up @@ -226,10 +228,12 @@ def double_click(self, selector, by=By.CSS_SELECTOR, timeout=None):
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
Expand Down Expand Up @@ -1289,13 +1293,15 @@ def switch_to_frame_of_element(self, selector, by=By.CSS_SELECTOR):
"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":
Expand Down Expand Up @@ -1339,6 +1345,8 @@ def hover_and_click(self, hover_selector, click_selector,
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(
Expand All @@ -1348,7 +1356,7 @@ def hover_and_click(self, hover_selector, click_selector,
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
Expand Down Expand Up @@ -1400,6 +1408,8 @@ def hover_and_double_click(self, hover_selector, click_selector,
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(
Expand All @@ -1409,7 +1419,7 @@ def hover_and_double_click(self, hover_selector, click_selector,
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
Expand Down Expand Up @@ -2239,7 +2249,7 @@ def highlight(self, selector, by=By.CSS_SELECTOR,
(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:
Expand Down Expand Up @@ -2464,7 +2474,7 @@ def click_xpath(self, xpath):
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. "
Expand Down Expand Up @@ -2504,7 +2514,7 @@ def js_click_all(self, selector, by=By.CSS_SELECTOR):

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):
Expand All @@ -2517,7 +2527,7 @@ def jquery_click(self, selector, by=By.CSS_SELECTOR):

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):
Expand Down Expand Up @@ -3137,7 +3147,7 @@ def set_value(self, selector, text, by=By.CSS_SELECTOR, timeout=None):
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)
Expand Down Expand Up @@ -3249,7 +3259,7 @@ def jquery_update_text(self, selector, text, by=By.CSS_SELECTOR,
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)
Expand Down Expand Up @@ -6063,8 +6073,10 @@ def __click_dropdown_partial_link_text(self, link_text, link_css):
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)!'
Expand All @@ -6081,9 +6093,10 @@ def __recalculate_selector(self, selector, by):
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):
Expand Down
2 changes: 1 addition & 1 deletion seleniumbase/fixtures/constants.py
Original file line number Diff line number Diff line change
Expand Up @@ -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)

Expand Down
2 changes: 1 addition & 1 deletion seleniumbase/fixtures/css_to_xpath.py
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ def xpath_attrib_substringmatch(self, xpath, name, value):

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):
Expand Down
24 changes: 17 additions & 7 deletions seleniumbase/fixtures/js_utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -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",
Expand Down
6 changes: 3 additions & 3 deletions setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@
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")
Expand Down Expand Up @@ -168,7 +168,7 @@
'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',
Expand All @@ -180,7 +180,7 @@
'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"',
Expand Down