Skip to content

Commit e489ac2

Browse files
authored
Merge pull request #780 from seleniumbase/demo-mode-updates-and-more
Demo Mode updates and more
2 parents 224e019 + 876b2c0 commit e489ac2

File tree

11 files changed

+75
-48
lines changed

11 files changed

+75
-48
lines changed

docs/requirements.txt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
regex>=2020.11.13
2-
tqdm>=4.55.2
2+
tqdm>=4.56.0
33
livereload==2.6.3;python_version>="3.6"
44
Markdown==3.3.3
55
readme-renderer==28.0

examples/presenter/core_presentation.py

Lines changed: 14 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -5,14 +5,14 @@ class MyChartMakerClass(BaseCase):
55

66
def test_seleniumbase_chart(self):
77
self.create_presentation(theme="league", transition="slide")
8-
self.create_pie_chart(title="There are 4 core areas of SeleniumBase:")
9-
self.add_data_point("Basic API (Test methods/functions)", 1)
10-
self.add_data_point("Command-line Options (pytest Options)", 1)
8+
self.create_pie_chart(title="The 4 core areas of SeleniumBase:")
9+
self.add_data_point("Basic API (test methods)", 1)
10+
self.add_data_point("Command-line options (pytest options)", 1)
1111
self.add_data_point("The Console Scripts interface", 1)
1212
self.add_data_point("Advanced API (Tours, Charts, & Presentations)", 1)
1313
self.add_slide("<p>SeleniumBase core areas</p>" + self.extract_chart())
1414
self.add_slide(
15-
"<p>Basic API (Test methods/functions) Example</p>",
15+
"<p>Basic API (test methods). Example test:</p>",
1616
code=(
1717
'from seleniumbase import BaseCase\n\n'
1818
'class MyTestClass(BaseCase):\n\n'
@@ -27,20 +27,23 @@ def test_seleniumbase_chart(self):
2727
' self.click_link_text("comic #249")\n'
2828
' self.assert_element(\'img[alt*="Chess"]\')\n'))
2929
self.add_slide(
30-
"<p>Command-line Options Example</p>",
30+
"<p>Command-line options. Examples:</p>",
3131
code=(
3232
'$ pytest my_first_test.py\n'
3333
'$ pytest test_swag_labs.py --mobile\n'
3434
'$ pytest edge_test.py --browser=edge\n'
3535
'$ pytest basic_test.py --headless\n'
36-
'$ pytest my_first_test.py --demo\n'
36+
'$ pytest my_first_test.py --demo --guest\n'
3737
'$ pytest basic_test.py --slow\n'
3838
'$ pytest -v -m marker2 --headless --save-screenshot\n'
39-
'$ pytest test_suite.py --reuse-session --html=report.html\n'
40-
'$ pytest basic_test.py --incognito\n'
41-
'$ pytest parameterized_test.py --guest --reuse-session\n'))
39+
'$ pytest parameterized_test.py --reuse-session\n'
40+
'$ pytest test_suite.py --html=report.html --rs\n'
41+
'$ pytest test_suite.py --dashboard --html=report.html\n'
42+
'$ pytest github_test.py --demo --disable-csp\n'
43+
'$ pytest test_suite.py -n=2 --rs --crumbs\n'
44+
'$ pytest basic_test.py --incognito\n'))
4245
self.add_slide(
43-
"<p>Console scripts interface Example</p>",
46+
"<p>The Console Scripts interface. Examples:</p>",
4447
code=(
4548
'$ sbase install chromedriver\n'
4649
'$ sbase install chromedriver latest\n'
@@ -57,7 +60,7 @@ def test_seleniumbase_chart(self):
5760
'$ sbase grid-hub stop\n'
5861
'$ sbase options\n'))
5962
self.add_slide(
60-
'<p>Advanced API (creating a presentation) Example</p>',
63+
'<p>Advanced API. "Presenter" example:</p>',
6164
code=(
6265
'from seleniumbase import BaseCase\n\n'
6366
'class MyPresenterClass(BaseCase):\n\n'

integrations/node_js/ReadMe.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
1-
<h2><img src="https://seleniumbase.io/img/sb_icon.png" title="SeleniumBase" width="30" /> Creating a SeleniumBase Test Runner with NodeJS</h2>
1+
<h2><img src="https://seleniumbase.io/img/sb_icon.png" title="SeleniumBase" width="30" /> Creating a Test Runner with NodeJS + Express</h2>
22

3-
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.)
3+
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.)
44

55
<img src="https://seleniumbase.io/other/node_runner.png" title="Node Runner" />
66

mkdocs.yml

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
# Project information
2-
site_name: SeleniumBase
2+
site_name: SeleniumBase / Docs
33
site_url: https://seleniumbase.io
44
site_author: Michael Mintz
55
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:
3030
sticky_navigation: true
3131
language: en
3232
include_search_page: false
33-
search_index_only: true
33+
search_index_only: false
3434
features:
3535
- tabs
3636
- instant
@@ -53,7 +53,7 @@ plugins:
5353
on_pre_build: docs.prepare:main
5454
# Page tree
5555
nav:
56-
- SeleniumBase | README: README.md
56+
- SeleniumBase / README: README.md
5757
- Features List: help_docs/features_list.md
5858
- Running Example Tests: examples/ReadMe.md
5959
- Command Line Options: help_docs/customizing_test_runs.md
@@ -104,6 +104,7 @@ nav:
104104
- TinyMCE Demo Page: https://seleniumbase.io/other/tinymce
105105
- Virtual Device Farm: https://seleniumbase.io/devices/
106106
- Error Demo Page: https://seleniumbase.io/error_page/
107+
- Presentations:
107108
- Presenter Demo: https://seleniumbase.io/other/presenter.html
108109
- Core Presentation: https://seleniumbase.io/other/core_presentation.html
109110
- Chart Maker Demo: https://seleniumbase.io/other/chart_presentation.html

requirements.txt

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -64,7 +64,7 @@ ipython==7.19.0;python_version>="3.7"
6464
colorama==0.4.4
6565
pathlib2==2.3.5;python_version<"3.5"
6666
importlib-metadata==2.0.0;python_version<"3.6"
67-
virtualenv>=20.2.2
67+
virtualenv>=20.3.0
6868
pymysql==0.10.1;python_version<"3.6"
6969
pymysql==1.0.2;python_version>="3.6"
7070
coverage==5.3.1
@@ -76,7 +76,7 @@ toml==0.10.2
7676
Pillow==6.2.2;python_version<"3.5"
7777
Pillow==7.2.0;python_version>="3.5" and python_version<"3.6"
7878
Pillow==8.1.0;python_version>="3.6"
79-
rich==9.7.0;python_version>="3.6" and python_version<"4.0"
79+
rich==9.8.0;python_version>="3.6" and python_version<"4.0"
8080
zipp==1.2.0;python_version<"3.6"
8181
zipp==3.4.0;python_version>="3.6"
8282
flake8==3.7.9;python_version<"3.5"

seleniumbase/__version__.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,2 @@
11
# seleniumbase package
2-
__version__ = "1.51.14"
2+
__version__ = "1.52.0"

seleniumbase/fixtures/base_case.py

Lines changed: 29 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -134,6 +134,8 @@ def click(self, selector, by=By.CSS_SELECTOR, timeout=None, delay=0):
134134
timeout = settings.SMALL_TIMEOUT
135135
if self.timeout_multiplier and timeout == settings.SMALL_TIMEOUT:
136136
timeout = self.__get_new_timeout(timeout)
137+
original_selector = selector
138+
original_by = by
137139
selector, by = self.__recalculate_selector(selector, by)
138140
if page_utils.is_link_text_selector(selector) or by == By.LINK_TEXT:
139141
if not self.is_link_text_visible(selector):
@@ -148,7 +150,7 @@ def click(self, selector, by=By.CSS_SELECTOR, timeout=None, delay=0):
148150
return
149151
element = page_actions.wait_for_element_visible(
150152
self.driver, selector, by, timeout=timeout)
151-
self.__demo_mode_highlight_if_active(selector, by)
153+
self.__demo_mode_highlight_if_active(original_selector, original_by)
152154
if not self.demo_mode and not self.slow_mode:
153155
self.__scroll_to_element(element, selector, by)
154156
pre_action_url = self.driver.current_url
@@ -226,10 +228,12 @@ def double_click(self, selector, by=By.CSS_SELECTOR, timeout=None):
226228
timeout = settings.SMALL_TIMEOUT
227229
if self.timeout_multiplier and timeout == settings.SMALL_TIMEOUT:
228230
timeout = self.__get_new_timeout(timeout)
231+
original_selector = selector
232+
original_by = by
229233
selector, by = self.__recalculate_selector(selector, by)
230234
element = page_actions.wait_for_element_visible(
231235
self.driver, selector, by, timeout=timeout)
232-
self.__demo_mode_highlight_if_active(selector, by)
236+
self.__demo_mode_highlight_if_active(original_selector, original_by)
233237
if not self.demo_mode and not self.slow_mode:
234238
self.__scroll_to_element(element, selector, by)
235239
pre_action_url = self.driver.current_url
@@ -1289,13 +1293,15 @@ def switch_to_frame_of_element(self, selector, by=By.CSS_SELECTOR):
12891293
"element {%s}!" % selector)
12901294

12911295
def hover_on_element(self, selector, by=By.CSS_SELECTOR):
1296+
original_selector = selector
1297+
original_by = by
12921298
selector, by = self.__recalculate_selector(selector, by)
12931299
if page_utils.is_xpath_selector(selector):
12941300
selector = self.convert_to_css_selector(selector, By.XPATH)
12951301
by = By.CSS_SELECTOR
12961302
self.wait_for_element_visible(
12971303
selector, by=by, timeout=settings.SMALL_TIMEOUT)
1298-
self.__demo_mode_highlight_if_active(selector, by)
1304+
self.__demo_mode_highlight_if_active(original_selector, original_by)
12991305
self.scroll_to(selector, by=by)
13001306
time.sleep(0.05) # Settle down from scrolling before hovering
13011307
if self.browser != "chrome":
@@ -1339,6 +1345,8 @@ def hover_and_click(self, hover_selector, click_selector,
13391345
timeout = settings.SMALL_TIMEOUT
13401346
if self.timeout_multiplier and timeout == settings.SMALL_TIMEOUT:
13411347
timeout = self.__get_new_timeout(timeout)
1348+
original_selector = hover_selector
1349+
original_by = hover_by
13421350
hover_selector, hover_by = self.__recalculate_selector(
13431351
hover_selector, hover_by)
13441352
hover_selector = self.convert_to_css_selector(
@@ -1348,7 +1356,7 @@ def hover_and_click(self, hover_selector, click_selector,
13481356
click_selector, click_by)
13491357
dropdown_element = self.wait_for_element_visible(
13501358
hover_selector, by=hover_by, timeout=timeout)
1351-
self.__demo_mode_highlight_if_active(hover_selector, hover_by)
1359+
self.__demo_mode_highlight_if_active(original_selector, original_by)
13521360
self.scroll_to(hover_selector, by=hover_by)
13531361
pre_action_url = self.driver.current_url
13541362
outdated_driver = False
@@ -1400,6 +1408,8 @@ def hover_and_double_click(self, hover_selector, click_selector,
14001408
timeout = settings.SMALL_TIMEOUT
14011409
if self.timeout_multiplier and timeout == settings.SMALL_TIMEOUT:
14021410
timeout = self.__get_new_timeout(timeout)
1411+
original_selector = hover_selector
1412+
original_by = hover_by
14031413
hover_selector, hover_by = self.__recalculate_selector(
14041414
hover_selector, hover_by)
14051415
hover_selector = self.convert_to_css_selector(
@@ -1409,7 +1419,7 @@ def hover_and_double_click(self, hover_selector, click_selector,
14091419
click_selector, click_by)
14101420
dropdown_element = self.wait_for_element_visible(
14111421
hover_selector, by=hover_by, timeout=timeout)
1412-
self.__demo_mode_highlight_if_active(hover_selector, hover_by)
1422+
self.__demo_mode_highlight_if_active(original_selector, original_by)
14131423
self.scroll_to(hover_selector, by=hover_by)
14141424
pre_action_url = self.driver.current_url
14151425
outdated_driver = False
@@ -2239,7 +2249,7 @@ def highlight(self, selector, by=By.CSS_SELECTOR,
22392249
(Default: 4. Each loop lasts for about 0.18s)
22402250
scroll - the option to scroll to the element first (Default: True)
22412251
"""
2242-
selector, by = self.__recalculate_selector(selector, by)
2252+
selector, by = self.__recalculate_selector(selector, by, xp_ok=False)
22432253
element = self.wait_for_element_visible(
22442254
selector, by=by, timeout=settings.SMALL_TIMEOUT)
22452255
if not loops:
@@ -2464,7 +2474,7 @@ def click_xpath(self, xpath):
24642474
def js_click(self, selector, by=By.CSS_SELECTOR, all_matches=False):
24652475
""" Clicks an element using JavaScript.
24662476
If "all_matches" is False, only the first match is clicked. """
2467-
selector, by = self.__recalculate_selector(selector, by)
2477+
selector, by = self.__recalculate_selector(selector, by, xp_ok=False)
24682478
if by == By.LINK_TEXT:
24692479
message = (
24702480
"Pure JavaScript doesn't support clicking by Link Text. "
@@ -2504,7 +2514,7 @@ def js_click_all(self, selector, by=By.CSS_SELECTOR):
25042514

25052515
def jquery_click(self, selector, by=By.CSS_SELECTOR):
25062516
""" Clicks an element using jQuery. Different from using pure JS. """
2507-
selector, by = self.__recalculate_selector(selector, by)
2517+
selector, by = self.__recalculate_selector(selector, by, xp_ok=False)
25082518
self.wait_for_element_present(
25092519
selector, by=by, timeout=settings.SMALL_TIMEOUT)
25102520
if self.is_element_visible(selector, by=by):
@@ -2517,7 +2527,7 @@ def jquery_click(self, selector, by=By.CSS_SELECTOR):
25172527

25182528
def jquery_click_all(self, selector, by=By.CSS_SELECTOR):
25192529
""" Clicks all matching elements using jQuery. """
2520-
selector, by = self.__recalculate_selector(selector, by)
2530+
selector, by = self.__recalculate_selector(selector, by, xp_ok=False)
25212531
self.wait_for_element_present(
25222532
selector, by=by, timeout=settings.SMALL_TIMEOUT)
25232533
if self.is_element_visible(selector, by=by):
@@ -3137,7 +3147,7 @@ def set_value(self, selector, text, by=By.CSS_SELECTOR, timeout=None):
31373147
timeout = settings.LARGE_TIMEOUT
31383148
if self.timeout_multiplier and timeout == settings.LARGE_TIMEOUT:
31393149
timeout = self.__get_new_timeout(timeout)
3140-
selector, by = self.__recalculate_selector(selector, by)
3150+
selector, by = self.__recalculate_selector(selector, by, xp_ok=False)
31413151
orginal_selector = selector
31423152
css_selector = self.convert_to_css_selector(selector, by=by)
31433153
self.__demo_mode_highlight_if_active(orginal_selector, by)
@@ -3249,7 +3259,7 @@ def jquery_update_text(self, selector, text, by=By.CSS_SELECTOR,
32493259
timeout = settings.LARGE_TIMEOUT
32503260
if self.timeout_multiplier and timeout == settings.LARGE_TIMEOUT:
32513261
timeout = self.__get_new_timeout(timeout)
3252-
selector, by = self.__recalculate_selector(selector, by)
3262+
selector, by = self.__recalculate_selector(selector, by, xp_ok=False)
32533263
element = self.wait_for_element_visible(
32543264
selector, by=by, timeout=timeout)
32553265
self.__demo_mode_highlight_if_active(selector, by)
@@ -6063,8 +6073,10 @@ def __click_dropdown_partial_link_text(self, link_text, link_css):
60636073
pass
60646074
return False
60656075

6066-
def __recalculate_selector(self, selector, by):
6067-
# Use auto-detection to return the correct selector with "by" updated
6076+
def __recalculate_selector(self, selector, by, xp_ok=True):
6077+
""" Use autodetection to return the correct selector with "by" updated.
6078+
If "xp_ok" is False, don't call convert_css_to_xpath(), which is
6079+
used to make the ":contains()" selector valid outside JS calls. """
60686080
_type = type(selector) # First make sure the selector is a string
60696081
if _type is not str:
60706082
msg = 'Expecting a selector of type: "<class \'str\'>" (string)!'
@@ -6081,9 +6093,10 @@ def __recalculate_selector(self, selector, by):
60816093
name = page_utils.get_name_from_selector(selector)
60826094
selector = '[name="%s"]' % name
60836095
by = By.CSS_SELECTOR
6084-
if ":contains(" in selector and by == By.CSS_SELECTOR:
6085-
selector = self.convert_css_to_xpath(selector)
6086-
by = By.XPATH
6096+
if xp_ok:
6097+
if ":contains(" in selector and by == By.CSS_SELECTOR:
6098+
selector = self.convert_css_to_xpath(selector)
6099+
by = By.XPATH
60876100
return (selector, by)
60886101

60896102
def __looks_like_a_page_url(self, url):

seleniumbase/fixtures/constants.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -90,7 +90,7 @@ class Messenger:
9090

9191

9292
class Underscore:
93-
VER = "1.10.2"
93+
VER = "1.12.0"
9494
MIN_JS = ("https://cdnjs.cloudflare.com/ajax/libs/"
9595
"underscore.js/%s/underscore-min.js" % VER)
9696

seleniumbase/fixtures/css_to_xpath.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,7 @@ def xpath_attrib_substringmatch(self, xpath, name, value):
3939

4040
def xpath_class(self, class_selector):
4141
xpath = self.xpath(class_selector.selector)
42-
return self.xpath_attrib_equals(
42+
return self.xpath_attrib_includes(
4343
xpath, '@class', class_selector.class_name)
4444

4545
def xpath_descendant_combinator(self, left, right):

seleniumbase/fixtures/js_utils.py

Lines changed: 17 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -475,20 +475,30 @@ def activate_messenger(driver):
475475
add_js_link(driver, underscore_js)
476476
add_css_link(driver, spinner_css)
477477
add_js_link(driver, messenger_js)
478-
add_js_link(driver, msgr_theme_flat_js)
479-
add_js_link(driver, msgr_theme_future_js)
480478
from seleniumbase.core import style_sheet
481479
add_css_style(driver, style_sheet.messenger_style)
482480

483481
for x in range(int(settings.MINI_TIMEOUT * 10.0)):
484482
# Messenger needs a small amount of time to load & activate.
485483
try:
486-
driver.execute_script(msg_style)
487-
wait_for_ready_state_complete(driver)
488-
wait_for_angularjs(driver)
489-
return
484+
result = (driver.execute_script(
485+
""" if (typeof Messenger === 'undefined') { return "U"; } """))
486+
if result == "U":
487+
time.sleep(0.01)
488+
continue
489+
else:
490+
break
490491
except Exception:
491-
time.sleep(0.1)
492+
time.sleep(0.01)
493+
try:
494+
driver.execute_script(msg_style)
495+
add_js_link(driver, msgr_theme_flat_js)
496+
add_js_link(driver, msgr_theme_future_js)
497+
wait_for_ready_state_complete(driver)
498+
wait_for_angularjs(driver)
499+
return
500+
except Exception:
501+
time.sleep(0.1)
492502

493503

494504
def set_messenger_theme(driver, theme="default", location="default",

0 commit comments

Comments
 (0)