class AdvancedSettingHelpTest(StudioCourseTest): """ Tests help links on course Advanced Settings page. """ def setUp(self, is_staff=False, test_xss=True): super(AdvancedSettingHelpTest, self).setUp() self.advanced_settings = AdvancedSettingsPage( self.browser, self.course_info['org'], self.course_info['number'], self.course_info['run']) self.advanced_settings.visit() def test_advanced_settings_nav_help(self): """ Scenario: Help link in navigation bar is working on Advanced Settings page. Given that I am on the Advanced Settings page. And I want help about the process And I click the 'Help' in the navigation bar Then Help link should open. And help url should be correct """ expected_url = _get_expected_documentation_url('/index.html') # Assert that help link is correct. assert_nav_help_link( test=self, page=self.advanced_settings, href=expected_url, )
class AdvancedSettingHelpTest(StudioCourseTest): """ Tests help links on course Advanced Settings page. """ def setUp(self, is_staff=False, test_xss=True): super(AdvancedSettingHelpTest, self).setUp() self.advanced_settings = AdvancedSettingsPage( self.browser, self.course_info['org'], self.course_info['number'], self.course_info['run'] ) self.advanced_settings.visit() def test_advanced_settings_nav_help(self): """ Scenario: Help link in navigation bar is working on Advanced Settings page. Given that I am on the Advanced Settings page. And I want help about the process And I click the 'Help' in the navigation bar Then Help link should open. And help url should end with 'index.html' """ href = 'http://edx.readthedocs.io/projects/open-edx-building-and-running-a-course' \ '/en/open-release-ficus.master/index.html' # Assert that help link is correct. assert_nav_help_link( test=self, page=self.advanced_settings, href=href )
class AdvancedSettingHelpTest(StudioCourseTest): """ Tests help links on course Advanced Settings page. """ def setUp(self, is_staff=False, test_xss=True): super(AdvancedSettingHelpTest, self).setUp() self.advanced_settings = AdvancedSettingsPage( self.browser, self.course_info['org'], self.course_info['number'], self.course_info['run'] ) self.advanced_settings.visit() def test_advanced_settings_nav_help(self): """ Scenario: Help link in navigation bar is working on Advanced Settings page. Given that I am on the Advanced Settings page. And I want help about the process And I click the 'Help' in the navigation bar Then Help link should open. And help url should be correct """ expected_url = _get_expected_documentation_url('/index.html') # Assert that help link is correct. assert_nav_help_link( test=self, page=self.advanced_settings, href=expected_url, )
class AdvancedSettingHelpTest(StudioCourseTest): """ Tests help links on course Advanced Settings page. """ def setUp(self, is_staff=False, test_xss=True): super(AdvancedSettingHelpTest, self).setUp() self.advanced_settings = AdvancedSettingsPage( self.browser, self.course_info['org'], self.course_info['number'], self.course_info['run']) self.advanced_settings.visit() def test_advanced_settings_nav_help(self): """ Scenario: Help link in navigation bar is working on Advanced Settings page. Given that I am on the Advanced Settings page. And I want help about the process And I click the 'Help' in the navigation bar Then Help link should open. And help url should end with 'index.html' """ href = 'http://edx.readthedocs.io/projects/open-edx-building-and-running-a-course' \ '/en/latest/index.html' # Assert that help link is correct. assert_nav_help_link(test=self, page=self.advanced_settings, href=href)
def setUp(self, is_staff=True): """ Create a course with a section, subsection, and unit to which to add the component. """ super(ComponentTest, self).setUp(is_staff=is_staff) self.advanced_settings = AdvancedSettingsPage( self.browser, self.course_info['org'], self.course_info['number'], self.course_info['run'])
def setUp(self, is_staff=False, test_xss=True): super(AdvancedSettingHelpTest, self).setUp() self.advanced_settings = AdvancedSettingsPage( self.browser, self.course_info['org'], self.course_info['number'], self.course_info['run']) self.advanced_settings.visit()
def setUp(self): super(AdvancedSettingsValidationTest, self).setUp() self.advanced_settings = AdvancedSettingsPage( self.browser, self.course_info['org'], self.course_info['number'], self.course_info['run'] ) self.type_fields = ['Course Display Name', 'Advanced Module List', 'Discussion Topic Mapping', 'Maximum Attempts', 'Course Announcement Date'] # Before every test, make sure to visit the page first self.advanced_settings.visit()
def setUp(self, is_staff=False, test_xss=True): super(AdvancedSettingHelpTest, self).setUp() self.advanced_settings = AdvancedSettingsPage( self.browser, self.course_info["org"], self.course_info["number"], self.course_info["run"] ) self.advanced_settings.visit()
def setUp(self): # pylint: disable=arguments-differ super(CertificatesTest, self).setUp(is_staff=True, test_xss=False) self.certificates_page = CertificatesPage(self.browser, self.course_info['org'], self.course_info['number'], self.course_info['run']) self.advanced_settings_page = AdvancedSettingsPage( self.browser, self.course_info['org'], self.course_info['number'], self.course_info['run']) self.course_advanced_settings = dict() # Add a verified mode to the course ModeCreationPage(self.browser, self.course_id, mode_slug=u'verified', mode_display_name=u'Verified Certificate', min_price=10, suggested_prices='10,20').visit()
def setUp(self, is_staff=True): """ Create a course with a section, subsection, and unit to which to add the component. """ super(ComponentTest, self).setUp(is_staff=is_staff) self.advanced_settings = AdvancedSettingsPage( self.browser, self.course_info['org'], self.course_info['number'], self.course_info['run'] )
def setUp(self): # pylint: disable=arguments-differ super(CertificatesTest, self).setUp(is_staff=True, test_xss=False) self.certificates_page = CertificatesPage( self.browser, self.course_info['org'], self.course_info['number'], self.course_info['run'] ) self.advanced_settings_page = AdvancedSettingsPage( self.browser, self.course_info['org'], self.course_info['number'], self.course_info['run'] ) self.course_advanced_settings = dict() # Add a verified mode to the course ModeCreationPage( self.browser, self.course_id, mode_slug=u'verified', mode_display_name=u'Verified Certificate', min_price=10, suggested_prices='10,20' ).visit()
class AdvancedSettingsValidationTest(StudioCourseTest): """ Tests for validation feature in Studio's advanced settings tab """ def setUp(self): super(AdvancedSettingsValidationTest, self).setUp() self.advanced_settings = AdvancedSettingsPage( self.browser, self.course_info['org'], self.course_info['number'], self.course_info['run']) self.type_fields = [ 'Course Display Name', 'Advanced Module List', 'Discussion Topic Mapping', 'Maximum Attempts', 'Course Announcement Date' ] # Before every test, make sure to visit the page first self.advanced_settings.visit() def test_modal_shows_one_validation_error(self): """ Test that advanced settings don't save if there's a single wrong input, and that it shows the correct error message in the modal. """ # Feed an integer value for String field. # .set method saves automatically after setting a value course_display_name = self.advanced_settings.get('Course Display Name') self.advanced_settings.set('Course Display Name', 1) self.advanced_settings.wait_for_modal_load() # Test Modal self.check_modal_shows_correct_contents(['Course Display Name']) self.advanced_settings.refresh_and_wait_for_load() self.assertEquals( self.advanced_settings.get('Course Display Name'), course_display_name, 'Wrong input for Course Display Name must not change its value') def test_modal_shows_multiple_validation_errors(self): """ Test that advanced settings don't save with multiple wrong inputs """ # Save original values and feed wrong inputs original_values_map = self.get_settings_fields_of_each_type() self.set_wrong_inputs_to_fields() self.advanced_settings.wait_for_modal_load() # Test Modal self.check_modal_shows_correct_contents(self.type_fields) self.advanced_settings.refresh_and_wait_for_load() for key, val in original_values_map.iteritems(): self.assertEquals( self.advanced_settings.get(key), val, 'Wrong input for Advanced Settings Fields must not change its value' ) def test_undo_changes(self): """ Test that undo changes button in the modal resets all settings changes """ # Save original values and feed wrong inputs original_values_map = self.get_settings_fields_of_each_type() self.set_wrong_inputs_to_fields() # Let modal popup self.advanced_settings.wait_for_modal_load() # Click Undo Changes button self.advanced_settings.undo_changes_via_modal() # Check that changes are undone for key, val in original_values_map.iteritems(): self.assertEquals(self.advanced_settings.get(key), val, 'Undoing Should revert back to original value') def test_manual_change(self): """ Test that manual changes button in the modal keeps settings unchanged """ inputs = { "Course Display Name": 1, "Advanced Module List": 1, "Discussion Topic Mapping": 1, "Maximum Attempts": '"string"', "Course Announcement Date": '"string"', } self.set_wrong_inputs_to_fields() self.advanced_settings.wait_for_modal_load() self.advanced_settings.trigger_manual_changes() # Check that the validation modal went away. self.assertFalse(self.advanced_settings.is_validation_modal_present()) # Iterate through the wrong values and make sure they're still displayed for key, val in inputs.iteritems(): self.assertEquals( str(self.advanced_settings.get(key)), str(val), 'manual change should keep: ' + str(val) + ', but is: ' + str(self.advanced_settings.get(key))) def check_modal_shows_correct_contents(self, wrong_settings_list): """ Helper function that checks if the validation modal contains correct error messages. """ # Check presence of modal self.assertTrue(self.advanced_settings.is_validation_modal_present()) # List of wrong settings item & what is presented in the modal should be the same error_item_names = self.advanced_settings.get_error_item_names() self.assertEqual(set(wrong_settings_list), set(error_item_names)) error_item_messages = self.advanced_settings.get_error_item_messages() self.assertEqual(len(error_item_names), len(error_item_messages)) def get_settings_fields_of_each_type(self): """ Get one of each field type: - String: Course Display Name - List: Advanced Module List - Dict: Discussion Topic Mapping - Integer: Maximum Attempts - Date: Course Announcement Date """ return { "Course Display Name": self.advanced_settings.get('Course Display Name'), "Advanced Module List": self.advanced_settings.get('Advanced Module List'), "Discussion Topic Mapping": self.advanced_settings.get('Discussion Topic Mapping'), "Maximum Attempts": self.advanced_settings.get('Maximum Attempts'), "Course Announcement Date": self.advanced_settings.get('Course Announcement Date'), } def set_wrong_inputs_to_fields(self): """ Set wrong values for the chosen fields """ self.advanced_settings.set_values({ "Course Display Name": 1, "Advanced Module List": 1, "Discussion Topic Mapping": 1, "Maximum Attempts": '"string"', "Course Announcement Date": '"string"', }) def test_only_expected_fields_are_displayed(self): """ Scenario: The Advanced Settings screen displays settings/fields not specifically hidden from view by a developer. Given I have a set of CourseMetadata fields defined for the course When I view the Advanced Settings screen for the course The total number of fields displayed matches the number I expect And the actual fields displayed match the fields I expect to see """ expected_fields = self.advanced_settings.expected_settings_names displayed_fields = self.advanced_settings.displayed_settings_names self.assertEquals(set(displayed_fields), set(expected_fields))
class CertificatesTest(StudioCourseTest): """ Tests for settings/certificates Page. """ shard = 22 def setUp(self): # pylint: disable=arguments-differ super(CertificatesTest, self).setUp(is_staff=True, test_xss=False) self.certificates_page = CertificatesPage( self.browser, self.course_info['org'], self.course_info['number'], self.course_info['run'] ) self.advanced_settings_page = AdvancedSettingsPage( self.browser, self.course_info['org'], self.course_info['number'], self.course_info['run'] ) self.course_advanced_settings = dict() # Add a verified mode to the course ModeCreationPage( self.browser, self.course_id, mode_slug=u'verified', mode_display_name=u'Verified Certificate', min_price=10, suggested_prices='10,20' ).visit() def make_signatory_data(self, prefix='First'): """ Makes signatory dict which can be used in the tests to create certificates """ return { 'name': '{prefix} Signatory Name'.format(prefix=prefix), 'title': '{prefix} Signatory Title'.format(prefix=prefix), 'organization': '{prefix} Signatory Organization'.format(prefix=prefix), } def create_and_verify_certificate(self, course_title_override, existing_certs, signatories): """ Creates a new certificate and verifies that it was properly created. """ self.assertEqual(existing_certs, len(self.certificates_page.certificates)) if existing_certs == 0: self.certificates_page.wait_for_first_certificate_button() self.certificates_page.click_first_certificate_button() else: self.certificates_page.wait_for_add_certificate_button() self.certificates_page.click_add_certificate_button() certificate = self.certificates_page.certificates[existing_certs] # Set the certificate properties certificate.course_title = course_title_override # add signatories added_signatories = 0 for idx, signatory in enumerate(signatories): certificate.signatories[idx].name = signatory['name'] certificate.signatories[idx].title = signatory['title'] certificate.signatories[idx].organization = signatory['organization'] certificate.signatories[idx].upload_signature_image('Signature-{}.png'.format(idx)) added_signatories += 1 if len(signatories) > added_signatories: certificate.click_add_signatory_button() # Save the certificate self.assertEqual(certificate.get_text('.action-primary'), "Create") certificate.click_create_certificate_button() self.assertIn(course_title_override, certificate.course_title) return certificate def test_no_certificates_by_default(self): """ Scenario: Ensure that message telling me to create a new certificate is shown when no certificate exist. Given I have a course without certificates When I go to the Certificates page in Studio Then I see "You have not created any certificates yet." message and a link with text "Set up your certificate" """ self.certificates_page.visit() self.assertTrue(self.certificates_page.no_certificates_message_shown) self.assertIn( "You have not created any certificates yet.", self.certificates_page.no_certificates_message_text ) self.assertIn( "Set up your certificate", self.certificates_page.new_certificate_link_text ) def test_can_create_and_edit_certficate(self): """ Scenario: Ensure that the certificates can be created and edited correctly. Given I have a course without certificates When I click button 'Add your first Certificate' And I set new the course title override and signatory and click the button 'Create' Then I see the new certificate is added and has correct data When I edit the certificate And I change the name and click the button 'Save' Then I see the certificate is saved successfully and has the new name """ self.certificates_page.visit() self.certificates_page.wait_for_first_certificate_button() certificate = self.create_and_verify_certificate( "Course Title Override", 0, [self.make_signatory_data('first'), self.make_signatory_data('second')] ) # Edit the certificate certificate.click_edit_certificate_button() certificate.course_title = "Updated Course Title Override 2" self.assertEqual(certificate.get_text('.action-primary'), "Save") certificate.click_save_certificate_button() self.assertIn("Updated Course Title Override 2", certificate.course_title) def test_can_delete_certificate(self): """ Scenario: Ensure that the user can delete certificate. Given I have a course with 1 certificate And I go to the Certificates page When I delete the Certificate with name "New Certificate" Then I see that there is no certificate When I refresh the page Then I see that the certificate has been deleted """ self.certificates_page.visit() certificate = self.create_and_verify_certificate( "Course Title Override", 0, [self.make_signatory_data('first'), self.make_signatory_data('second')] ) certificate.wait_for_certificate_delete_button() self.assertEqual(len(self.certificates_page.certificates), 1) # Delete the certificate we just created certificate.click_delete_certificate_button() self.certificates_page.click_confirmation_prompt_primary_button() # Reload the page and confirm there are no certificates self.certificates_page.visit() self.assertEqual(len(self.certificates_page.certificates), 0) @skip_if_browser('chrome') # TODO Need to fix this for chrome browser def test_can_create_and_edit_signatories_of_certficate(self): """ Scenario: Ensure that the certificates can be created with signatories and edited correctly. Given I have a course without certificates When I click button 'Add your first Certificate' And I set new the course title override and signatory and click the button 'Create' Then I see the new certificate is added and has one signatory inside it When I click 'Edit' button of signatory panel And I set the name and click the button 'Save' icon Then I see the signatory name updated with newly set name When I refresh the certificates page Then I can see course has one certificate with new signatory name When I click 'Edit' button of signatory panel And click on 'Close' button Then I can see no change in signatory detail """ self.certificates_page.visit() certificate = self.create_and_verify_certificate( "Course Title Override", 0, [self.make_signatory_data('first')] ) self.assertEqual(len(self.certificates_page.certificates), 1) # Edit the signatory in certificate signatory = certificate.signatories[0] signatory.edit() signatory.name = 'Updated signatory name' signatory.title = 'Update signatory title' signatory.organization = 'Updated signatory organization' signatory.save() self.assertEqual(len(self.certificates_page.certificates), 1) #Refreshing the page, So page have the updated certificate object. self.certificates_page.refresh() self.certificates_page.wait_for_page() signatory = self.certificates_page.certificates[0].signatories[0] self.assertIn("Updated signatory name", signatory.name) self.assertIn("Update signatory title", signatory.title) self.assertIn("Updated signatory organization", signatory.organization) signatory.edit() signatory.close() self.assertIn("Updated signatory name", signatory.name) def test_can_cancel_creation_of_certificate(self): """ Scenario: Ensure that creation of a certificate can be canceled correctly. Given I have a course without certificates When I click button 'Add your first Certificate' And I set name of certificate and click the button 'Cancel' Then I see that there is no certificates in the course """ self.certificates_page.visit() self.certificates_page.click_first_certificate_button() certificate = self.certificates_page.certificates[0] certificate.course_title = "Title Override" certificate.click_cancel_edit_certificate() self.assertEqual(len(self.certificates_page.certificates), 0) def test_line_breaks_in_signatory_title(self): """ Scenario: Ensure that line breaks are properly reflected in certificate Given I have a certificate with signatories When I add signatory title with new line character Then I see line break in certificate title """ self.certificates_page.visit() certificate = self.create_and_verify_certificate( "Course Title Override", 0, [ { 'name': 'Signatory Name', 'title': 'Signatory title with new line character \n', 'organization': 'Signatory Organization', } ] ) certificate.wait_for_certificate_delete_button() # Make sure certificate is created self.assertEqual(len(self.certificates_page.certificates), 1) signatory_title = self.certificates_page.get_first_signatory_title() self.assertNotEqual([], re.findall(r'<br\s*/?>', signatory_title)) def test_course_number_in_certificate_details_view(self): """ Scenario: Ensure that Course Number is displayed in certificate details view Given I have a certificate When I visit certificate details page on studio Then I see Course Number next to Course Name """ self.certificates_page.visit() certificate = self.create_and_verify_certificate( "Course Title Override", 0, [self.make_signatory_data('first')] ) certificate.wait_for_certificate_delete_button() # Make sure certificate is created self.assertEqual(len(self.certificates_page.certificates), 1) course_number = self.certificates_page.get_course_number() self.assertEqual(self.course_info['number'], course_number) def test_course_number_override_in_certificate_details_view(self): """ Scenario: Ensure that Course Number Override is displayed in certificate details view Given I have a certificate When I visit certificate details page on studio then course number override should be hidden. Then I visit the course advance settings page and set the value for course override number. Then I see Course Number Override next to Course Name in certificate settings page. """ self.course_advanced_settings.update( {'Course Number Display String': 'Course Number Override String'} ) self.certificates_page.visit() certificate = self.create_and_verify_certificate( "Course Title Override", 0, [self.make_signatory_data('first')] ) self.assertFalse(self.certificates_page.course_number_override().present) certificate.wait_for_certificate_delete_button() # Make sure certificate is created self.assertEqual(len(self.certificates_page.certificates), 1) # set up course number override in Advanced Settings Page self.advanced_settings_page.visit() self.advanced_settings_page.set_values(self.course_advanced_settings) self.advanced_settings_page.wait_for_ajax() self.certificates_page.visit() course_number_override = self.certificates_page.get_course_number_override() self.assertEqual(self.course_advanced_settings['Course Number Display String'], course_number_override) self.assertTrue(self.certificates_page.course_number_override().present)
class AdvancedSettingsValidationTest(StudioCourseTest): """ Tests for validation feature in Studio's advanced settings tab """ def setUp(self): super(AdvancedSettingsValidationTest, self).setUp() self.advanced_settings = AdvancedSettingsPage( self.browser, self.course_info['org'], self.course_info['number'], self.course_info['run'] ) self.type_fields = ['Course Display Name', 'Advanced Module List', 'Discussion Topic Mapping', 'Maximum Attempts', 'Course Announcement Date'] # Before every test, make sure to visit the page first self.advanced_settings.visit() def test_modal_shows_one_validation_error(self): """ Test that advanced settings don't save if there's a single wrong input, and that it shows the correct error message in the modal. """ # Feed an integer value for String field. # .set method saves automatically after setting a value course_display_name = self.advanced_settings.get('Course Display Name') self.advanced_settings.set('Course Display Name', 1) self.advanced_settings.wait_for_modal_load() # Test Modal self.check_modal_shows_correct_contents(['Course Display Name']) self.advanced_settings.refresh_and_wait_for_load() self.assertEquals( self.advanced_settings.get('Course Display Name'), course_display_name, 'Wrong input for Course Display Name must not change its value' ) def test_modal_shows_multiple_validation_errors(self): """ Test that advanced settings don't save with multiple wrong inputs """ # Save original values and feed wrong inputs original_values_map = self.get_settings_fields_of_each_type() self.set_wrong_inputs_to_fields() self.advanced_settings.wait_for_modal_load() # Test Modal self.check_modal_shows_correct_contents(self.type_fields) self.advanced_settings.refresh_and_wait_for_load() for key, val in original_values_map.iteritems(): self.assertEquals( self.advanced_settings.get(key), val, 'Wrong input for Advanced Settings Fields must not change its value' ) def test_undo_changes(self): """ Test that undo changes button in the modal resets all settings changes """ # Save original values and feed wrong inputs original_values_map = self.get_settings_fields_of_each_type() self.set_wrong_inputs_to_fields() # Let modal popup self.advanced_settings.wait_for_modal_load() # Click Undo Changes button self.advanced_settings.undo_changes_via_modal() # Check that changes are undone for key, val in original_values_map.iteritems(): self.assertEquals( self.advanced_settings.get(key), val, 'Undoing Should revert back to original value' ) def test_manual_change(self): """ Test that manual changes button in the modal keeps settings unchanged """ inputs = {"Course Display Name": 1, "Advanced Module List": 1, "Discussion Topic Mapping": 1, "Maximum Attempts": '"string"', "Course Announcement Date": '"string"', } self.set_wrong_inputs_to_fields() self.advanced_settings.wait_for_modal_load() self.advanced_settings.trigger_manual_changes() # Check that the validation modal went away. self.assertFalse(self.advanced_settings.is_validation_modal_present()) # Iterate through the wrong values and make sure they're still displayed for key, val in inputs.iteritems(): self.assertEquals( str(self.advanced_settings.get(key)), str(val), 'manual change should keep: ' + str(val) + ', but is: ' + str(self.advanced_settings.get(key)) ) def check_modal_shows_correct_contents(self, wrong_settings_list): """ Helper function that checks if the validation modal contains correct error messages. """ # Check presence of modal self.assertTrue(self.advanced_settings.is_validation_modal_present()) # List of wrong settings item & what is presented in the modal should be the same error_item_names = self.advanced_settings.get_error_item_names() self.assertEqual(set(wrong_settings_list), set(error_item_names)) error_item_messages = self.advanced_settings.get_error_item_messages() self.assertEqual(len(error_item_names), len(error_item_messages)) def get_settings_fields_of_each_type(self): """ Get one of each field type: - String: Course Display Name - List: Advanced Module List - Dict: Discussion Topic Mapping - Integer: Maximum Attempts - Date: Course Announcement Date """ return { "Course Display Name": self.advanced_settings.get('Course Display Name'), "Advanced Module List": self.advanced_settings.get('Advanced Module List'), "Discussion Topic Mapping": self.advanced_settings.get('Discussion Topic Mapping'), "Maximum Attempts": self.advanced_settings.get('Maximum Attempts'), "Course Announcement Date": self.advanced_settings.get('Course Announcement Date'), } def set_wrong_inputs_to_fields(self): """ Set wrong values for the chosen fields """ self.advanced_settings.set_values( { "Course Display Name": 1, "Advanced Module List": 1, "Discussion Topic Mapping": 1, "Maximum Attempts": '"string"', "Course Announcement Date": '"string"', } ) def test_only_expected_fields_are_displayed(self): """ Scenario: The Advanced Settings screen displays settings/fields not specifically hidden from view by a developer. Given I have a set of CourseMetadata fields defined for the course When I view the Advanced Settings screen for the course The total number of fields displayed matches the number I expect And the actual fields displayed match the fields I expect to see """ expected_fields = self.advanced_settings.expected_settings_names displayed_fields = self.advanced_settings.displayed_settings_names self.assertEquals(set(displayed_fields), set(expected_fields))
class AdvancedSettingsValidationTest(StudioCourseTest): """ Tests for validation feature in Studio's advanced settings tab """ course_name_key = 'Course Display Name' course_name_value = 'Test Name' def setUp(self): super(AdvancedSettingsValidationTest, self).setUp() self.advanced_settings = AdvancedSettingsPage( self.browser, self.course_info['org'], self.course_info['number'], self.course_info['run'] ) self.type_fields = ['Course Display Name', 'Advanced Module List', 'Discussion Topic Mapping', 'Maximum Attempts', 'Course Announcement Date'] # Before every test, make sure to visit the page first self.advanced_settings.visit() def test_course_author_sees_default_advanced_settings(self): """ Scenario: Test that advanced settings have the default settings Given a staff logs in to studio When this user goes to advanced settings page Then this user sees 'Allow Anonymous Discussion Posts' as true And 'Enable Timed Exams' as false And 'Maximum Attempts' as null """ anonymous_discussion_setting = self.advanced_settings.get('Allow Anonymous Discussion Posts') timed_exam_settings = self.advanced_settings.get('Enable Timed Exams') max_attempts = self.advanced_settings.get('Maximum Attempts') page_default_settings = [ anonymous_discussion_setting, timed_exam_settings, max_attempts ] default_anonymous_discussion_setting = 'true' default_timed_exam_settings = 'false' default_max_attempts = 'null' expected_default_settings = [ default_anonymous_discussion_setting, default_timed_exam_settings, default_max_attempts ] self.assertEqual( page_default_settings, expected_default_settings ) def test_keys_appear_alphabetically(self): """ Scenario: Test that advanced settings have all the keys in alphabetic order Given a staff logs in to studio When this user goes to advanced settings page Then he sees all the advanced setting keys in alphabetic order """ key_names = self.advanced_settings.key_names self.assertEqual(key_names, sorted(key_names)) def test_cancel_editing_key_value(self): """ Scenario: Test that advanced settings does not save the key value, if cancel is clicked from notification bar Given a staff logs in to studio When this user goes to advanced settings page and enters and new course name Then he clicks 'cancel' buttin when asked to save changes When this user reloads the page And then he does not see any change in the original course name """ original_course_display_name = self.advanced_settings.get(self.course_name_key) new_course_name = 'New Course Name' type_in_codemirror(self.advanced_settings, 16, new_course_name) self.advanced_settings.cancel() self.advanced_settings.refresh_and_wait_for_load() self.assertNotEqual( original_course_display_name, new_course_name, ( 'original course name:{} can not not be equal to unsaved course name {}'.format( original_course_display_name, new_course_name ) ) ) self.assertEqual( self.advanced_settings.get(self.course_name_key), original_course_display_name, ( 'course name from the page should be same as original_course_display_name:{}'.format( original_course_display_name ) ) ) def test_editing_key_value(self): """ Scenario: Test that advanced settings saves the key value, if save button is clicked from notification bar after the editing Given a staff logs in to studio When this user goes to advanced settings page and enters a new course name And he clicks 'save' button from the notification bar Then he is able to see the updated course name """ new_course_name = ''.join(random.choice(string.ascii_uppercase) for _ in range(10)) self.advanced_settings.set(self.course_name_key, new_course_name) self.assertEqual( self.advanced_settings.get(self.course_name_key), '"{}"'.format(new_course_name), ( 'course name from the page should be same as new_course_name:{}'.format( new_course_name ) ) ) def test_confirmation_is_shown_on_save(self): """ Scenario: Test that advanced settings shows confirmation after editing a field successfully Given a staff logs in to studio When this user goes to advanced settings page and edits any value And he clicks 'save' button from the notification bar Then he is able to see the confirmation message """ self.advanced_settings.set('Maximum Attempts', 5) confirmation_message = self.advanced_settings.confirmation_message self.assertEqual( confirmation_message, 'Your policy changes have been saved.', 'Settings must be saved successfully in order to have confirmation message' ) def test_deprecated_settings_invisible_by_default(self): """ Scenario: Test that advanced settings does not have deprecated settings by default Given a staff logs in to studio When this user goes to advanced settings page Then the user does not see the deprecated settings And sees 'Show Deprecated Settings' button """ button_text = self.advanced_settings.deprecated_settings_button_text self.assertEqual(button_text, 'Show Deprecated Settings') self.assertFalse(self.advanced_settings.is_deprecated_setting_visible()) def test_deprecated_settings_can_be_toggled(self): """ Scenario: Test that advanced settings can toggle deprecated settings Given I am on the Advanced Course Settings page in Studio When I toggle the display of deprecated settings Then deprecated settings are then shown And I toggle the display of deprecated settings Then deprecated settings are not shown """ self.advanced_settings.toggle_deprecated_settings() button_text = self.advanced_settings.deprecated_settings_button_text self.assertEqual( button_text, 'Hide Deprecated Settings', "Button text should change to 'Hide Deprecated Settings' after the click" ) self.assertTrue(self.advanced_settings.is_deprecated_setting_visible()) self.advanced_settings.toggle_deprecated_settings() self.assertFalse(self.advanced_settings.is_deprecated_setting_visible()) self.assertEqual( self.advanced_settings.deprecated_settings_button_text, 'Show Deprecated Settings', "Button text should change to 'Show Deprecated Settings' after the click" ) def test_multi_line_input(self): """ Scenario: Test that advanced settings correctly shows the multi-line input Given I am on the Advanced Course Settings page in Studio When I create a JSON object as a value for "Discussion Topic Mapping" Then it is displayed as formatted """ inputs = { "key": "value", "key_2": "value_2" } json_input = json.dumps(inputs) self.advanced_settings.set('Discussion Topic Mapping', json_input) self.assertEqual( self.advanced_settings.get('Discussion Topic Mapping'), '{\n "key": "value",\n "key_2": "value_2"\n}' ) def test_automatic_quoting_of_non_json_value(self): """ Scenario: Test that advanced settings automatically quotes the field input upon saving 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 """ self.advanced_settings.set(self.course_name_key, self.course_name_value) self.assertEqual( self.advanced_settings.get(self.course_name_key), '"Test Name"' ) def test_validation_error_for_wrong_input_type(self): """ Scenario: Test error if value supplied is of the wrong type Given I am on the Advanced Course Settings page in Studio When I create a JSON object as a value for "Course Display Name" Then I get an error on save And I reload the page Then the policy key value is unchanged """ course_display_name = self.advanced_settings.get('Course Display Name') inputs = { "key": "value", "key_2": "value_2" } json_input = json.dumps(inputs) self.advanced_settings.set('Course Display Name', json_input) self.advanced_settings.wait_for_modal_load() self.check_modal_shows_correct_contents(['Course Display Name']) self.advanced_settings.refresh_and_wait_for_load() self.assertEquals( self.advanced_settings.get('Course Display Name'), course_display_name, 'Wrong input for Course Display Name must not change its value' ) def test_modal_shows_one_validation_error(self): """ Test that advanced settings don't save if there's a single wrong input, and that it shows the correct error message in the modal. """ # Feed an integer value for String field. # .set method saves automatically after setting a value course_display_name = self.advanced_settings.get('Course Display Name') self.advanced_settings.set('Course Display Name', 1) self.advanced_settings.wait_for_modal_load() # Test Modal self.check_modal_shows_correct_contents(['Course Display Name']) self.advanced_settings.refresh_and_wait_for_load() self.assertEquals( self.advanced_settings.get('Course Display Name'), course_display_name, 'Wrong input for Course Display Name must not change its value' ) def test_modal_shows_multiple_validation_errors(self): """ Test that advanced settings don't save with multiple wrong inputs """ # Save original values and feed wrong inputs original_values_map = self.get_settings_fields_of_each_type() self.set_wrong_inputs_to_fields() self.advanced_settings.wait_for_modal_load() # Test Modal self.check_modal_shows_correct_contents(self.type_fields) self.advanced_settings.refresh_and_wait_for_load() for key, val in original_values_map.iteritems(): self.assertEquals( self.advanced_settings.get(key), val, 'Wrong input for Advanced Settings Fields must not change its value' ) def test_undo_changes(self): """ Test that undo changes button in the modal resets all settings changes """ # Save original values and feed wrong inputs original_values_map = self.get_settings_fields_of_each_type() self.set_wrong_inputs_to_fields() # Let modal popup self.advanced_settings.wait_for_modal_load() # Click Undo Changes button self.advanced_settings.undo_changes_via_modal() # Check that changes are undone for key, val in original_values_map.iteritems(): self.assertEquals( self.advanced_settings.get(key), val, 'Undoing Should revert back to original value' ) def test_manual_change(self): """ Test that manual changes button in the modal keeps settings unchanged """ inputs = {"Course Display Name": 1, "Advanced Module List": 1, "Discussion Topic Mapping": 1, "Maximum Attempts": '"string"', "Course Announcement Date": '"string"', } self.set_wrong_inputs_to_fields() self.advanced_settings.wait_for_modal_load() self.advanced_settings.trigger_manual_changes() # Check that the validation modal went away. self.assertFalse(self.advanced_settings.is_validation_modal_present()) # Iterate through the wrong values and make sure they're still displayed for key, val in inputs.iteritems(): self.assertEquals( str(self.advanced_settings.get(key)), str(val), 'manual change should keep: ' + str(val) + ', but is: ' + str(self.advanced_settings.get(key)) ) def check_modal_shows_correct_contents(self, wrong_settings_list): """ Helper function that checks if the validation modal contains correct error messages. """ # Check presence of modal self.assertTrue(self.advanced_settings.is_validation_modal_present()) # List of wrong settings item & what is presented in the modal should be the same error_item_names = self.advanced_settings.get_error_item_names() self.assertEqual(set(wrong_settings_list), set(error_item_names)) error_item_messages = self.advanced_settings.get_error_item_messages() self.assertEqual(len(error_item_names), len(error_item_messages)) def get_settings_fields_of_each_type(self): """ Get one of each field type: - String: Course Display Name - List: Advanced Module List - Dict: Discussion Topic Mapping - Integer: Maximum Attempts - Date: Course Announcement Date """ return { "Course Display Name": self.advanced_settings.get('Course Display Name'), "Advanced Module List": self.advanced_settings.get('Advanced Module List'), "Discussion Topic Mapping": self.advanced_settings.get('Discussion Topic Mapping'), "Maximum Attempts": self.advanced_settings.get('Maximum Attempts'), "Course Announcement Date": self.advanced_settings.get('Course Announcement Date'), } def set_wrong_inputs_to_fields(self): """ Set wrong values for the chosen fields """ self.advanced_settings.set_values( { "Course Display Name": 1, "Advanced Module List": 1, "Discussion Topic Mapping": 1, "Maximum Attempts": '"string"', "Course Announcement Date": '"string"', } ) def test_only_expected_fields_are_displayed(self): """ Scenario: The Advanced Settings screen displays settings/fields not specifically hidden from view by a developer. Given I have a set of CourseMetadata fields defined for the course When I view the Advanced Settings screen for the course The total number of fields displayed matches the number I expect And the actual fields displayed match the fields I expect to see """ expected_fields = self.advanced_settings.expected_settings_names displayed_fields = self.advanced_settings.displayed_settings_names self.assertEquals(set(displayed_fields), set(expected_fields))
class ComponentTest(ContainerBase): """ Test class to add different components. (Not the advanced components) """ def setUp(self, is_staff=True): """ Create a course with a section, subsection, and unit to which to add the component. """ super(ComponentTest, self).setUp(is_staff=is_staff) self.advanced_settings = AdvancedSettingsPage( self.browser, self.course_info['org'], self.course_info['number'], self.course_info['run'] ) def populate_course_fixture(self, course_fixture): course_fixture.add_advanced_settings( {u"advanced_modules": {"value": ["split_test"]}} ) course_fixture.add_children( XBlockFixtureDesc('chapter', 'Test Section').add_children( XBlockFixtureDesc('sequential', 'Test Subsection').add_children( XBlockFixtureDesc('vertical', 'Test Unit') ) ) ) @flaky(max_runs=3) def test_add_html_component(self): """ Scenario: I can add HTML components Given I am in Studio editing a new unit When I add this type of HTML component: | Component | | Text | | Announcement | | Zooming Image Tool | | Raw HTML | Then I see HTML components in this order: | Component | | Text | | Announcement | | Zooming Image Tool | | Raw HTML | """ # Components to be added components = ['Text', 'Announcement', 'Zooming Image Tool', 'Raw HTML'] self.go_to_unit_page() container_page = ContainerPage(self.browser, None) # Add components add_components(container_page, 'html', components) problems = [x_block.name for x_block in container_page.xblocks[1:]] # Assert that components appear in same order as added. self.assertEqual(problems, components) def test_add_latex_html_component(self): """ Scenario: I can add Latex HTML components Given I am in Studio editing a new unit Given I have enabled latex compiler When I add this type of HTML component: | Component | | E-text Written in LaTeX | Then I see HTML components in this order: | Component | | E-text Written in LaTeX | """ # Latex component component = 'E-text Written in LaTeX' # Visit advanced settings page and enable latex compiler. self.advanced_settings.visit() self.advanced_settings.set('Enable LaTeX Compiler', 'True') self.go_to_unit_page() container_page = ContainerPage(self.browser, None) # Add latex component add_component(container_page, 'html', component, is_advanced_problem=False) problem = container_page.xblocks[1] # Asset that component has been added. self.assertEqual(problem.name, component) def test_common_problem_component(self): """ Scenario: I can add Common Problem components Given I am in Studio editing a new unit When I add this type of Problem component: | Component |` | Blank Common Problem | | Checkboxes | | Dropdown | | Multiple Choice | | Numerical Input | | Text Input | Then I see Problem components in this order: | Component | | Blank Common Problem | | Checkboxes | | Dropdown | | Multiple Choice | | Numerical Input | | Text Input | """ # Components to be added. components = ['Blank Common Problem', 'Checkboxes', 'Dropdown', 'Multiple Choice', 'Numerical Input', 'Text Input'] self.go_to_unit_page() container_page = ContainerPage(self.browser, None) # Add components add_components(container_page, 'problem', components) problems = [x_block.name for x_block in container_page.xblocks[1:]] # Assert that components appear in the same order as added. self.assertEqual(problems, components)
class ComponentTest(ContainerBase): """ Test class to add different components. (Not the advanced components) """ def setUp(self, is_staff=True): """ Create a course with a section, subsection, and unit to which to add the component. """ super(ComponentTest, self).setUp(is_staff=is_staff) self.advanced_settings = AdvancedSettingsPage( self.browser, self.course_info['org'], self.course_info['number'], self.course_info['run'] ) def populate_course_fixture(self, course_fixture): course_fixture.add_advanced_settings( {u"advanced_modules": {"value": ["split_test"]}} ) course_fixture.add_children( XBlockFixtureDesc('chapter', 'Test Section').add_children( XBlockFixtureDesc('sequential', 'Test Subsection').add_children( XBlockFixtureDesc('vertical', 'Test Unit') ) ) ) def test_add_html_component(self): """ Scenario: I can add HTML components Given I am in Studio editing a new unit When I add this type of HTML component: | Component | | Text | | Announcement | | Zooming Image Tool | | Raw HTML | Then I see HTML components in this order: | Component | | Text | | Announcement | | Zooming Image Tool | | Raw HTML | """ # Components to be added components = ['Text', 'Announcement', 'Zooming Image Tool', 'Raw HTML'] self.go_to_unit_page() container_page = ContainerPage(self.browser, None) # Add components add_components(container_page, 'html', components) problems = [x_block.name for x_block in container_page.xblocks[1:]] # Assert that components appear in same order as added. self.assertEqual(problems, components) def test_add_latex_html_component(self): """ Scenario: I can add Latex HTML components Given I am in Studio editing a new unit Given I have enabled latex compiler When I add this type of HTML component: | Component | | E-text Written in LaTeX | Then I see HTML components in this order: | Component | | E-text Written in LaTeX | """ # Latex component component = 'E-text Written in LaTeX' # Visit advanced settings page and enable latex compiler. self.advanced_settings.visit() self.advanced_settings.set('Enable LaTeX Compiler', 'True') self.go_to_unit_page() container_page = ContainerPage(self.browser, None) # Add latex component add_component(container_page, 'html', component, is_advanced_problem=False) problem = container_page.xblocks[1] # Asset that component has been added. self.assertEqual(problem.name, component) def test_common_problem_component(self): """ Scenario: I can add Common Problem components Given I am in Studio editing a new unit When I add this type of Problem component: | Component |` | Blank Common Problem | | Checkboxes | | Dropdown | | Multiple Choice | | Numerical Input | | Text Input | Then I see Problem components in this order: | Component | | Blank Common Problem | | Checkboxes | | Dropdown | | Multiple Choice | | Numerical Input | | Text Input | """ # Components to be added. components = ['Blank Common Problem', 'Checkboxes', 'Dropdown', 'Multiple Choice', 'Numerical Input', 'Text Input'] self.go_to_unit_page() container_page = ContainerPage(self.browser, None) # Add components add_components(container_page, 'problem', components) problems = [x_block.name for x_block in container_page.xblocks[1:]] # Assert that components appear in the same order as added. self.assertEqual(problems, components)