diff --git a/cms/djangoapps/contentstore/features/advanced-settings.feature b/cms/djangoapps/contentstore/features/advanced-settings.feature index c35fe1ed13..af97709ad0 100644 --- a/cms/djangoapps/contentstore/features/advanced-settings.feature +++ b/cms/djangoapps/contentstore/features/advanced-settings.feature @@ -2,33 +2,41 @@ Feature: Advanced (manual) course policy In order to specify course policy settings for which no custom user interface exists I want to be able to manually enter JSON key/value pairs -# Scenario: A course author sees default advanced settings -# Given I have opened a new course in Studio -# When I select the Advanced Settings -# Then I see default advanced settings + Scenario: A course author sees default advanced settings + Given I have opened a new course in Studio + When I select the Advanced Settings + Then I see default advanced settings + Scenario: Add new entries, and they appear alphabetically after save + Given I am on the Advanced Course Settings page in Studio + Then the settings are alphabetized -# Scenario: Test cancel editing key value -# Given I am on the Advanced Course Settings page in Studio -# When I edit the value of a policy key -# And I press the "Cancel" notification button -# Then the policy key value is unchanged -# + Scenario: Test cancel editing key value + Given I am on the Advanced Course Settings page in Studio + When I edit the value of a policy key + And I press the "Cancel" notification button + Then the policy key value is unchanged + And I reload the page + Then the policy key value is unchanged Scenario: Test editing key value Given I am on the Advanced Course Settings page in Studio When I edit the value of a policy key And I press the "Save" notification button Then the policy key value is changed -# -# Scenario: Add new entries, and they appear alphabetically after save -# Given I am on the Advanced Course Settings page in Studio -# When I create New Entries -# Then they are alphabetized -# And I reload the page -# Then they are alphabetized -# -# Scenario: Test how multi-line input appears -# Given I am on the Advanced Course Settings page in Studio -# When I create a JSON object -# Then it is displayed as formatted + And I reload the page + Then the policy key value is changed + + Scenario: Test how multi-line input appears + Given I am on the Advanced Course Settings page in Studio + When I create a JSON object as a value + Then it is displayed as formatted + And I reload the page + Then it is displayed as formatted + + Scenario: Test automatic quoting of non-JSON values + Given I am on the Advanced Course Settings page in Studio + When I create a non-JSON value not in quotes + Then it is displayed as a string + And I reload the page + Then it is displayed as a string diff --git a/cms/djangoapps/contentstore/features/advanced-settings.py b/cms/djangoapps/contentstore/features/advanced-settings.py index ff44ecebfe..7e86e94a31 100644 --- a/cms/djangoapps/contentstore/features/advanced-settings.py +++ b/cms/djangoapps/contentstore/features/advanced-settings.py @@ -1,6 +1,7 @@ from lettuce import world, step from common import * import time +from terrain.steps import reload_the_page from selenium.common.exceptions import WebDriverException from selenium.webdriver.support import expected_conditions as EC @@ -11,6 +12,10 @@ http://selenium.googlecode.com/svn/trunk/docs/api/py/webdriver/selenium.webdrive """ from selenium.webdriver.common.keys import Keys +KEY_CSS = '.key input.policy-key' +VALUE_CSS = 'textarea.json' +DISPLAY_NAME_KEY = "display_name" +DISPLAY_NAME_VALUE = '"Robot Super Course"' ############### ACTIONS #################### @step('I select the Advanced Settings$') @@ -28,32 +33,26 @@ def i_am_on_advanced_course_settings(step): step.given('I select the Advanced Settings') -# TODO: this is copied from terrain's step.py. Need to figure out how to share that code. -@step('I reload the page$') -def reload_the_page(step): - world.browser.reload() - - @step(u'I press the "([^"]*)" notification button$') def press_the_notification_button(step, name): def is_visible(driver): - return EC.visibility_of_element_located((By.CSS_SELECTOR,css,)) - def is_invisible(driver): - return EC.invisibility_of_element_located((By.CSS_SELECTOR,css,)) + return EC.visibility_of_element_located((By.CSS_SELECTOR, css,)) + + # def is_invisible(driver): + # return EC.invisibility_of_element_located((By.CSS_SELECTOR,css,)) css = 'a.%s-button' % name.lower() wait_for(is_visible) + time.sleep(float(1)) + css_click_at(css) - try: - css_click_at(css) - wait_for(is_invisible) - except WebDriverException, e: - css_click_at(css) - wait_for(is_invisible) - - if name == "Save": - css = "" - wait_for(is_visible) +# is_invisible is not returning a boolean, not working +# try: +# css_click_at(css) +# wait_for(is_invisible) +# except WebDriverException, e: +# css_click_at(css) +# wait_for(is_invisible) @step(u'I edit the value of a policy key$') @@ -62,16 +61,18 @@ def edit_the_value_of_a_policy_key(step): It is hard to figure out how to get into the CodeMirror area, so cheat and do it from the policy key field :) """ - policy_key_css = 'input.policy-key' - index = get_index_of("display_name") - e = css_find(policy_key_css)[index] + e = css_find(KEY_CSS)[get_index_of(DISPLAY_NAME_KEY)] e._element.send_keys(Keys.TAB, Keys.END, Keys.ARROW_LEFT, ' ', 'X') -@step('I create a JSON object$') +@step('I create a JSON object as a value$') def create_JSON_object(step): - create_entry("json", '{"key": "value", "key_2": "value_2"}') - click_save() + change_display_name_value(step, '{"key": "value", "key_2": "value_2"}') + + +@step('I create a non-JSON value not in quotes$') +def create_value_not_in_quotes(step): + change_display_name_value(step, 'quote me') ############### RESULTS #################### @@ -79,21 +80,32 @@ def create_JSON_object(step): def i_see_default_advanced_settings(step): # Test only a few of the existing properties (there are around 34 of them) assert_policy_entries( - ["advanced_modules", "display_name", "show_calculator"], ["[]", '"Robot Super Course"', "false"], False) + ["advanced_modules", DISPLAY_NAME_KEY, "show_calculator"], ["[]", DISPLAY_NAME_VALUE, "false"]) -@step('they are alphabetized$') +@step('the settings are alphabetized$') def they_are_alphabetized(step): - assert_policy_entries(["a", "display_name", "z"], ['"zebra"', '"Robot Super Course"', '"apple"']) + key_elements = css_find(KEY_CSS) + all_keys = [] + for key in key_elements: + all_keys.append(key.value) + + assert_equal(sorted(all_keys), all_keys, "policy keys were not sorted") @step('it is displayed as formatted$') def it_is_formatted(step): - assert_policy_entries(["display_name", "json"], ['"Robot Super Course"', '{\n "key": "value",\n "key_2": "value_2"\n}']) + assert_policy_entries([DISPLAY_NAME_KEY], ['{\n "key": "value",\n "key_2": "value_2"\n}']) + + +@step('it is displayed as a string') +def it_is_formatted(step): + assert_policy_entries([DISPLAY_NAME_KEY], ['"quote me"']) + @step(u'the policy key value is unchanged$') def the_policy_key_value_is_unchanged(step): - assert_equal(get_display_name_value(), '"Robot Super Course"') + assert_equal(get_display_name_value(), DISPLAY_NAME_VALUE) @step(u'the policy key value is changed$') @@ -102,36 +114,33 @@ def the_policy_key_value_is_changed(step): ############# HELPERS ############### -def assert_policy_entries(expected_keys, expected_values, assertLength=True): - key_css = '.key input.policy-key' - key_elements = css_find(key_css) - if assertLength: - assert_equal(len(expected_keys), len(key_elements)) - - value_css = 'textarea.json' +def assert_policy_entries(expected_keys, expected_values): for counter in range(len(expected_keys)): index = get_index_of(expected_keys[counter]) assert_false(index == -1, "Could not find key: " + expected_keys[counter]) - assert_equal(expected_values[counter], css_find(value_css)[index].value, "value is incorrect") + assert_equal(expected_values[counter], css_find(VALUE_CSS)[index].value, "value is incorrect") def get_index_of(expected_key): - key_css = '.key input.policy-key' - for counter in range(len(css_find(key_css))): + for counter in range(len(css_find(KEY_CSS))): # Sometimes get stale reference if I hold on to the array of elements - key = css_find(key_css)[counter].value + key = css_find(KEY_CSS)[counter].value if key == expected_key: return counter return -1 -def click_save(): - css = "a.save-button" - css_click_at(css) - - def get_display_name_value(): - policy_value_css = 'textarea.json' - index = get_index_of("display_name") - return css_find(policy_value_css)[index].value + index = get_index_of(DISPLAY_NAME_KEY) + return css_find(VALUE_CSS)[index].value + + +def change_display_name_value(step, new_value): + e = css_find(KEY_CSS)[get_index_of(DISPLAY_NAME_KEY)] + display_name = get_display_name_value() + for count in range(len(display_name)): + e._element.send_keys(Keys.TAB, Keys.END, Keys.BACK_SPACE) + # Must delete "" before typing the JSON value + e._element.send_keys(Keys.TAB, Keys.END, Keys.BACK_SPACE, Keys.BACK_SPACE, new_value) + press_the_notification_button(step, "Save") \ No newline at end of file diff --git a/cms/djangoapps/models/settings/course_metadata.py b/cms/djangoapps/models/settings/course_metadata.py index 3972751082..ed11a6d7a4 100644 --- a/cms/djangoapps/models/settings/course_metadata.py +++ b/cms/djangoapps/models/settings/course_metadata.py @@ -10,8 +10,7 @@ class CourseMetadata(object): For CRUD operations on metadata fields which do not have specific editors on the other pages including any user generated ones. The objects have no predefined attrs but instead are obj encodings of the editable metadata. ''' - # __new_advanced_key__ is used by client not server; so, could argue against it being here - FILTERED_LIST = XModuleDescriptor.system_metadata_fields + ['start', 'end', 'enrollment_start', 'enrollment_end', 'tabs', 'graceperiod', '__new_advanced_key__'] + FILTERED_LIST = XModuleDescriptor.system_metadata_fields + ['start', 'end', 'enrollment_start', 'enrollment_end', 'tabs', 'graceperiod'] @classmethod def fetch(cls, course_location): diff --git a/cms/static/client_templates/advanced_entry.html b/cms/static/client_templates/advanced_entry.html index 1dbd99cc8b..6be22e2116 100644 --- a/cms/static/client_templates/advanced_entry.html +++ b/cms/static/client_templates/advanced_entry.html @@ -1,5 +1,5 @@
Note: Your changes will not take effect until you save your - progress. Take care with key and value formatting, as validation is not implemented.
+ progress. Take care with policy value formatting, as validation is not implemented.