Refactor wait_for methods in ui_helpers for acceptance tests.

This commit is contained in:
Jay Zoldak
2013-10-18 11:52:00 -04:00
parent a1bc5a1184
commit ecea49ba2d
9 changed files with 151 additions and 137 deletions

View File

@@ -283,24 +283,33 @@ def button_disabled(step, value):
assert world.css_has_class(button_css, 'is-disabled')
def _do_studio_prompt_action(intent, action):
"""
Wait for a studio prompt to appear and press the specified action button
See cms/static/js/views/feedback_prompt.js for implementation
"""
assert intent in ['warning', 'error', 'confirmation', 'announcement',
'step-required', 'help', 'mini']
assert action in ['primary', 'secondary']
world.wait_for_present('div.wrapper-prompt.is-shown#prompt-{}'.format(intent))
action_css = 'li.nav-item > a.action-{}'.format(action)
world.trigger_event(action_css, event='focus')
world.browser.execute_script("$('{}').click()".format(action_css))
world.wait_for_ajax_complete()
world.wait_for_present('div.wrapper-prompt.is-hiding#prompt-{}'.format(intent))
@world.absorb
def confirm_studio_prompt():
_do_studio_prompt_action('warning', 'primary')
@step('I confirm the prompt')
def confirm_the_prompt(step):
def click_button(btn_css):
world.css_click(btn_css)
return world.css_find(btn_css).visible == False
prompt_css = 'div.prompt.has-actions'
world.wait_for_visible(prompt_css)
btn_css = 'a.button.action-primary'
world.wait_for_visible(btn_css)
# Sometimes you can do a click before the prompt is up.
# Thus we need some retry logic here.
world.wait_for(lambda _driver: click_button(btn_css))
assert_false(world.css_find(btn_css).visible)
confirm_studio_prompt()
@step(u'I am shown a prompt$')

View File

@@ -23,8 +23,7 @@ def create_component_instance(step, category, component_type=None, is_advanced=F
----------
category: component type (discussion, html, problem, video)
component_type: for components with multiple templates, the link text in the menu
is_advanced: for html and problem, is the desired component under the
advanced menu
is_advanced: for problems, is the desired component under the advanced menu?
"""
assert_in(category, ['problem', 'html', 'video', 'discussion'])
@@ -40,6 +39,8 @@ def create_component_instance(step, category, component_type=None, is_advanced=F
# because it's ok if there are currently zero of them.
module_count_before = len(world.browser.find_by_css(module_css))
# Disable the jquery animation for the transition to the menus.
world.disable_jquery_animations()
world.css_click(component_button_css)
if category in ('problem', 'html'):
@@ -50,17 +51,13 @@ def create_component_instance(step, category, component_type=None, is_advanced=F
module_count_before + 1))
@world.absorb
def click_new_component_button(step, component_button_css):
step.given('I have clicked the new unit button')
world.css_click(component_button_css)
def _click_advanced():
css = 'ul.problem-type-tabs a[href="#tab2"]'
world.css_click(css)
my_css = 'ul.problem-type-tabs li.ui-state-active a[href="#tab2"]'
assert(world.css_find(my_css))
# Wait for the advanced tab items to be displayed
tab2_css = 'div.ui-tabs-panel#tab2'
world.wait_for_visible(tab2_css)
def _find_matching_link(category, component_type):

View File

@@ -2,22 +2,24 @@
#pylint: disable=W0621
from lettuce import world, step
from auth.authz import get_course_groupname_for_role, get_user_by_email
from nose.tools import assert_true, assert_in # pylint: disable=E0611
from nose.tools import assert_in # pylint: disable=E0611
@step(u'(I am viewing|s?he views) the course team settings')
@step(u'(I am viewing|s?he views) the course team settings$')
def view_grading_settings(_step, whom):
world.click_course_settings()
link_css = 'li.nav-course-settings-team a'
world.css_click(link_css)
@step(u'I add "([^"]*)" to the course team')
@step(u'I add "([^"]*)" to the course team$')
def add_other_user(_step, name):
new_user_css = 'a.create-user-button'
world.css_click(new_user_css)
world.wait(0.5)
# Wait for the css animation to apply the is-shown class
shown_css = 'div.wrapper-create-user.is-shown'
world.wait_for_present(shown_css)
email_css = 'input#user-email-input'
world.css_fill(email_css, name + '@edx.org')
@@ -27,35 +29,30 @@ def add_other_user(_step, name):
world.css_click(confirm_css)
@step(u'I delete "([^"]*)" from the course team')
@step(u'I delete "([^"]*)" from the course team$')
def delete_other_user(_step, name):
to_delete_css = '.user-item .item-actions a.remove-user[data-id="{email}"]'.format(
email="{0}{1}".format(name, '@edx.org'))
world.css_click(to_delete_css)
# confirm prompt
# need to wait for the animation to be done, there isn't a good success condition that won't work both on latest chrome and jenkins
world.wait(.5)
world.css_click(".wrapper-prompt-warning .action-primary")
world.confirm_studio_prompt()
@step(u's?he deletes me from the course team')
@step(u's?he deletes me from the course team$')
def other_delete_self(_step):
to_delete_css = '.user-item .item-actions a.remove-user[data-id="{email}"]'.format(
email="robot+studio@edx.org")
world.css_click(to_delete_css)
# confirm prompt
world.wait(.5)
world.css_click(".wrapper-prompt-warning .action-primary")
world.confirm_studio_prompt()
@step(u'I make "([^"]*)" a course team admin')
@step(u'I make "([^"]*)" a course team admin$')
def make_course_team_admin(_step, name):
admin_btn_css = '.user-item[data-email="{name}@edx.org"] .user-actions .add-admin-role'.format(
name=name)
world.css_click(admin_btn_css)
@step(u'I remove admin rights from ("([^"]*)"|myself)')
@step(u'I remove admin rights from ("([^"]*)"|myself)$')
def remove_course_team_admin(_step, outer_capture, name):
if outer_capture == "myself":
email = world.scenario_dict["USER"].email
@@ -66,8 +63,8 @@ def remove_course_team_admin(_step, outer_capture, name):
world.css_click(admin_btn_css)
@step(u'I( do not)? see the course on my page')
@step(u's?he does( not)? see the course on (his|her) page')
@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, do_not_see, gender='self'):
class_css = 'h3.course-title'
if do_not_see:
@@ -78,7 +75,7 @@ def see_course(_step, do_not_see, gender='self'):
assert_in(world.scenario_dict['COURSE'].display_name, all_names)
@step(u'"([^"]*)" should( not)? be marked as an admin')
@step(u'"([^"]*)" should( not)? be marked as an admin$')
def marked_as_admin(_step, name, not_marked_admin):
flag_css = '.user-item[data-email="{name}@edx.org"] .flag-role.flag-role-admin'.format(
name=name)
@@ -88,13 +85,13 @@ def marked_as_admin(_step, name, not_marked_admin):
assert world.is_css_present(flag_css)
@step(u'I should( not)? be marked as an admin')
@step(u'I should( not)? be marked as an admin$')
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')
@step(u'I can(not)? delete users$')
@step(u's?he can(not)? delete users$')
def can_delete_users(_step, can_not_delete):
to_delete_css = 'a.remove-user'
if can_not_delete:
@@ -103,8 +100,8 @@ def can_delete_users(_step, can_not_delete):
assert world.is_css_present(to_delete_css)
@step(u'I can(not)? add users')
@step(u's?he can(not)? add users')
@step(u'I can(not)? add users$')
@step(u's?he can(not)? add users$')
def can_add_users(_step, can_not_add):
add_css = 'a.create-user-button'
if can_not_add:
@@ -113,8 +110,8 @@ def can_add_users(_step, can_not_add):
assert world.is_css_present(add_css)
@step(u'I can(not)? make ("([^"]*)"|myself) a course team admin')
@step(u's?he can(not)? make ("([^"]*)"|me) a course team admin')
@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, can_not_make_admin, outer_capture, name):
if outer_capture == "myself":
email = world.scenario_dict["USER"].email

View File

@@ -6,7 +6,7 @@ from lettuce import world, step
from nose.tools import assert_equal, assert_true # pylint: disable=E0611
from common import type_in_codemirror, open_new_course
from course_import import import_file, go_to_import
from selenium.webdriver.common.keys import Keys
DISPLAY_NAME = "Display Name"
MAXIMUM_ATTEMPTS = "Maximum Attempts"
@@ -47,9 +47,7 @@ def i_can_modify_the_display_name(_step):
# Verifying that the display name can be a string containing a floating point value
# (to confirm that we don't throw an error because it is of the wrong type).
index = world.get_setting_entry_index(DISPLAY_NAME)
world.css_fill('.wrapper-comp-setting .setting-input', '3.4', index=index)
if world.is_firefox():
world.trigger_event('.wrapper-comp-setting .setting-input', index=index)
set_field_value(index, '3.4')
verify_modified_display_name()
@@ -62,9 +60,7 @@ def my_display_name_change_is_persisted_on_save(step):
@step('I can specify special characters in the display name')
def i_can_modify_the_display_name_with_special_chars(_step):
index = world.get_setting_entry_index(DISPLAY_NAME)
world.css_fill('.wrapper-comp-setting .setting-input', "updated ' \" &", index=index)
if world.is_firefox():
world.trigger_event('.wrapper-comp-setting .setting-input', index=index)
set_field_value(index, "updated ' \" &")
verify_modified_display_name_with_special_chars()
@@ -136,11 +132,10 @@ def set_the_weight_to_abc(step, bad_weight):
@step('if I set the max attempts to "(.*)", it will persist as a valid integer$')
def set_the_max_attempts(step, max_attempts_set):
# on firefox with selenium, the behaviour is different. eg 2.34 displays as 2.34 and is persisted as 2
# on firefox with selenium, the behaviour is different.
# eg 2.34 displays as 2.34 and is persisted as 2
index = world.get_setting_entry_index(MAXIMUM_ATTEMPTS)
world.css_fill('.wrapper-comp-setting .setting-input', max_attempts_set, index=index)
if world.is_firefox():
world.trigger_event('.wrapper-comp-setting .setting-input', index=index)
set_field_value(index, max_attempts_set)
world.save_component_and_reopen(step)
value = world.css_value('input.setting-input', index=index)
assert value != "", "max attempts is blank"
@@ -276,12 +271,23 @@ def verify_unset_display_name():
world.verify_setting_entry(world.get_setting_entry(DISPLAY_NAME), DISPLAY_NAME, 'Blank Advanced Problem', False)
def set_field_value(index, value):
"""
Set the field to the specified value.
Note: we cannot use css_fill here because the value is not set
until after you move away from that field.
Instead we will find the element, set its value, then hit the Tab key
to get to the next field.
"""
elem = world.css_find('div.wrapper-comp-setting input.setting-input')[index]
elem.value = value
elem.type(Keys.TAB)
def set_weight(weight):
index = world.get_setting_entry_index(PROBLEM_WEIGHT)
world.css_fill('.wrapper-comp-setting .setting-input', weight, index=index)
if world.is_firefox():
world.trigger_event('.wrapper-comp-setting .setting-input', index=index, event='blur')
world.trigger_event('a.save-button', event='focus')
set_field_value(index, weight)
def open_high_level_source():

View File

@@ -88,11 +88,7 @@ def delete_file(_step, file_name):
assert index != -1
delete_css = "a.remove-asset-button"
world.css_click(delete_css, index=index)
world.wait_for_present(".wrapper-prompt.is-shown")
world.wait(0.2) # wait for css animation
prompt_confirm_css = 'li.nav-item > a.action-primary'
world.css_click(prompt_confirm_css)
world.confirm_studio_prompt()
@step(u'I should see only one "([^"]*)"$')