# disable missing docstring # pylint: disable=missing-docstring import json from lettuce import world, step from nose.tools import assert_equal, assert_true # pylint: disable=no-name-in-module from common import type_in_codemirror, open_new_course from advanced_settings import change_value, ADVANCED_MODULES_KEY from course_import import import_file DISPLAY_NAME = "Display Name" MAXIMUM_ATTEMPTS = "Maximum Attempts" PROBLEM_WEIGHT = "Problem Weight" RANDOMIZATION = 'Randomization' SHOW_ANSWER = "Show Answer" SHOW_RESET_BUTTON = "Show Reset Button" TIMER_BETWEEN_ATTEMPTS = "Timer Between Attempts" MATLAB_API_KEY = "Matlab API key" @step('I have created a Blank Common Problem$') def i_created_blank_common_problem(step): step.given('I am in Studio editing a new unit') step.given("I have created another Blank Common Problem") @step('I have created a unit with advanced module "(.*)"$') def i_created_unit_with_advanced_module(step, advanced_module): step.given('I am in Studio editing a new unit') url = world.browser.url step.given("I select the Advanced Settings") change_value(step, ADVANCED_MODULES_KEY, '["{}"]'.format(advanced_module)) world.visit(url) world.wait_for_xmodule() @step('I have created an advanced component "(.*)" of type "(.*)"') def i_create_new_advanced_component(step, component_type, advanced_component): world.create_component_instance( step=step, category='advanced', component_type=component_type, advanced_component=advanced_component ) @step('I have created another Blank Common Problem$') def i_create_new_common_problem(step): world.create_component_instance( step=step, category='problem', component_type='Blank Common Problem' ) @step('when I mouseover on "(.*)"') def i_mouseover_on_html_component(step, element_class): action_css = '.{}'.format(element_class) world.trigger_event(action_css, event='mouseover') @step(u'I can see Reply to Annotation link$') def i_see_reply_to_annotation_link(_step): css_selector = 'a.annotatable-reply' world.wait_for_visible(css_selector) @step(u'I see that page has scrolled "(.*)" when I click on "(.*)" link$') def i_see_annotation_problem_page_scrolls(_step, scroll_direction, link_css): scroll_js = "$(window).scrollTop();" scroll_height_before = world.browser.evaluate_script(scroll_js) world.css_click("a.{}".format(link_css)) scroll_height_after = world.browser.evaluate_script(scroll_js) if scroll_direction == "up": assert scroll_height_after < scroll_height_before elif scroll_direction == "down": assert scroll_height_after > scroll_height_before @step('I have created an advanced problem of type "(.*)"$') def i_create_new_advanced_problem(step, component_type): world.create_component_instance( step=step, category='problem', component_type=component_type, is_advanced=True ) @step('I edit and select Settings$') def i_edit_and_select_settings(_step): world.edit_component_and_select_settings() @step('I see the advanced settings and their expected values$') def i_see_advanced_settings_with_values(step): world.verify_all_setting_entries( [ [DISPLAY_NAME, "Blank Common Problem", True], [MATLAB_API_KEY, "", False], [MAXIMUM_ATTEMPTS, "", False], [PROBLEM_WEIGHT, "", False], [RANDOMIZATION, "Never", False], [SHOW_ANSWER, "Finished", False], [SHOW_RESET_BUTTON, "False", False], [TIMER_BETWEEN_ATTEMPTS, "0", False], ]) @step('I can modify the display name') 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.set_field_value(index, '3.4') 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('the problem display name is "(.*)"$') def verify_problem_display_name(step, name): assert_equal(name.upper(), world.browser.find_by_css('.problem-header').text) @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.set_field_value(index, "updated ' \" &") verify_modified_display_name_with_special_chars() @step('I can specify html in the display name and save') def i_can_modify_the_display_name_with_html(_step): """ If alert appear on save then UnexpectedAlertPresentException will occur and test will fail. """ index = world.get_setting_entry_index(DISPLAY_NAME) world.set_field_value(index, "<script>alert('test')</script>") verify_modified_display_name_with_html() world.save_component() @step('my special characters and persisted on save') def special_chars_persisted_on_save(step): world.save_component_and_reopen(step) verify_modified_display_name_with_special_chars() @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, "Never", False) @step('I can set the weight to "(.*)"?') def i_can_set_weight(_step, weight): set_weight(weight) verify_modified_weight() @step('my change to weight is persisted') def my_change_to_weight_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_unset_weight(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 "(.*)", it remains unset') def set_the_weight_to_abc(step, bad_weight): set_weight(bad_weight) # We show the clear button immediately on type, hence the "True" here. world.verify_setting_entry(world.get_setting_entry(PROBLEM_WEIGHT), PROBLEM_WEIGHT, "", True) world.save_component_and_reopen(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 "(.*)", it will persist as a valid integer$') def set_the_max_attempts(step, max_attempts_set): # on firefox with selenium, the behavior is different. # eg 2.34 displays as 2.34 and is persisted as 2 index = world.get_setting_entry_index(MAXIMUM_ATTEMPTS) world.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" assert int(value) >= 0 @step('Edit High Level Source is not visible') def edit_high_level_source_not_visible(step): verify_high_level_source_links(step, False) @step('Edit High Level Source is visible') def edit_high_level_source_links_visible(step): verify_high_level_source_links(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 the advanced settings and their expected values") @step('I have enabled latex compiler') def enable_latex_compiler(step): url = world.browser.url step.given("I select the Advanced Settings") change_value(step, 'Enable LaTeX Compiler', 'true') world.visit(url) world.wait_for_xmodule() @step('I have created a LaTeX Problem') def create_latex_problem(step): step.given('I am in Studio editing a new unit') step.given('I have enabled latex compiler') world.create_component_instance( step=step, category='problem', component_type='Problem Written in LaTeX', is_advanced=True ) @step('I edit and compile the High Level Source') def edit_latex_source(_step): open_high_level_source() type_in_codemirror(1, "hi") world.css_click('.hls-compile') @step('my change to the High Level Source is persisted') def high_level_source_persisted(_step): def verify_text(driver): css_sel = '.problem div>span' return world.css_text(css_sel) == 'hi' world.wait_for(verify_text, timeout=10) @step('I view the High Level Source I see my changes') def high_level_source_in_editor(_step): open_high_level_source() assert_equal('hi', world.css_value('.source-edit-box')) @step(u'I have an empty course') def i_have_empty_course(step): open_new_course() @step(u'I import the file "([^"]*)"$') def i_import_the_file(_step, filename): import_file(filename) @step(u'I go to the vertical "([^"]*)"$') def i_go_to_vertical(_step, vertical): world.css_click("span:contains('{0}')".format(vertical)) @step(u'I go to the unit "([^"]*)"$') def i_go_to_unit(_step, unit): loc = "window.location = $(\"span:contains('{0}')\").closest('a').attr('href')".format(unit) world.browser.execute_script(loc) @step(u'I see a message that says "([^"]*)"$') def i_can_see_message(_step, msg): msg = json.dumps(msg) # escape quotes world.css_has_text("h2.title", msg) @step(u'I can edit the problem$') def i_can_edit_problem(_step): world.edit_component() @step(u'I edit first blank advanced problem for annotation response$') def i_edit_blank_problem_for_annotation_response(_step): world.edit_component(1) text = """ <problem> <annotationresponse> <annotationinput><text>Text of annotation</text></annotationinput> </annotationresponse> </problem>""" type_in_codemirror(0, text) world.save_component() @step(u'I can see cheatsheet$') def verify_cheat_sheet_displaying(_step): world.css_click("a.cheatsheet-toggle") css_selector = 'article.simple-editor-cheatsheet' world.wait_for_visible(css_selector) def verify_high_level_source_links(step, visible): if visible: assert_true(world.is_css_present('.launch-latex-compiler'), msg="Expected to find the latex button but it is not present.") else: assert_true(world.is_css_not_present('.launch-latex-compiler'), msg="Expected not to find the latex button but it is present.") world.cancel_component(step) 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, '3.4', True) def verify_modified_display_name_with_special_chars(): world.verify_setting_entry(world.get_setting_entry(DISPLAY_NAME), DISPLAY_NAME, "updated ' \" &", True) def verify_modified_display_name_with_html(): world.verify_setting_entry(world.get_setting_entry(DISPLAY_NAME), DISPLAY_NAME, "<script>alert('test')</script>", True) def verify_unset_display_name(): world.verify_setting_entry(world.get_setting_entry(DISPLAY_NAME), DISPLAY_NAME, 'Blank Advanced Problem', False) def set_weight(weight): index = world.get_setting_entry_index(PROBLEM_WEIGHT) world.set_field_value(index, weight) def open_high_level_source(): world.edit_component() world.css_click('.launch-latex-compiler > a')