Skip to content

Commit 78bbf83

Browse files
authored
Merge pull request #364 from seleniumbase/updates-and-fixes
Updates and fixes
2 parents 7516540 + a3ac4d4 commit 78bbf83

File tree

7 files changed

+131
-37
lines changed

7 files changed

+131
-37
lines changed

help_docs/method_summary.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -230,6 +230,9 @@ self.hover_on_element(selector, by=By.CSS_SELECTOR)
230230
self.hover_and_click(hover_selector, click_selector,
231231
hover_by=By.CSS_SELECTOR, click_by=By.CSS_SELECTOR, timeout=settings.SMALL_TIMEOUT)
232232

233+
self.hover_and_double_click(hover_selector, click_selector,
234+
hover_by=By.CSS_SELECTOR, click_by=By.CSS_SELECTOR, timeout=settings.SMALL_TIMEOUT)
235+
233236
self.select_option_by_text(dropdown_selector, option,
234237
dropdown_by=By.CSS_SELECTOR, timeout=settings.SMALL_TIMEOUT)
235238

requirements.txt

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
1-
pip>=19.2.2
2-
setuptools>=41.1.0
3-
wheel>=0.33.4
1+
pip>=19.2.3
2+
setuptools>=41.2.0
3+
wheel>=0.33.6
44
six>=1.12.0
55
nose>=1.3.7
66
ipdb>=0.12.2
@@ -11,7 +11,7 @@ requests>=2.22.0
1111
selenium==3.141.0
1212
pluggy>=0.12.0
1313
pytest>=4.6.5;python_version<"3"
14-
pytest>=5.1.0;python_version>="3"
14+
pytest>=5.1.2;python_version>="3"
1515
pytest-cov>=2.7.1
1616
pytest-forked>=1.0.2
1717
pytest-html==1.22.0

seleniumbase/console_scripts/run.py

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,7 @@ def show_basic_usage():
3737
print("")
3838
print('Usage: "seleniumbase [COMMAND] [PARAMETERS]"')
3939
print("Commands:")
40-
print(" install [DRIVER_NAME]")
40+
print(" install [DRIVER_NAME] [OPTIONS]")
4141
print(" mkdir [NEW_TEST_DIRECTORY_NAME]")
4242
print(" convert [PYTHON_WEBDRIVER_UNITTEST_FILE]")
4343
print(" extract-objects [SELENIUMBASE_PYTHON_FILE]")
@@ -55,11 +55,18 @@ def show_install_usage():
5555
print(" ** install **")
5656
print("")
5757
print(" Usage:")
58-
print(" seleniumbase install [DRIVER_NAME]")
58+
print(" seleniumbase install [DRIVER_NAME] [OPTIONS]")
5959
print(" (Drivers: chromedriver, geckodriver, edgedriver")
6060
print(" iedriver, operadriver)")
61+
print(" Options:")
62+
print(" VERSION - Specify the version (For Chromedriver ONLY).")
63+
print(" (Default Chromedriver version = 2.44)")
64+
print(' Use "latest" to get the latest Chromedriver.')
6165
print(" Example:")
6266
print(" seleniumbase install chromedriver")
67+
print(" seleniumbase install chromedriver 76.0.3809.126")
68+
print(" seleniumbase install chromedriver latest")
69+
print(" seleniumbase install geckodriver")
6370
print(" Output:")
6471
print(" Installs the specified webdriver.")
6572
print(" (chromedriver is required for Chrome automation)")

seleniumbase/console_scripts/sb_install.py

Lines changed: 49 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,16 @@
33
44
Usage:
55
seleniumbase install {chromedriver|geckodriver|edgedriver|
6-
iedriver|operadriver}
6+
iedriver|operadriver} [OPTIONS]
7+
Options:
8+
VERSION - Specify the version (For Chromedriver ONLY)
9+
(Default Chromedriver version = 2.44)
10+
Use "latest" to get the latest Chromedriver.
11+
Example:
12+
seleniumbase install chromedriver
13+
seleniumbase install chromedriver 76.0.3809.126
14+
seleniumbase install chromedriver latest
15+
seleniumbase install geckodriver
716
Output:
817
Installs the specified webdriver.
918
(chromedriver is required for Chrome automation)
@@ -24,16 +33,24 @@
2433
from seleniumbase import drivers # webdriver storage folder for SeleniumBase
2534
urllib3.disable_warnings()
2635
DRIVER_DIR = os.path.dirname(os.path.realpath(drivers.__file__))
36+
DEFAULT_CHROMEDRIVER_VERSION = "2.44"
2737

2838

2939
def invalid_run_command():
3040
exp = (" ** install **\n\n")
3141
exp += " Usage:\n"
32-
exp += " seleniumbase install [DRIVER_NAME]\n"
42+
exp += " seleniumbase install [DRIVER_NAME] [OPTIONS]\n"
3343
exp += " (Drivers: chromedriver, geckodriver, edgedriver,\n"
3444
exp += " iedriver, operadriver)\n"
45+
exp += " Options:\n"
46+
exp += " VERSION - Specify the version (For Chromedriver ONLY)."
47+
exp += " (Default Chromedriver version = 2.44)"
48+
exp += ' Use "latest" to get the latest Chromedriver.'
3549
exp += " Example:\n"
3650
exp += " seleniumbase install chromedriver\n"
51+
exp += " seleniumbase install chromedriver 76.0.3809.126\n"
52+
exp += " seleniumbase install chromedriver latest\n"
53+
exp += " seleniumbase install geckodriver\n"
3754
exp += " Output:\n"
3855
exp += " Installs the specified webdriver.\n"
3956
exp += " (chromedriver is required for Chrome automation)\n"
@@ -56,11 +73,11 @@ def main():
5673
num_args = len(sys.argv)
5774
if sys.argv[0].split('/')[-1].lower() == "seleniumbase" or (
5875
sys.argv[0].split('\\')[-1].lower() == "seleniumbase"):
59-
if num_args < 3 or num_args > 3:
76+
if num_args < 3 or num_args > 4:
6077
invalid_run_command()
6178
else:
6279
invalid_run_command()
63-
name = sys.argv[num_args - 1].lower()
80+
name = sys.argv[2].lower()
6481

6582
file_name = None
6683
download_url = None
@@ -71,52 +88,56 @@ def main():
7188
inner_folder = None
7289

7390
if name == "chromedriver":
74-
latest_version = "2.44" # It's not the latest, but most compatible
91+
use_version = DEFAULT_CHROMEDRIVER_VERSION
92+
get_latest = False
93+
if num_args == 4:
94+
use_version = sys.argv[3]
95+
if use_version.lower() == "latest":
96+
get_latest = True
7597
if "darwin" in sys_plat:
7698
file_name = "chromedriver_mac64.zip"
7799
elif "linux" in sys_plat:
78-
latest_version = "2.44" # Linux machines may need the old driver
79100
file_name = "chromedriver_linux64.zip"
80101
elif "win32" in sys_plat or "win64" in sys_plat or "x64" in sys_plat:
81102
file_name = "chromedriver_win32.zip" # Works for win32 / win_x64
82103
else:
83104
raise Exception("Cannot determine which version of Chromedriver "
84105
"to download!")
85-
download_url = ("http://chromedriver.storage.googleapis.com/"
86-
"%s/%s" % (latest_version, file_name))
87-
# Forcing Chromedriver v2.40 for now, even though it's not the latest.
88-
get_latest = False
106+
found_chromedriver = False
89107
if get_latest:
90108
last = "http://chromedriver.storage.googleapis.com/LATEST_RELEASE"
91-
print('\nLocating the latest version of Chromedriver...')
92-
latest_version = requests.get(last).text
93-
if not requests.get(download_url).ok:
94-
fallback_version = "2.44"
95-
download_url = ("http://chromedriver.storage.googleapis.com/"
96-
"%s/%s" % (fallback_version, file_name))
97-
else:
98-
download_url = ("http://chromedriver.storage.googleapis.com/"
99-
"%s/%s" % (latest_version, file_name))
100-
print("Found %s" % download_url)
109+
url_request = requests.get(last)
110+
if url_request.ok:
111+
found_chromedriver = True
112+
use_version = url_request.text
113+
download_url = ("http://chromedriver.storage.googleapis.com/"
114+
"%s/%s" % (use_version, file_name))
115+
url_request = None
116+
if not found_chromedriver:
117+
url_request = requests.get(download_url)
118+
if found_chromedriver or url_request.ok:
119+
print("\nChromedriver version for download = %s" % use_version)
120+
else:
121+
raise Exception("Could not find Chromedriver to download!\n")
101122
elif name == "geckodriver" or name == "firefoxdriver":
102-
latest_version = "v0.24.0"
123+
use_version = "v0.24.0"
103124
if "darwin" in sys_plat:
104-
file_name = "geckodriver-%s-macos.tar.gz" % latest_version
125+
file_name = "geckodriver-%s-macos.tar.gz" % use_version
105126
elif "linux" in sys_plat:
106127
arch = platform.architecture()[0]
107128
if "64" in arch:
108-
file_name = "geckodriver-%s-linux64.tar.gz" % latest_version
129+
file_name = "geckodriver-%s-linux64.tar.gz" % use_version
109130
else:
110-
file_name = "geckodriver-%s-linux32.tar.gz" % latest_version
131+
file_name = "geckodriver-%s-linux32.tar.gz" % use_version
111132
elif "win32" in sys_plat or "win64" in sys_plat or "x64" in sys_plat:
112-
file_name = "geckodriver-%s-win64.zip" % latest_version
133+
file_name = "geckodriver-%s-win64.zip" % use_version
113134
else:
114135
raise Exception("Cannot determine which version of Geckodriver "
115136
"(Firefox Driver) to download!")
116137

117138
download_url = ("https://github.com/mozilla/geckodriver/"
118139
"releases/download/"
119-
"%s/%s" % (latest_version, file_name))
140+
"%s/%s" % (use_version, file_name))
120141
elif name == "edgedriver" or name == "microsoftwebdriver":
121142
name = "edgedriver"
122143
version_code = "F/8/A/F8AF50AB-3C3A-4BC4-8773-DC27B32988DD"
@@ -141,7 +162,7 @@ def main():
141162
"%s/%s" % (major_version, file_name))
142163
elif name == "operadriver" or name == "operachromiumdriver":
143164
name = "operadriver"
144-
latest_version = "v.2.40"
165+
use_version = "v.2.40"
145166
if "darwin" in sys_plat:
146167
file_name = "operadriver_mac64.zip"
147168
platform_code = "mac64"
@@ -176,7 +197,7 @@ def main():
176197

177198
download_url = ("https://github.com/operasoftware/operachromiumdriver/"
178199
"releases/download/"
179-
"%s/%s" % (latest_version, file_name))
200+
"%s/%s" % (use_version, file_name))
180201
else:
181202
invalid_run_command()
182203

seleniumbase/fixtures/base_case.py

Lines changed: 39 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -177,7 +177,7 @@ def slow_click(self, selector, by=By.CSS_SELECTOR,
177177

178178
def double_click(self, selector, by=By.CSS_SELECTOR,
179179
timeout=settings.SMALL_TIMEOUT):
180-
from selenium.webdriver import ActionChains
180+
from selenium.webdriver.common.action_chains import ActionChains
181181
if self.timeout_multiplier and timeout == settings.SMALL_TIMEOUT:
182182
timeout = self.__get_new_timeout(timeout)
183183
if page_utils.is_xpath_selector(selector):
@@ -1962,6 +1962,8 @@ def hover_on_element(self, selector, by=By.CSS_SELECTOR):
19621962
def hover_and_click(self, hover_selector, click_selector,
19631963
hover_by=By.CSS_SELECTOR, click_by=By.CSS_SELECTOR,
19641964
timeout=settings.SMALL_TIMEOUT):
1965+
""" When you want to hover over an element or dropdown menu,
1966+
and then click an element that appears after that. """
19651967
if self.timeout_multiplier and timeout == settings.SMALL_TIMEOUT:
19661968
timeout = self.__get_new_timeout(timeout)
19671969
hover_selector, hover_by = self.__recalculate_selector(
@@ -1985,6 +1987,35 @@ def hover_and_click(self, hover_selector, click_selector,
19851987
self.__demo_mode_pause_if_active(tiny=True)
19861988
return element
19871989

1990+
def hover_and_double_click(self, hover_selector, click_selector,
1991+
hover_by=By.CSS_SELECTOR,
1992+
click_by=By.CSS_SELECTOR,
1993+
timeout=settings.SMALL_TIMEOUT):
1994+
""" When you want to hover over an element or dropdown menu,
1995+
and then double-click an element that appears after that. """
1996+
if self.timeout_multiplier and timeout == settings.SMALL_TIMEOUT:
1997+
timeout = self.__get_new_timeout(timeout)
1998+
hover_selector, hover_by = self.__recalculate_selector(
1999+
hover_selector, hover_by)
2000+
hover_selector = self.convert_to_css_selector(
2001+
hover_selector, hover_by)
2002+
click_selector, click_by = self.__recalculate_selector(
2003+
click_selector, click_by)
2004+
hover_element = self.wait_for_element_visible(
2005+
hover_selector, by=hover_by, timeout=timeout)
2006+
self.__demo_mode_highlight_if_active(hover_selector, hover_by)
2007+
self.scroll_to(hover_selector, by=hover_by)
2008+
pre_action_url = self.driver.current_url
2009+
click_element = page_actions.hover_element_and_double_click(
2010+
self.driver, hover_element, click_selector,
2011+
click_by=By.CSS_SELECTOR, timeout=timeout)
2012+
if self.demo_mode:
2013+
if self.driver.current_url != pre_action_url:
2014+
self.__demo_mode_pause_if_active()
2015+
else:
2016+
self.__demo_mode_pause_if_active(tiny=True)
2017+
return click_element
2018+
19882019
def __select_option(self, dropdown_selector, option,
19892020
dropdown_by=By.CSS_SELECTOR, option_by="text",
19902021
timeout=settings.SMALL_TIMEOUT):
@@ -2409,6 +2440,13 @@ def assert_element_not_visible(self, selector, by=By.CSS_SELECTOR,
24092440
############
24102441

24112442
def wait_for_ready_state_complete(self, timeout=settings.EXTREME_TIMEOUT):
2443+
try:
2444+
# If there's an alert, skip
2445+
self.driver.switch_to.alert
2446+
return
2447+
except Exception:
2448+
# If there's no alert, continue
2449+
pass
24122450
if self.timeout_multiplier and timeout == settings.EXTREME_TIMEOUT:
24132451
timeout = self.__get_new_timeout(timeout)
24142452
is_ready = js_utils.wait_for_ready_state_complete(self.driver, timeout)

seleniumbase/fixtures/page_actions.py

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -158,6 +158,31 @@ def hover_element_and_click(driver, element, click_selector,
158158
(click_selector, timeout))
159159

160160

161+
def hover_element_and_double_click(driver, element, click_selector,
162+
click_by=By.CSS_SELECTOR,
163+
timeout=settings.SMALL_TIMEOUT):
164+
start_ms = time.time() * 1000.0
165+
stop_ms = start_ms + (timeout * 1000.0)
166+
hover = ActionChains(driver).move_to_element(element)
167+
hover.perform()
168+
for x in range(int(timeout * 10)):
169+
try:
170+
element_2 = driver.find_element(by=click_by, value=click_selector)
171+
actions = ActionChains(driver)
172+
actions.move_to_element(element_2)
173+
actions.double_click(element_2)
174+
actions.perform()
175+
return element_2
176+
except Exception:
177+
now_ms = time.time() * 1000.0
178+
if now_ms >= stop_ms:
179+
break
180+
time.sleep(0.1)
181+
raise NoSuchElementException(
182+
"Element {%s} was not present after %s seconds!" %
183+
(click_selector, timeout))
184+
185+
161186
def wait_for_element_present(driver, selector, by=By.CSS_SELECTOR,
162187
timeout=settings.LARGE_TIMEOUT):
163188
"""

setup.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@
1717

1818
setup(
1919
name='seleniumbase',
20-
version='1.30.0',
20+
version='1.31.0',
2121
description='Fast, Easy, and Reliable Browser Automation & Testing.',
2222
long_description=long_description,
2323
long_description_content_type='text/markdown',
@@ -65,7 +65,7 @@
6565
'selenium==3.141.0',
6666
'pluggy>=0.12.0',
6767
'pytest>=4.6.5;python_version<"3"', # For Python 2 compatibility
68-
'pytest>=5.1.0;python_version>="3"',
68+
'pytest>=5.1.2;python_version>="3"',
6969
'pytest-cov>=2.7.1',
7070
'pytest-forked>=1.0.2',
7171
'pytest-html==1.22.0', # Keep at 1.22.0 unless tested on Windows

0 commit comments

Comments
 (0)