From 6627ca5635947aca187e0988207230bca9134cc6 Mon Sep 17 00:00:00 2001 From: Jay Zoldak Date: Thu, 30 May 2013 12:26:18 -0400 Subject: [PATCH] Tidy up the new lettuce tests for metadata editing a bit. --- .../component_settings_editor_helpers.py | 22 +++++++----- .../features/discussion-editor.py | 6 ++-- .../contentstore/features/html-editor.py | 6 ++-- .../contentstore/features/problem-editor.py | 36 +++++++++++++++---- common/djangoapps/terrain/ui_helpers.py | 19 ++++++++-- 5 files changed, 67 insertions(+), 22 deletions(-) diff --git a/cms/djangoapps/contentstore/features/component_settings_editor_helpers.py b/cms/djangoapps/contentstore/features/component_settings_editor_helpers.py index 6e35d1711f..69c9f40ae2 100644 --- a/cms/djangoapps/contentstore/features/component_settings_editor_helpers.py +++ b/cms/djangoapps/contentstore/features/component_settings_editor_helpers.py @@ -5,13 +5,13 @@ from lettuce import world from nose.tools import assert_equal from terrain.steps import reload_the_page -import time @world.absorb def create_component_instance(step, component_button_css, instance_id, expected_css): click_new_component_button(step, component_button_css) click_component_from_menu(instance_id, expected_css) + @world.absorb def click_new_component_button(step, component_button_css): step.given('I have opened a new course section in Studio') @@ -20,20 +20,21 @@ def click_new_component_button(step, component_button_css): world.css_click('a.new-unit-item') world.css_click(component_button_css) + @world.absorb def click_component_from_menu(instance_id, expected_css): - new_instance = world.browser.find_by_id(instance_id) - assert_equal(1, len(new_instance)) - # TODO: why is this sleep necessary? - time.sleep(float(1)) - new_instance[0].click() + elem_css = "a[data-location='%s']" % instance_id + assert_equal(1, len(world.css_find(elem_css))) + world.css_click(elem_css) assert_equal(1, len(world.css_find(expected_css))) + @world.absorb def edit_component_and_select_settings(): world.css_click('a.edit-button') world.css_click('#settings-mode') + @world.absorb def verify_setting_entry(setting, display_name, value, explicitly_set): assert_equal(display_name, setting.find_by_css('.setting-label')[0].value) @@ -42,13 +43,15 @@ def verify_setting_entry(setting, display_name, value, explicitly_set): assert_equal(explicitly_set, settingClearButton.has_class('active')) assert_equal(not explicitly_set, settingClearButton.has_class('inactive')) + @world.absorb def verify_all_setting_entries(expected_entries): settings = world.browser.find_by_css('.wrapper-comp-setting') assert_equal(len(expected_entries), len(settings)) for (counter, setting) in enumerate(settings): world.verify_setting_entry(setting, expected_entries[counter][0], - expected_entries[counter][1], expected_entries[counter][2]) + expected_entries[counter][1], expected_entries[counter][2]) + @world.absorb def save_component_and_reopen(step): @@ -58,6 +61,7 @@ def save_component_and_reopen(step): reload_the_page(step) edit_component_and_select_settings() + @world.absorb def cancel_component(step): world.css_click("a.cancel-button") @@ -65,10 +69,12 @@ def cancel_component(step): # they are not persisted. Refresh the browser to make sure the changes were not persisted. reload_the_page(step) + @world.absorb def revert_setting_entry(label): get_setting_entry(label).find_by_css('.setting-clear')[0].click() + @world.absorb def get_setting_entry(label): settings = world.browser.find_by_css('.wrapper-comp-setting') @@ -76,5 +82,3 @@ def get_setting_entry(label): if setting.find_by_css('.setting-label')[0].value == label: return setting return None - - diff --git a/cms/djangoapps/contentstore/features/discussion-editor.py b/cms/djangoapps/contentstore/features/discussion-editor.py index 4e661a89e1..a7ec923192 100644 --- a/cms/djangoapps/contentstore/features/discussion-editor.py +++ b/cms/djangoapps/contentstore/features/discussion-editor.py @@ -3,10 +3,12 @@ from lettuce import world, step + @step('I have created a Discussion Tag$') -def i_created_blank_common_problem(step): +def i_created_discussion_tag(step): world.create_component_instance(step, '.large-discussion-icon', 'i4x://edx/templates/discussion/Discussion_Tag', - '.xmodule_DiscussionModule') + '.xmodule_DiscussionModule') + @step('I see three alphabetized settings and their expected values$') def i_see_only_the_display_name(step): diff --git a/cms/djangoapps/contentstore/features/html-editor.py b/cms/djangoapps/contentstore/features/html-editor.py index 564d4d986c..ea5064b27d 100644 --- a/cms/djangoapps/contentstore/features/html-editor.py +++ b/cms/djangoapps/contentstore/features/html-editor.py @@ -3,10 +3,12 @@ from lettuce import world, step + @step('I have created a Blank HTML Page$') -def i_created_blank_common_problem(step): +def i_created_blank_html_page(step): world.create_component_instance(step, '.large-html-icon', 'i4x://edx/templates/html/Blank_HTML_Page', - '.xmodule_HtmlModule') + '.xmodule_HtmlModule') + @step('I see only the HTML display name setting$') def i_see_only_the_html_display_name(step): diff --git a/cms/djangoapps/contentstore/features/problem-editor.py b/cms/djangoapps/contentstore/features/problem-editor.py index ade1f07b2d..f75a60415c 100644 --- a/cms/djangoapps/contentstore/features/problem-editor.py +++ b/cms/djangoapps/contentstore/features/problem-editor.py @@ -5,21 +5,24 @@ from lettuce import world, step from nose.tools import assert_equal DISPLAY_NAME = "Display Name" -MAXIMUM_ATTEMPTS="Maximum Attempts" -PROBLEM_WEIGHT="Problem Weight" -RANDOMIZATION='Randomization' -SHOW_ANSWER="Show Answer" +MAXIMUM_ATTEMPTS = "Maximum Attempts" +PROBLEM_WEIGHT = "Problem Weight" +RANDOMIZATION = 'Randomization' +SHOW_ANSWER = "Show Answer" + ############### ACTIONS #################### @step('I have created a Blank Common Problem$') def i_created_blank_common_problem(step): world.create_component_instance(step, '.large-problem-icon', 'i4x://edx/templates/problem/Blank_Common_Problem', - '.xmodule_CapaModule') + '.xmodule_CapaModule') + @step('I edit and select Settings$') def i_edit_and_select_settings(step): world.edit_component_and_select_settings() + @step('I see five alphabetized settings and their expected values$') def i_see_five_settings_with_values(step): world.verify_all_setting_entries( @@ -31,58 +34,69 @@ def i_see_five_settings_with_values(step): [SHOW_ANSWER, "Finished", True] ]) + @step('I can modify the display name') def i_can_modify_the_display_name(step): world.get_setting_entry(DISPLAY_NAME).find_by_css('.setting-input')[0].fill('modified') verify_modified_display_name() + @step('my display name change is persisted on save') def my_display_name_change_is_persisted_on_save(step): world.save_component_and_reopen(step) verify_modified_display_name() + @step('I can revert the display name to unset') def can_revert_display_name_to_unset(step): world.revert_setting_entry(DISPLAY_NAME) verify_unset_display_name() + @step('my display name is unset on save') def my_display_name_is_persisted_on_save(step): world.save_component_and_reopen(step) verify_unset_display_name() + @step('I can select Per Student for Randomization') def i_can_select_per_student_for_randomization(step): world.browser.select(RANDOMIZATION, "Per Student") verify_modified_randomization() + @step('my change to randomization is persisted') def my_change_to_randomization_is_persisted(step): world.save_component_and_reopen(step) verify_modified_randomization() + @step('I can revert to the default value for randomization') def i_can_revert_to_default_for_randomization(step): world.revert_setting_entry(RANDOMIZATION) world.save_component_and_reopen(step) world.verify_setting_entry(world.get_setting_entry(RANDOMIZATION), RANDOMIZATION, "Always", False) + @step('I can set the weight to 3.5') def i_can_set_weight_to_3_5(step): world.get_setting_entry(PROBLEM_WEIGHT).find_by_css('.setting-input')[0].fill('3.5') verify_modified_weight() + @step('my change to weight is persisted') def my_change_to_randomization_is_persisted(step): world.save_component_and_reopen(step) verify_modified_weight() + @step('I can revert to the default value of unset for weight') def i_can_revert_to_default_for_randomization(step): world.revert_setting_entry(PROBLEM_WEIGHT) world.save_component_and_reopen(step) world.verify_setting_entry(world.get_setting_entry(PROBLEM_WEIGHT), PROBLEM_WEIGHT, "", False) + @step('if I set the weight to abc, it remains unset') def set_the_weight_to_abc(step): world.get_setting_entry(PROBLEM_WEIGHT).find_by_css('.setting-input')[0].fill('abc') @@ -92,6 +106,7 @@ def set_the_weight_to_abc(step): # But no change was actually ever sent to the model, so on reopen, explicitly_set is False world.verify_setting_entry(world.get_setting_entry(PROBLEM_WEIGHT), PROBLEM_WEIGHT, "", False) + @step('if I set the max attempts to 2.34, the max attempts are persisted as 234') def set_the_weight_to_abc(step): world.get_setting_entry(MAXIMUM_ATTEMPTS).find_by_css('.setting-input')[0].fill('2.34') @@ -99,6 +114,7 @@ def set_the_weight_to_abc(step): world.save_component_and_reopen(step) world.verify_setting_entry(world.get_setting_entry(MAXIMUM_ATTEMPTS), MAXIMUM_ATTEMPTS, "234", True) + @step('I set the max attempts to -3, the max attempts are persisted as 1') def set_max_attempts_to_neg_3(step): world.get_setting_entry(MAXIMUM_ATTEMPTS).find_by_css('.setting-input')[0].fill('-3') @@ -106,20 +122,24 @@ def set_max_attempts_to_neg_3(step): world.save_component_and_reopen(step) world.verify_setting_entry(world.get_setting_entry(MAXIMUM_ATTEMPTS), MAXIMUM_ATTEMPTS, "1", True) + @step('Edit High Level Source is not visible') def edit_high_level_source_not_visible(step): verify_high_level_source(step, False) + @step('Edit High Level Source is visible') def edit_high_level_source_visible(step): verify_high_level_source(step, True) + @step('If I press Cancel my changes are not persisted') def cancel_does_not_save_changes(step): world.cancel_component(step) step.given("I edit and select Settings") step.given("I see five alphabetized settings and their expected values") + @step('I have created a LaTeX Problem') def create_latex_problem(step): world.click_new_component_button(step, '.large-problem-icon') @@ -128,20 +148,24 @@ def create_latex_problem(step): world.css_click('#ui-id-2') world.click_component_from_menu("i4x://edx/templates/problem/Problem_Written_in_LaTeX", '.xmodule_CapaModule') + def verify_high_level_source(step, visible): assert_equal(visible, world.is_css_present('.launch-latex-compiler')) world.cancel_component(step) assert_equal(visible, world.is_css_present('.upload-button')) + def verify_modified_weight(): world.verify_setting_entry(world.get_setting_entry(PROBLEM_WEIGHT), PROBLEM_WEIGHT, "3.5", True) + def verify_modified_randomization(): world.verify_setting_entry(world.get_setting_entry(RANDOMIZATION), RANDOMIZATION, "Per Student", True) + def verify_modified_display_name(): world.verify_setting_entry(world.get_setting_entry(DISPLAY_NAME), DISPLAY_NAME, 'modified', True) + def verify_unset_display_name(): world.verify_setting_entry(world.get_setting_entry(DISPLAY_NAME), DISPLAY_NAME, '', False) - diff --git a/common/djangoapps/terrain/ui_helpers.py b/common/djangoapps/terrain/ui_helpers.py index 79e9b0afdb..45252dbb7b 100644 --- a/common/djangoapps/terrain/ui_helpers.py +++ b/common/djangoapps/terrain/ui_helpers.py @@ -4,7 +4,7 @@ from lettuce import world import time from urllib import quote_plus -from selenium.common.exceptions import WebDriverException +from selenium.common.exceptions import WebDriverException, StaleElementReferenceException from selenium.webdriver.support import expected_conditions as EC from selenium.webdriver.common.by import By from selenium.webdriver.support.ui import WebDriverWait @@ -63,7 +63,7 @@ def css_click(css_selector): # Occassionally, MathJax or other JavaScript can cover up # an element temporarily. # If this happens, wait a second, then try again - time.sleep(1) + world.wait(1) world.browser.find_by_css(css_selector).click() @@ -79,6 +79,14 @@ def css_click_at(css, x=10, y=10): e.action_chains.perform() +@world.absorb +def id_click(elem_id): + """ + Perform a click on an element as specified by its id + """ + world.css_click('#%s' % elem_id) + + @world.absorb def css_fill(css_selector, text): world.browser.find_by_css(css_selector).first.fill(text) @@ -94,7 +102,12 @@ def css_text(css_selector): # Wait for the css selector to appear if world.is_css_present(css_selector): - return world.browser.find_by_css(css_selector).first.text + try: + return world.browser.find_by_css(css_selector).first.text + except StaleElementReferenceException: + # The DOM was still redrawing. Wait a second and try again. + world.wait(1) + return world.browser.find_by_css(css_selector).first.text else: return ""