Improve code clarity and error messages for css selection
This commit is contained in:
@@ -11,7 +11,6 @@ DISPLAY_NAME_KEY = "display_name"
|
||||
DISPLAY_NAME_VALUE = '"Robot Super Course"'
|
||||
|
||||
|
||||
############### ACTIONS ####################
|
||||
@step('I select the Advanced Settings$')
|
||||
def i_select_advanced_settings(step):
|
||||
world.click_course_settings()
|
||||
@@ -45,7 +44,6 @@ def create_value_not_in_quotes(step):
|
||||
change_display_name_value(step, 'quote me')
|
||||
|
||||
|
||||
############### RESULTS ####################
|
||||
@step('I see default advanced settings$')
|
||||
def i_see_default_advanced_settings(step):
|
||||
# Test only a few of the existing properties (there are around 34 of them)
|
||||
@@ -88,14 +86,13 @@ def the_policy_key_value_is_changed(step):
|
||||
assert_equal(get_display_name_value(), '"foo"')
|
||||
|
||||
|
||||
############# HELPERS ###############
|
||||
def assert_policy_entries(expected_keys, expected_values):
|
||||
for key, value in zip(expected_keys, expected_values):
|
||||
index = get_index_of(key)
|
||||
assert_false(index == -1, "Could not find key: {key}".format(key=key))
|
||||
found_value = world.css_find(VALUE_CSS)[index].value
|
||||
assert_equal(value, found_value,
|
||||
"{} is not equal to {}".format(value, found_value))
|
||||
"Expected {} to have value {} but found {}".format(key, value, found_value))
|
||||
|
||||
|
||||
def get_index_of(expected_key):
|
||||
|
||||
@@ -165,7 +165,7 @@ def log_into_studio(
|
||||
world.log_in(username=uname, password=password, email=email, name=name)
|
||||
# Navigate to the studio dashboard
|
||||
world.visit('/')
|
||||
assert_in(uname, world.css_text('h2.title', timeout=60))
|
||||
assert_in(uname, world.css_text('h2.title', timeout=10))
|
||||
|
||||
|
||||
def create_a_course():
|
||||
|
||||
@@ -110,9 +110,9 @@ def other_user_login(_step, name):
|
||||
|
||||
@step(u'I( do not)? see the course on my page')
|
||||
@step(u's?he does( not)? see the course on (his|her) page')
|
||||
def see_course(_step, inverted, gender='self'):
|
||||
def see_course(_step, do_not_see, gender='self'):
|
||||
class_css = 'h3.course-title'
|
||||
if inverted:
|
||||
if do_not_see:
|
||||
assert world.is_css_not_present(class_css)
|
||||
else:
|
||||
all_courses = world.css_find(class_css)
|
||||
@@ -121,25 +121,25 @@ def see_course(_step, inverted, gender='self'):
|
||||
|
||||
|
||||
@step(u'"([^"]*)" should( not)? be marked as an admin')
|
||||
def marked_as_admin(_step, name, inverted):
|
||||
def marked_as_admin(_step, name, not_marked_admin):
|
||||
flag_css = '.user-item[data-email="{email}"] .flag-role.flag-role-admin'.format(
|
||||
email=name+EMAIL_EXTENSION)
|
||||
if inverted:
|
||||
if not_marked_admin:
|
||||
assert world.is_css_not_present(flag_css)
|
||||
else:
|
||||
assert world.is_css_present(flag_css)
|
||||
|
||||
|
||||
@step(u'I should( not)? be marked as an admin')
|
||||
def self_marked_as_admin(_step, inverted):
|
||||
return marked_as_admin(_step, "robot+studio", inverted)
|
||||
def self_marked_as_admin(_step, not_marked_admin):
|
||||
return marked_as_admin(_step, "robot+studio", not_marked_admin)
|
||||
|
||||
|
||||
@step(u'I can(not)? delete users')
|
||||
@step(u's?he can(not)? delete users')
|
||||
def can_delete_users(_step, inverted):
|
||||
def can_delete_users(_step, can_not_delete):
|
||||
to_delete_css = 'a.remove-user'
|
||||
if inverted:
|
||||
if can_not_delete:
|
||||
assert world.is_css_not_present(to_delete_css)
|
||||
else:
|
||||
assert world.is_css_present(to_delete_css)
|
||||
@@ -147,9 +147,9 @@ def can_delete_users(_step, inverted):
|
||||
|
||||
@step(u'I can(not)? add users')
|
||||
@step(u's?he can(not)? add users')
|
||||
def can_add_users(_step, inverted):
|
||||
def can_add_users(_step, can_not_add):
|
||||
add_css = 'a.create-user-button'
|
||||
if inverted:
|
||||
if can_not_add:
|
||||
assert world.is_css_not_present(add_css)
|
||||
else:
|
||||
assert world.is_css_present(add_css)
|
||||
@@ -157,13 +157,13 @@ def can_add_users(_step, inverted):
|
||||
|
||||
@step(u'I can(not)? make ("([^"]*)"|myself) a course team admin')
|
||||
@step(u's?he can(not)? make ("([^"]*)"|me) a course team admin')
|
||||
def can_make_course_admin(_step, inverted, outer_capture, name):
|
||||
def can_make_course_admin(_step, can_not_make_admin, outer_capture, name):
|
||||
if outer_capture == "myself":
|
||||
email = world.scenario_dict["USER"].email
|
||||
else:
|
||||
email = name + EMAIL_EXTENSION
|
||||
add_button_css = '.user-item[data-email="{email}"] .add-admin-role'.format(email=email)
|
||||
if inverted:
|
||||
if can_not_make_admin:
|
||||
assert world.is_css_not_present(add_button_css)
|
||||
else:
|
||||
assert world.is_css_present(add_button_css)
|
||||
|
||||
@@ -82,9 +82,9 @@ def see_assignment_name(step, do_not, name):
|
||||
assignment_menu = world.css_find(assignment_menu_css)
|
||||
allnames = [item.html for item in assignment_menu]
|
||||
if do_not:
|
||||
assert_not_in (name, allnames)
|
||||
assert_not_in(name, allnames)
|
||||
else:
|
||||
assert_in (name, allnames)
|
||||
assert_in(name, allnames)
|
||||
|
||||
|
||||
@step(u'I delete the assignment type "([^"]*)"$')
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
#pylint: disable=C0111
|
||||
|
||||
from lettuce import world, step
|
||||
from nose.tools import assert_equal # pylint: disable=E0611
|
||||
from nose.tools import assert_equal, assert_true # pylint: disable=E0611
|
||||
from common import type_in_codemirror
|
||||
|
||||
DISPLAY_NAME = "Display Name"
|
||||
@@ -198,14 +198,19 @@ def high_level_source_in_editor(step):
|
||||
|
||||
def verify_high_level_source_links(step, visible):
|
||||
if visible:
|
||||
assert world.is_css_present('.launch-latex-compiler')
|
||||
assert_true(world.is_css_present('.launch-latex-compiler'),
|
||||
msg="Expected to find the latex button but it is not present.")
|
||||
else:
|
||||
assert world.is_css_not_present('.launch-latex-compiler')
|
||||
assert_true(world.is_css_not_present('.launch-latex-compiler'),
|
||||
msg="Expected not to find the latex button but it is present.")
|
||||
|
||||
world.cancel_component(step)
|
||||
if visible:
|
||||
assert world.is_css_present('.upload-button')
|
||||
assert_true(world.is_css_present('.upload-button'),
|
||||
msg="Expected to find the upload button but it is not present.")
|
||||
else:
|
||||
assert world.is_css_not_present('.upload-button')
|
||||
assert_true(world.is_css_not_present('.upload-button'),
|
||||
msg="Expected not to find the upload button but it is present.")
|
||||
|
||||
|
||||
def verify_modified_weight():
|
||||
|
||||
@@ -88,7 +88,6 @@ def initial_setup(server):
|
||||
"""
|
||||
Launch the browser once before executing the tests.
|
||||
"""
|
||||
# from nose.tools import set_trace; set_trace()
|
||||
world.absorb(settings.SAUCE.get('SAUCE_ENABLED'), 'SAUCE_ENABLED')
|
||||
|
||||
if not world.SAUCE_ENABLED:
|
||||
@@ -166,15 +165,18 @@ def reset_databases(scenario):
|
||||
xmodule.modulestore.django.clear_existing_modulestores()
|
||||
|
||||
|
||||
# Uncomment below to trigger a screenshot on error
|
||||
# @after.each_scenario
|
||||
@after.each_scenario
|
||||
def screenshot_on_error(scenario):
|
||||
"""
|
||||
Save a screenshot to help with debugging.
|
||||
"""
|
||||
if scenario.failed:
|
||||
world.browser.driver.save_screenshot('/tmp/last_failed_scenario.png')
|
||||
|
||||
try:
|
||||
output_dir = '{}/log'.format(settings.TEST_ROOT)
|
||||
image_name = '{}/{}.png'.format(output_dir, scenario.name.replace(' ', '_'))
|
||||
world.browser.driver.save_screenshot(image_name)
|
||||
except WebDriverException:
|
||||
LOGGER.error('Could not capture a screenshot')
|
||||
|
||||
@after.all
|
||||
def teardown_browser(total):
|
||||
|
||||
@@ -5,7 +5,7 @@ from lettuce import world
|
||||
import time
|
||||
import platform
|
||||
from urllib import quote_plus
|
||||
from selenium.common.exceptions import WebDriverException
|
||||
from selenium.common.exceptions import WebDriverException, TimeoutException
|
||||
from selenium.webdriver.support import expected_conditions as EC
|
||||
from selenium.webdriver.common.by import By
|
||||
from selenium.webdriver.support.ui import WebDriverWait
|
||||
@@ -54,8 +54,11 @@ def wait_for_present(css_selector, timeout=30):
|
||||
Throws an error if the wait_for time expires.
|
||||
Otherwise this method will return None
|
||||
"""
|
||||
WebDriverWait(driver=world.browser.driver,
|
||||
timeout=60).until(EC.presence_of_element_located((By.CSS_SELECTOR, css_selector,)))
|
||||
try:
|
||||
WebDriverWait(driver=world.browser.driver,
|
||||
timeout=60).until(EC.presence_of_element_located((By.CSS_SELECTOR, css_selector,)))
|
||||
except TimeoutException:
|
||||
raise TimeoutException("Timed out waiting for {} to be present.".format(css_selector))
|
||||
|
||||
|
||||
@world.absorb
|
||||
@@ -65,8 +68,11 @@ def wait_for_visible(css_selector, timeout=30):
|
||||
Throws an error if the wait_for time expires.
|
||||
Otherwise this method will return None
|
||||
"""
|
||||
WebDriverWait(driver=world.browser.driver,
|
||||
timeout=timeout).until(EC.visibility_of_element_located((By.CSS_SELECTOR, css_selector,)))
|
||||
try:
|
||||
WebDriverWait(driver=world.browser.driver,
|
||||
timeout=timeout).until(EC.visibility_of_element_located((By.CSS_SELECTOR, css_selector,)))
|
||||
except TimeoutException:
|
||||
raise TimeoutException("Timed out waiting for {} to be visible.".format(css_selector))
|
||||
|
||||
|
||||
@world.absorb
|
||||
@@ -76,8 +82,11 @@ def wait_for_invisible(css_selector, timeout=30):
|
||||
Throws an error if the wait_for time expires.
|
||||
Otherwise this method will return None
|
||||
"""
|
||||
WebDriverWait(driver=world.browser.driver,
|
||||
timeout=timeout).until(EC.invisibility_of_element_located((By.CSS_SELECTOR, css_selector,)))
|
||||
try:
|
||||
WebDriverWait(driver=world.browser.driver,
|
||||
timeout=timeout).until(EC.invisibility_of_element_located((By.CSS_SELECTOR, css_selector,)))
|
||||
except TimeoutException:
|
||||
raise TimeoutException("Timed out waiting for {} to be invisible.".format(css_selector))
|
||||
|
||||
|
||||
@world.absorb
|
||||
@@ -89,8 +98,11 @@ def wait_for_clickable(css_selector, timeout=30):
|
||||
"""
|
||||
# Sometimes the element is clickable then gets obscured.
|
||||
# In this case, pause so that it is not reported clickable too early
|
||||
WebDriverWait(world.browser.driver,
|
||||
timeout=timeout).until(EC.element_to_be_clickable((By.CSS_SELECTOR, css_selector,)))
|
||||
try:
|
||||
WebDriverWait(world.browser.driver,
|
||||
timeout=timeout).until(EC.element_to_be_clickable((By.CSS_SELECTOR, css_selector,)))
|
||||
except TimeoutException:
|
||||
raise TimeoutException("Timed out waiting for {} to be clickable.".format(css_selector))
|
||||
|
||||
|
||||
@world.absorb
|
||||
@@ -114,7 +126,8 @@ def css_click(css_selector, index=0, wait_time=30):
|
||||
This method will return True if the click worked.
|
||||
"""
|
||||
wait_for_clickable(css_selector, timeout=wait_time)
|
||||
assert world.css_find(css_selector)[index].visible
|
||||
assert_true(world.css_find(css_selector)[index].visible,
|
||||
msg="Element {}[{}] is present but not visible".format(css_selector, index))
|
||||
|
||||
# Sometimes you can't click in the center of the element, as
|
||||
# another element might be on top of it. In this case, try
|
||||
@@ -146,7 +159,8 @@ def css_click_at(css_selector, index=0, x_coord=10, y_coord=10, timeout=5):
|
||||
'''
|
||||
wait_for_clickable(css_selector, timeout=timeout)
|
||||
element = css_find(css_selector)[index]
|
||||
assert element.visible
|
||||
assert_true(element.visible,
|
||||
msg="Element {}[{}] is present but not visible".format(css_selector, index))
|
||||
|
||||
element.action_chains.move_to_element_with_offset(element._element, x_coord, y_coord)
|
||||
element.action_chains.click()
|
||||
@@ -158,7 +172,7 @@ def id_click(elem_id):
|
||||
"""
|
||||
Perform a click on an element as specified by its id
|
||||
"""
|
||||
css_click('#%s' % elem_id)
|
||||
css_click('#{}'.format(elem_id))
|
||||
|
||||
|
||||
@world.absorb
|
||||
|
||||
@@ -80,8 +80,8 @@ def click_on_section(step, section):
|
||||
section_css = 'h3[tabindex="-1"]'
|
||||
world.css_click(section_css)
|
||||
|
||||
subid = "ui-accordion-accordion-panel-" + str(int(section) - 1)
|
||||
subsection_css = 'ul.ui-accordion-content-active[id=\'%s\'] > li > a' % subid
|
||||
subid = "ui-accordion-accordion-panel-{}".format(str(int(section) - 1))
|
||||
subsection_css = "ul.ui-accordion-content-active[id='{}'] > li > a".format(subid)
|
||||
world.css_click(subsection_css)
|
||||
|
||||
|
||||
|
||||
@@ -166,6 +166,8 @@ def answer_problem(problem_type, correctness):
|
||||
if problem_type == "drop down":
|
||||
select_name = "input_i4x-edx-model_course-problem-drop_down_2_1"
|
||||
option_text = 'Option 2' if correctness == 'correct' else 'Option 3'
|
||||
# First wait for the element to be there on the page
|
||||
world.wait_for_visible("select#{}".format(select_name))
|
||||
world.browser.select(select_name, option_text)
|
||||
|
||||
elif problem_type == "multiple choice":
|
||||
|
||||
Reference in New Issue
Block a user