diff --git a/cms/djangoapps/contentstore/features/advanced-settings.feature b/cms/djangoapps/contentstore/features/advanced-settings.feature index a0ad8004cc..4790c2eef7 100644 --- a/cms/djangoapps/contentstore/features/advanced-settings.feature +++ b/cms/djangoapps/contentstore/features/advanced-settings.feature @@ -7,18 +7,18 @@ Feature: Advanced (manual) course policy When I select the Advanced Settings Then I see only the display name - Scenario: A course author sees something sensible if there are no policy settings without existing UI controls + Scenario: Test if there are no policy settings without existing UI controls Given I have opened a new course in Studio When I select the Advanced Settings And I delete the display name - Then There are no advanced policy settings - And I refresh and select the Advanced Settings - Then There are no advanced policy settings + Then there are no advanced policy settings + And I reload the page + Then there are no advanced policy settings - Scenario: A course author can add new entries, and they appear alphabetically after save - Given I have opened a new course in Studio - When I select the Advanced Settings - And Create New Entries - Then They are alphabetized - And I refresh and select the Advanced Settings - Then They are alphabetized \ No newline at end of file + Scenario: Add new entries, and they appear alphabetically after save + Given I have opened a new course in Studio + When I select the Advanced Settings + And I create New Entries + Then they are alphabetized + And I reload the page + Then they are alphabetized \ No newline at end of file diff --git a/cms/djangoapps/contentstore/features/advanced-settings.py b/cms/djangoapps/contentstore/features/advanced-settings.py index 19460220d5..5356a96739 100644 --- a/cms/djangoapps/contentstore/features/advanced-settings.py +++ b/cms/djangoapps/contentstore/features/advanced-settings.py @@ -11,41 +11,43 @@ from selenium.webdriver.common.keys import Keys ############### ACTIONS #################### @step('I select the Advanced Settings$') def i_select_advanced_settings(step): - link_css = 'a#settings-tab' - css_click(link_css) - link_css = "[data-section='advanced']" + expand_icon_css = 'li.nav-course-settings i.icon-expand' + if world.browser.is_element_present_by_css(expand_icon_css): + css_click(expand_icon_css) + link_css = 'li.nav-course-settings-advanced a' css_click(link_css) -@step('I refresh and select the Advanced Settings$') -def refresh_and_select_advanced_settings(step): - reload() - i_select_advanced_settings(step) @step('I see only the display name$') def i_see_only_display_name(step): assert_policy_entries(["display_name"], ['"Robot Super Course"']) + @step('I delete the display name') def i_delete_the_display_name(step): delete_entry(0) click_save() -@step("There are no advanced policy settings$") + +@step('there are no advanced policy settings$') def no_policy_settings(step): assert_policy_entries([], []) -@step("Create New Entries") + +@step('create New Entries$') def create_new_entries(step): create_entry("z", "apple") create_entry("a", "zebra") click_save() -@step("They are alphabetized") + +@step('they are alphabetized$') def they_are_alphabetized(step): assert_policy_entries(["a", "display_name", "z"], ['"zebra"', '"Robot Super Course"', '"apple"']) + def create_entry(key, value): - css_click(".new-advanced-policy-item") + css_click_at('a.new-advanced-policy-item') newKey = css_find('#__new_advanced_key__ input').first newKey.fill(key) # For some reason have to get the instance for each command (get error that it is no longer attached to the DOM) @@ -54,6 +56,7 @@ def create_entry(key, value): css_find('.CodeMirror textarea').last._element.send_keys(Keys.ARROW_LEFT) css_find('.CodeMirror textarea').last.fill(value) + def delete_entry(index): """ index is 0-based """ @@ -63,17 +66,20 @@ def delete_entry(index): assert_true(len(delete_buttons) > index, "no delete button exists for entry " + str(index)) delete_buttons[index].click() + def assert_policy_entries(expected_keys, expected_values): assert_entries('.key input', expected_keys) assert_entries('.json', expected_values) + def assert_entries(css, expected_values): webElements = css_find(css) - assert_equal(len(expected_values),len(webElements)) + assert_equal(len(expected_values), len(webElements)) # Sometimes get stale reference if I hold on to the array of elements for counter in range(len(expected_values)): assert_equal(expected_values[counter], css_find(css)[counter].value) + def click_save(): css = ".save-button" def is_shown(driver): @@ -85,6 +91,7 @@ def click_save(): wait_for(is_shown) css_click(css) + def fill_last_field(value): newValue = css_find('#__new_advanced_key__ input').first - newValue.fill(value) \ No newline at end of file + newValue.fill(value) diff --git a/cms/djangoapps/contentstore/features/common.py b/cms/djangoapps/contentstore/features/common.py index d0d007b231..e611d81b4f 100644 --- a/cms/djangoapps/contentstore/features/common.py +++ b/cms/djangoapps/contentstore/features/common.py @@ -10,6 +10,7 @@ from logging import getLogger logger = getLogger(__name__) ########### STEP HELPERS ############## + @step('I (?:visit|access|open) the Studio homepage$') def i_visit_the_studio_homepage(step): # To make this go to port 8001, put @@ -19,14 +20,17 @@ def i_visit_the_studio_homepage(step): signin_css = 'a.action-signin' assert world.browser.is_element_present_by_css(signin_css, 10) + @step('I am logged into Studio$') def i_am_logged_into_studio(step): log_into_studio() + @step('I confirm the alert$') def i_confirm_with_ok(step): world.browser.get_alert().accept() + @step(u'I press the "([^"]*)" delete icon$') def i_press_the_category_delete_icon(step, category): if category == 'section': @@ -37,6 +41,7 @@ def i_press_the_category_delete_icon(step, category): assert False, 'Invalid category: %s' % category css_click(css) + @step('I have opened a new course in Studio$') def i_have_opened_a_new_course(step): clear_courses() @@ -44,13 +49,14 @@ def i_have_opened_a_new_course(step): create_a_course() ####### HELPER FUNCTIONS ############## + def create_studio_user( uname='robot', email='robot+studio@edx.org', password='test', - is_staff=False): + is_staff=False): studio_user = UserFactory.build( - username=uname, + username=uname, email=email, password=password, is_staff=is_staff) @@ -63,6 +69,7 @@ def create_studio_user( user_profile = UserProfileFactory(user=studio_user) + def flush_xmodule_store(): # Flush and initialize the module store # It needs the templates because it creates new records @@ -75,32 +82,53 @@ def flush_xmodule_store(): xmodule.modulestore.django.modulestore().collection.drop() xmodule.templates.update_templates() + def assert_css_with_text(css, text): assert_true(world.browser.is_element_present_by_css(css, 5)) assert_equal(world.browser.find_by_css(css).text, text) + def css_click(css): assert_true(world.browser.is_element_present_by_css(css, 5)) world.browser.find_by_css(css).first.click() + +def css_click_at(css, x=10, y=10): + ''' + A method to click at x,y coordinates of the element + rather than in the center of the element + ''' + assert_true(world.browser.is_element_present_by_css(css, 5)) + e = world.browser.find_by_css(css).first + e.action_chains.move_to_element_with_offset(e._element, x, y) + e.action_chains.click() + e.action_chains.perform() + + def css_fill(css, value): world.browser.find_by_css(css).first.fill(value) + def css_find(css): return world.browser.find_by_css(css) + def wait_for(func): WebDriverWait(world.browser.driver, 10).until(func) + def id_find(id): return world.browser.find_by_id(id) + def reload(): return world.browser.reload() + def clear_courses(): flush_xmodule_store() + def fill_in_course_info( name='Robot Super Course', org='MITx', @@ -109,6 +137,7 @@ def fill_in_course_info( css_fill('.new-course-org', org) css_fill('.new-course-number', num) + def log_into_studio( uname='robot', email='robot+studio@edx.org', @@ -130,6 +159,7 @@ def log_into_studio( assert_true(world.browser.is_element_present_by_css('.new-course-button', 5)) + def create_a_course(): css_click('a.new-course-button') fill_in_course_info() @@ -137,6 +167,7 @@ def create_a_course(): course_title_css = 'span.course-title' assert_true(world.browser.is_element_present_by_css(course_title_css, 5)) + def add_section(name='My Section'): link_css = 'a.new-courseware-section-button' css_click(link_css) diff --git a/common/djangoapps/terrain/steps.py b/common/djangoapps/terrain/steps.py index 6b2a813d8d..a69f8dc7a2 100644 --- a/common/djangoapps/terrain/steps.py +++ b/common/djangoapps/terrain/steps.py @@ -21,6 +21,11 @@ def wait(step, seconds): time.sleep(float(seconds)) +@step('I reload the page$') +def reload_the_page(step): + world.browser.reload() + + @step('I (?:visit|access|open) the homepage$') def i_visit_the_homepage(step): world.browser.visit(django_url('/'))