Merge pull request #364 from seleniumbase/updates-and-fixes

Updates and fixes
This commit is contained in:
Michael Mintz 2019-08-30 20:59:31 -04:00 committed by GitHub
commit 78bbf830d8
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
7 changed files with 131 additions and 37 deletions

View File

@ -230,6 +230,9 @@ self.hover_on_element(selector, by=By.CSS_SELECTOR)
self.hover_and_click(hover_selector, click_selector, self.hover_and_click(hover_selector, click_selector,
hover_by=By.CSS_SELECTOR, click_by=By.CSS_SELECTOR, timeout=settings.SMALL_TIMEOUT) hover_by=By.CSS_SELECTOR, click_by=By.CSS_SELECTOR, timeout=settings.SMALL_TIMEOUT)
self.hover_and_double_click(hover_selector, click_selector,
hover_by=By.CSS_SELECTOR, click_by=By.CSS_SELECTOR, timeout=settings.SMALL_TIMEOUT)
self.select_option_by_text(dropdown_selector, option, self.select_option_by_text(dropdown_selector, option,
dropdown_by=By.CSS_SELECTOR, timeout=settings.SMALL_TIMEOUT) dropdown_by=By.CSS_SELECTOR, timeout=settings.SMALL_TIMEOUT)

View File

@ -1,6 +1,6 @@
pip>=19.2.2 pip>=19.2.3
setuptools>=41.1.0 setuptools>=41.2.0
wheel>=0.33.4 wheel>=0.33.6
six>=1.12.0 six>=1.12.0
nose>=1.3.7 nose>=1.3.7
ipdb>=0.12.2 ipdb>=0.12.2
@ -11,7 +11,7 @@ requests>=2.22.0
selenium==3.141.0 selenium==3.141.0
pluggy>=0.12.0 pluggy>=0.12.0
pytest>=4.6.5;python_version<"3" pytest>=4.6.5;python_version<"3"
pytest>=5.1.0;python_version>="3" pytest>=5.1.2;python_version>="3"
pytest-cov>=2.7.1 pytest-cov>=2.7.1
pytest-forked>=1.0.2 pytest-forked>=1.0.2
pytest-html==1.22.0 pytest-html==1.22.0

View File

@ -37,7 +37,7 @@ def show_basic_usage():
print("") print("")
print('Usage: "seleniumbase [COMMAND] [PARAMETERS]"') print('Usage: "seleniumbase [COMMAND] [PARAMETERS]"')
print("Commands:") print("Commands:")
print(" install [DRIVER_NAME]") print(" install [DRIVER_NAME] [OPTIONS]")
print(" mkdir [NEW_TEST_DIRECTORY_NAME]") print(" mkdir [NEW_TEST_DIRECTORY_NAME]")
print(" convert [PYTHON_WEBDRIVER_UNITTEST_FILE]") print(" convert [PYTHON_WEBDRIVER_UNITTEST_FILE]")
print(" extract-objects [SELENIUMBASE_PYTHON_FILE]") print(" extract-objects [SELENIUMBASE_PYTHON_FILE]")
@ -55,11 +55,18 @@ def show_install_usage():
print(" ** install **") print(" ** install **")
print("") print("")
print(" Usage:") print(" Usage:")
print(" seleniumbase install [DRIVER_NAME]") print(" seleniumbase install [DRIVER_NAME] [OPTIONS]")
print(" (Drivers: chromedriver, geckodriver, edgedriver") print(" (Drivers: chromedriver, geckodriver, edgedriver")
print(" iedriver, operadriver)") print(" iedriver, operadriver)")
print(" Options:")
print(" VERSION - Specify the version (For Chromedriver ONLY).")
print(" (Default Chromedriver version = 2.44)")
print(' Use "latest" to get the latest Chromedriver.')
print(" Example:") print(" Example:")
print(" seleniumbase install chromedriver") print(" seleniumbase install chromedriver")
print(" seleniumbase install chromedriver 76.0.3809.126")
print(" seleniumbase install chromedriver latest")
print(" seleniumbase install geckodriver")
print(" Output:") print(" Output:")
print(" Installs the specified webdriver.") print(" Installs the specified webdriver.")
print(" (chromedriver is required for Chrome automation)") print(" (chromedriver is required for Chrome automation)")

View File

@ -3,7 +3,16 @@ Installs the specified web driver.
Usage: Usage:
seleniumbase install {chromedriver|geckodriver|edgedriver| seleniumbase install {chromedriver|geckodriver|edgedriver|
iedriver|operadriver} iedriver|operadriver} [OPTIONS]
Options:
VERSION - Specify the version (For Chromedriver ONLY)
(Default Chromedriver version = 2.44)
Use "latest" to get the latest Chromedriver.
Example:
seleniumbase install chromedriver
seleniumbase install chromedriver 76.0.3809.126
seleniumbase install chromedriver latest
seleniumbase install geckodriver
Output: Output:
Installs the specified webdriver. Installs the specified webdriver.
(chromedriver is required for Chrome automation) (chromedriver is required for Chrome automation)
@ -24,16 +33,24 @@ import zipfile
from seleniumbase import drivers # webdriver storage folder for SeleniumBase from seleniumbase import drivers # webdriver storage folder for SeleniumBase
urllib3.disable_warnings() urllib3.disable_warnings()
DRIVER_DIR = os.path.dirname(os.path.realpath(drivers.__file__)) DRIVER_DIR = os.path.dirname(os.path.realpath(drivers.__file__))
DEFAULT_CHROMEDRIVER_VERSION = "2.44"
def invalid_run_command(): def invalid_run_command():
exp = (" ** install **\n\n") exp = (" ** install **\n\n")
exp += " Usage:\n" exp += " Usage:\n"
exp += " seleniumbase install [DRIVER_NAME]\n" exp += " seleniumbase install [DRIVER_NAME] [OPTIONS]\n"
exp += " (Drivers: chromedriver, geckodriver, edgedriver,\n" exp += " (Drivers: chromedriver, geckodriver, edgedriver,\n"
exp += " iedriver, operadriver)\n" exp += " iedriver, operadriver)\n"
exp += " Options:\n"
exp += " VERSION - Specify the version (For Chromedriver ONLY)."
exp += " (Default Chromedriver version = 2.44)"
exp += ' Use "latest" to get the latest Chromedriver.'
exp += " Example:\n" exp += " Example:\n"
exp += " seleniumbase install chromedriver\n" exp += " seleniumbase install chromedriver\n"
exp += " seleniumbase install chromedriver 76.0.3809.126\n"
exp += " seleniumbase install chromedriver latest\n"
exp += " seleniumbase install geckodriver\n"
exp += " Output:\n" exp += " Output:\n"
exp += " Installs the specified webdriver.\n" exp += " Installs the specified webdriver.\n"
exp += " (chromedriver is required for Chrome automation)\n" exp += " (chromedriver is required for Chrome automation)\n"
@ -56,11 +73,11 @@ def main():
num_args = len(sys.argv) num_args = len(sys.argv)
if sys.argv[0].split('/')[-1].lower() == "seleniumbase" or ( if sys.argv[0].split('/')[-1].lower() == "seleniumbase" or (
sys.argv[0].split('\\')[-1].lower() == "seleniumbase"): sys.argv[0].split('\\')[-1].lower() == "seleniumbase"):
if num_args < 3 or num_args > 3: if num_args < 3 or num_args > 4:
invalid_run_command() invalid_run_command()
else: else:
invalid_run_command() invalid_run_command()
name = sys.argv[num_args - 1].lower() name = sys.argv[2].lower()
file_name = None file_name = None
download_url = None download_url = None
@ -71,52 +88,56 @@ def main():
inner_folder = None inner_folder = None
if name == "chromedriver": if name == "chromedriver":
latest_version = "2.44" # It's not the latest, but most compatible use_version = DEFAULT_CHROMEDRIVER_VERSION
get_latest = False
if num_args == 4:
use_version = sys.argv[3]
if use_version.lower() == "latest":
get_latest = True
if "darwin" in sys_plat: if "darwin" in sys_plat:
file_name = "chromedriver_mac64.zip" file_name = "chromedriver_mac64.zip"
elif "linux" in sys_plat: elif "linux" in sys_plat:
latest_version = "2.44" # Linux machines may need the old driver
file_name = "chromedriver_linux64.zip" file_name = "chromedriver_linux64.zip"
elif "win32" in sys_plat or "win64" in sys_plat or "x64" in sys_plat: elif "win32" in sys_plat or "win64" in sys_plat or "x64" in sys_plat:
file_name = "chromedriver_win32.zip" # Works for win32 / win_x64 file_name = "chromedriver_win32.zip" # Works for win32 / win_x64
else: else:
raise Exception("Cannot determine which version of Chromedriver " raise Exception("Cannot determine which version of Chromedriver "
"to download!") "to download!")
download_url = ("http://chromedriver.storage.googleapis.com/" found_chromedriver = False
"%s/%s" % (latest_version, file_name))
# Forcing Chromedriver v2.40 for now, even though it's not the latest.
get_latest = False
if get_latest: if get_latest:
last = "http://chromedriver.storage.googleapis.com/LATEST_RELEASE" last = "http://chromedriver.storage.googleapis.com/LATEST_RELEASE"
print('\nLocating the latest version of Chromedriver...') url_request = requests.get(last)
latest_version = requests.get(last).text if url_request.ok:
if not requests.get(download_url).ok: found_chromedriver = True
fallback_version = "2.44" use_version = url_request.text
download_url = ("http://chromedriver.storage.googleapis.com/" download_url = ("http://chromedriver.storage.googleapis.com/"
"%s/%s" % (fallback_version, file_name)) "%s/%s" % (use_version, file_name))
else: url_request = None
download_url = ("http://chromedriver.storage.googleapis.com/" if not found_chromedriver:
"%s/%s" % (latest_version, file_name)) url_request = requests.get(download_url)
print("Found %s" % download_url) if found_chromedriver or url_request.ok:
print("\nChromedriver version for download = %s" % use_version)
else:
raise Exception("Could not find Chromedriver to download!\n")
elif name == "geckodriver" or name == "firefoxdriver": elif name == "geckodriver" or name == "firefoxdriver":
latest_version = "v0.24.0" use_version = "v0.24.0"
if "darwin" in sys_plat: if "darwin" in sys_plat:
file_name = "geckodriver-%s-macos.tar.gz" % latest_version file_name = "geckodriver-%s-macos.tar.gz" % use_version
elif "linux" in sys_plat: elif "linux" in sys_plat:
arch = platform.architecture()[0] arch = platform.architecture()[0]
if "64" in arch: if "64" in arch:
file_name = "geckodriver-%s-linux64.tar.gz" % latest_version file_name = "geckodriver-%s-linux64.tar.gz" % use_version
else: else:
file_name = "geckodriver-%s-linux32.tar.gz" % latest_version file_name = "geckodriver-%s-linux32.tar.gz" % use_version
elif "win32" in sys_plat or "win64" in sys_plat or "x64" in sys_plat: elif "win32" in sys_plat or "win64" in sys_plat or "x64" in sys_plat:
file_name = "geckodriver-%s-win64.zip" % latest_version file_name = "geckodriver-%s-win64.zip" % use_version
else: else:
raise Exception("Cannot determine which version of Geckodriver " raise Exception("Cannot determine which version of Geckodriver "
"(Firefox Driver) to download!") "(Firefox Driver) to download!")
download_url = ("https://github.com/mozilla/geckodriver/" download_url = ("https://github.com/mozilla/geckodriver/"
"releases/download/" "releases/download/"
"%s/%s" % (latest_version, file_name)) "%s/%s" % (use_version, file_name))
elif name == "edgedriver" or name == "microsoftwebdriver": elif name == "edgedriver" or name == "microsoftwebdriver":
name = "edgedriver" name = "edgedriver"
version_code = "F/8/A/F8AF50AB-3C3A-4BC4-8773-DC27B32988DD" version_code = "F/8/A/F8AF50AB-3C3A-4BC4-8773-DC27B32988DD"
@ -141,7 +162,7 @@ def main():
"%s/%s" % (major_version, file_name)) "%s/%s" % (major_version, file_name))
elif name == "operadriver" or name == "operachromiumdriver": elif name == "operadriver" or name == "operachromiumdriver":
name = "operadriver" name = "operadriver"
latest_version = "v.2.40" use_version = "v.2.40"
if "darwin" in sys_plat: if "darwin" in sys_plat:
file_name = "operadriver_mac64.zip" file_name = "operadriver_mac64.zip"
platform_code = "mac64" platform_code = "mac64"
@ -176,7 +197,7 @@ def main():
download_url = ("https://github.com/operasoftware/operachromiumdriver/" download_url = ("https://github.com/operasoftware/operachromiumdriver/"
"releases/download/" "releases/download/"
"%s/%s" % (latest_version, file_name)) "%s/%s" % (use_version, file_name))
else: else:
invalid_run_command() invalid_run_command()

View File

@ -177,7 +177,7 @@ class BaseCase(unittest.TestCase):
def double_click(self, selector, by=By.CSS_SELECTOR, def double_click(self, selector, by=By.CSS_SELECTOR,
timeout=settings.SMALL_TIMEOUT): timeout=settings.SMALL_TIMEOUT):
from selenium.webdriver import ActionChains from selenium.webdriver.common.action_chains import ActionChains
if self.timeout_multiplier and timeout == settings.SMALL_TIMEOUT: if self.timeout_multiplier and timeout == settings.SMALL_TIMEOUT:
timeout = self.__get_new_timeout(timeout) timeout = self.__get_new_timeout(timeout)
if page_utils.is_xpath_selector(selector): if page_utils.is_xpath_selector(selector):
@ -1962,6 +1962,8 @@ class BaseCase(unittest.TestCase):
def hover_and_click(self, hover_selector, click_selector, def hover_and_click(self, hover_selector, click_selector,
hover_by=By.CSS_SELECTOR, click_by=By.CSS_SELECTOR, hover_by=By.CSS_SELECTOR, click_by=By.CSS_SELECTOR,
timeout=settings.SMALL_TIMEOUT): timeout=settings.SMALL_TIMEOUT):
""" When you want to hover over an element or dropdown menu,
and then click an element that appears after that. """
if self.timeout_multiplier and timeout == settings.SMALL_TIMEOUT: if self.timeout_multiplier and timeout == settings.SMALL_TIMEOUT:
timeout = self.__get_new_timeout(timeout) timeout = self.__get_new_timeout(timeout)
hover_selector, hover_by = self.__recalculate_selector( hover_selector, hover_by = self.__recalculate_selector(
@ -1985,6 +1987,35 @@ class BaseCase(unittest.TestCase):
self.__demo_mode_pause_if_active(tiny=True) self.__demo_mode_pause_if_active(tiny=True)
return element return element
def hover_and_double_click(self, hover_selector, click_selector,
hover_by=By.CSS_SELECTOR,
click_by=By.CSS_SELECTOR,
timeout=settings.SMALL_TIMEOUT):
""" When you want to hover over an element or dropdown menu,
and then double-click an element that appears after that. """
if self.timeout_multiplier and timeout == settings.SMALL_TIMEOUT:
timeout = self.__get_new_timeout(timeout)
hover_selector, hover_by = self.__recalculate_selector(
hover_selector, hover_by)
hover_selector = self.convert_to_css_selector(
hover_selector, hover_by)
click_selector, click_by = self.__recalculate_selector(
click_selector, click_by)
hover_element = self.wait_for_element_visible(
hover_selector, by=hover_by, timeout=timeout)
self.__demo_mode_highlight_if_active(hover_selector, hover_by)
self.scroll_to(hover_selector, by=hover_by)
pre_action_url = self.driver.current_url
click_element = page_actions.hover_element_and_double_click(
self.driver, hover_element, click_selector,
click_by=By.CSS_SELECTOR, timeout=timeout)
if self.demo_mode:
if self.driver.current_url != pre_action_url:
self.__demo_mode_pause_if_active()
else:
self.__demo_mode_pause_if_active(tiny=True)
return click_element
def __select_option(self, dropdown_selector, option, def __select_option(self, dropdown_selector, option,
dropdown_by=By.CSS_SELECTOR, option_by="text", dropdown_by=By.CSS_SELECTOR, option_by="text",
timeout=settings.SMALL_TIMEOUT): timeout=settings.SMALL_TIMEOUT):
@ -2409,6 +2440,13 @@ class BaseCase(unittest.TestCase):
############ ############
def wait_for_ready_state_complete(self, timeout=settings.EXTREME_TIMEOUT): def wait_for_ready_state_complete(self, timeout=settings.EXTREME_TIMEOUT):
try:
# If there's an alert, skip
self.driver.switch_to.alert
return
except Exception:
# If there's no alert, continue
pass
if self.timeout_multiplier and timeout == settings.EXTREME_TIMEOUT: if self.timeout_multiplier and timeout == settings.EXTREME_TIMEOUT:
timeout = self.__get_new_timeout(timeout) timeout = self.__get_new_timeout(timeout)
is_ready = js_utils.wait_for_ready_state_complete(self.driver, timeout) is_ready = js_utils.wait_for_ready_state_complete(self.driver, timeout)

View File

@ -158,6 +158,31 @@ def hover_element_and_click(driver, element, click_selector,
(click_selector, timeout)) (click_selector, timeout))
def hover_element_and_double_click(driver, element, click_selector,
click_by=By.CSS_SELECTOR,
timeout=settings.SMALL_TIMEOUT):
start_ms = time.time() * 1000.0
stop_ms = start_ms + (timeout * 1000.0)
hover = ActionChains(driver).move_to_element(element)
hover.perform()
for x in range(int(timeout * 10)):
try:
element_2 = driver.find_element(by=click_by, value=click_selector)
actions = ActionChains(driver)
actions.move_to_element(element_2)
actions.double_click(element_2)
actions.perform()
return element_2
except Exception:
now_ms = time.time() * 1000.0
if now_ms >= stop_ms:
break
time.sleep(0.1)
raise NoSuchElementException(
"Element {%s} was not present after %s seconds!" %
(click_selector, timeout))
def wait_for_element_present(driver, selector, by=By.CSS_SELECTOR, def wait_for_element_present(driver, selector, by=By.CSS_SELECTOR,
timeout=settings.LARGE_TIMEOUT): timeout=settings.LARGE_TIMEOUT):
""" """

View File

@ -17,7 +17,7 @@ except IOError:
setup( setup(
name='seleniumbase', name='seleniumbase',
version='1.30.0', version='1.31.0',
description='Fast, Easy, and Reliable Browser Automation & Testing.', description='Fast, Easy, and Reliable Browser Automation & Testing.',
long_description=long_description, long_description=long_description,
long_description_content_type='text/markdown', long_description_content_type='text/markdown',
@ -65,7 +65,7 @@ setup(
'selenium==3.141.0', 'selenium==3.141.0',
'pluggy>=0.12.0', 'pluggy>=0.12.0',
'pytest>=4.6.5;python_version<"3"', # For Python 2 compatibility 'pytest>=4.6.5;python_version<"3"', # For Python 2 compatibility
'pytest>=5.1.0;python_version>="3"', 'pytest>=5.1.2;python_version>="3"',
'pytest-cov>=2.7.1', 'pytest-cov>=2.7.1',
'pytest-forked>=1.0.2', 'pytest-forked>=1.0.2',
'pytest-html==1.22.0', # Keep at 1.22.0 unless tested on Windows 'pytest-html==1.22.0', # Keep at 1.22.0 unless tested on Windows