Refactor wait_for methods in ui_helpers for acceptance tests.
This commit is contained in:
@@ -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$')
|
||||
|
||||
@@ -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):
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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():
|
||||
|
||||
@@ -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 "([^"]*)"$')
|
||||
|
||||
Reference in New Issue
Block a user