214 lines
6.1 KiB
Python
214 lines
6.1 KiB
Python
#pylint: disable=C0111
|
|
#pylint: disable=W0621
|
|
|
|
from lettuce import world
|
|
import time
|
|
import platform
|
|
from urllib import quote_plus
|
|
from selenium.common.exceptions import WebDriverException, StaleElementReferenceException
|
|
from selenium.webdriver.support import expected_conditions as EC
|
|
from selenium.webdriver.common.by import By
|
|
from selenium.webdriver.support.ui import WebDriverWait
|
|
from lettuce.django import django_url
|
|
|
|
|
|
@world.absorb
|
|
def wait(seconds):
|
|
time.sleep(float(seconds))
|
|
|
|
|
|
@world.absorb
|
|
def wait_for(func):
|
|
WebDriverWait(world.browser.driver, 5).until(func)
|
|
|
|
|
|
@world.absorb
|
|
def visit(url):
|
|
world.browser.visit(django_url(url))
|
|
|
|
|
|
@world.absorb
|
|
def url_equals(url):
|
|
return world.browser.url == django_url(url)
|
|
|
|
|
|
@world.absorb
|
|
def is_css_present(css_selector, wait_time=5):
|
|
return world.browser.is_element_present_by_css(css_selector, wait_time=wait_time)
|
|
|
|
|
|
@world.absorb
|
|
def is_css_not_present(css_selector, wait_time=5):
|
|
return world.browser.is_element_not_present_by_css(css_selector, wait_time=wait_time)
|
|
|
|
|
|
@world.absorb
|
|
def css_has_text(css_selector, text):
|
|
return world.css_text(css_selector) == text
|
|
|
|
|
|
@world.absorb
|
|
def css_find(css, wait_time=5):
|
|
def is_visible(_driver):
|
|
return EC.visibility_of_element_located((By.CSS_SELECTOR, css,))
|
|
|
|
world.browser.is_element_present_by_css(css, wait_time=wait_time)
|
|
wait_for(is_visible)
|
|
return world.browser.find_by_css(css)
|
|
|
|
|
|
@world.absorb
|
|
def css_click(css_selector, index=0, max_attempts=5, success_condition=lambda: True):
|
|
"""
|
|
Perform a click on a CSS selector, retrying if it initially fails.
|
|
|
|
This function handles errors that may be thrown if the component cannot be clicked on.
|
|
However, there are cases where an error may not be thrown, and yet the operation did not
|
|
actually succeed. For those cases, a success_condition lambda can be supplied to verify that the click worked.
|
|
|
|
This function will return True if the click worked (taking into account both errors and the optional
|
|
success_condition).
|
|
"""
|
|
assert is_css_present(css_selector)
|
|
attempt = 0
|
|
result = False
|
|
while attempt < max_attempts:
|
|
try:
|
|
world.css_find(css_selector)[index].click()
|
|
if success_condition():
|
|
result = True
|
|
break
|
|
except WebDriverException:
|
|
# Occasionally, MathJax or other JavaScript can cover up
|
|
# an element temporarily.
|
|
# If this happens, wait a second, then try again
|
|
world.wait(1)
|
|
attempt += 1
|
|
except:
|
|
attempt += 1
|
|
return result
|
|
|
|
|
|
@world.absorb
|
|
def css_check(css_selector, index=0, max_attempts=5, success_condition=lambda: True):
|
|
"""
|
|
Checks a check box based on a CSS selector, retrying if it initially fails.
|
|
|
|
This function handles errors that may be thrown if the component cannot be clicked on.
|
|
However, there are cases where an error may not be thrown, and yet the operation did not
|
|
actually succeed. For those cases, a success_condition lambda can be supplied to verify that the check worked.
|
|
|
|
This function will return True if the check worked (taking into account both errors and the optional
|
|
success_condition).
|
|
"""
|
|
assert is_css_present(css_selector)
|
|
attempt = 0
|
|
result = False
|
|
while attempt < max_attempts:
|
|
try:
|
|
world.css_find(css_selector)[index].check()
|
|
if success_condition():
|
|
result = True
|
|
break
|
|
except WebDriverException:
|
|
# Occasionally, MathJax or other JavaScript can cover up
|
|
# an element temporarily.
|
|
# If this happens, wait a second, then try again
|
|
world.wait(1)
|
|
attempt += 1
|
|
except:
|
|
attempt += 1
|
|
return result
|
|
|
|
|
|
@world.absorb
|
|
def css_click_at(css, x_cord=10, y_cord=10):
|
|
'''
|
|
A method to click at x,y coordinates of the element
|
|
rather than in the center of the element
|
|
'''
|
|
element = css_find(css).first
|
|
element.action_chains.move_to_element_with_offset(element._element, x_cord, y_cord)
|
|
element.action_chains.click()
|
|
element.action_chains.perform()
|
|
|
|
|
|
@world.absorb
|
|
def id_click(elem_id):
|
|
"""
|
|
Perform a click on an element as specified by its id
|
|
"""
|
|
world.css_click('#%s' % elem_id)
|
|
|
|
|
|
@world.absorb
|
|
def css_fill(css_selector, text):
|
|
assert is_css_present(css_selector)
|
|
world.browser.find_by_css(css_selector).first.fill(text)
|
|
|
|
|
|
@world.absorb
|
|
def click_link(partial_text):
|
|
world.browser.find_link_by_partial_text(partial_text).first.click()
|
|
|
|
|
|
@world.absorb
|
|
def css_text(css_selector):
|
|
|
|
# Wait for the css selector to appear
|
|
if world.is_css_present(css_selector):
|
|
try:
|
|
return world.browser.find_by_css(css_selector).first.text
|
|
except StaleElementReferenceException:
|
|
# The DOM was still redrawing. Wait a second and try again.
|
|
world.wait(1)
|
|
return world.browser.find_by_css(css_selector).first.text
|
|
else:
|
|
return ""
|
|
|
|
|
|
@world.absorb
|
|
def css_visible(css_selector):
|
|
assert is_css_present(css_selector)
|
|
return world.browser.find_by_css(css_selector).visible
|
|
|
|
|
|
@world.absorb
|
|
def dialogs_closed():
|
|
def are_dialogs_closed(_driver):
|
|
'''
|
|
Return True when no modal dialogs are visible
|
|
'''
|
|
return not css_visible('.modal')
|
|
wait_for(are_dialogs_closed)
|
|
return not css_visible('.modal')
|
|
|
|
|
|
@world.absorb
|
|
def save_the_html(path='/tmp'):
|
|
url = world.browser.url
|
|
html = world.browser.html.encode('ascii', 'ignore')
|
|
filename = '%s.html' % quote_plus(url)
|
|
file = open('%s/%s' % (path, filename), 'w')
|
|
file.write(html)
|
|
file.close()
|
|
|
|
|
|
@world.absorb
|
|
def click_course_settings():
|
|
course_settings_css = 'li.nav-course-settings'
|
|
if world.browser.is_element_present_by_css(course_settings_css):
|
|
world.css_click(course_settings_css)
|
|
|
|
|
|
@world.absorb
|
|
def click_tools():
|
|
tools_css = 'li.nav-course-tools'
|
|
if world.browser.is_element_present_by_css(tools_css):
|
|
world.css_click(tools_css)
|
|
|
|
|
|
@world.absorb
|
|
def is_mac():
|
|
return platform.mac_ver()[0] is not ''
|