Files
edx-platform/common/test/acceptance/tests/studio/test_studio_settings.py
Clinton Blackburn 6ff614800c Updated auto_auth endpoint to always return JSON
Defaulting to a plaintext response makes no sense for an endpoint that is intended to be used by machines for testing. The endpoint now returns JSON only unless a redirect action is triggered.
2017-05-31 23:18:05 -04:00

959 lines
39 KiB
Python

# coding: utf-8
"""
Acceptance tests for Studio's Setting pages
"""
from __future__ import unicode_literals
import os
from textwrap import dedent
from bok_choy.promise import EmptyPromise
from mock import patch
from nose.plugins.attrib import attr
from base_studio_test import StudioCourseTest
from common.test.acceptance.fixtures.course import XBlockFixtureDesc
from common.test.acceptance.pages.common.utils import add_enrollment_course_modes
from common.test.acceptance.pages.lms.courseware import CoursewarePage
from common.test.acceptance.pages.studio.overview import CourseOutlinePage
from common.test.acceptance.pages.studio.settings import SettingsPage
from common.test.acceptance.pages.studio.settings_advanced import AdvancedSettingsPage
from common.test.acceptance.pages.studio.settings_group_configurations import GroupConfigurationsPage
from common.test.acceptance.pages.studio.utils import get_input_value
from common.test.acceptance.tests.helpers import create_user_partition_json, element_has_text
from xmodule.partitions.partitions import Group
@attr(shard=8)
class ContentGroupConfigurationTest(StudioCourseTest):
"""
Tests for content groups in the Group Configurations Page.
There are tests for the experiment groups in test_studio_split_test.
"""
def setUp(self):
super(ContentGroupConfigurationTest, self).setUp()
self.group_configurations_page = GroupConfigurationsPage(
self.browser,
self.course_info['org'],
self.course_info['number'],
self.course_info['run']
)
self.outline_page = CourseOutlinePage(
self.browser,
self.course_info['org'],
self.course_info['number'],
self.course_info['run']
)
def populate_course_fixture(self, course_fixture):
"""
Populates test course with chapter, sequential, and 1 problems.
The problem is visible only to Group "alpha".
"""
course_fixture.add_children(
XBlockFixtureDesc('chapter', 'Test Section').add_children(
XBlockFixtureDesc('sequential', 'Test Subsection').add_children(
XBlockFixtureDesc('vertical', 'Test Unit')
)
)
)
def create_and_verify_content_group(self, name, existing_groups):
"""
Creates a new content group and verifies that it was properly created.
"""
self.assertEqual(existing_groups, len(self.group_configurations_page.content_groups))
if existing_groups == 0:
self.group_configurations_page.create_first_content_group()
else:
self.group_configurations_page.add_content_group()
config = self.group_configurations_page.content_groups[existing_groups]
config.name = name
# Save the content group
self.assertEqual(config.get_text('.action-primary'), "Create")
self.assertFalse(config.delete_button_is_present)
config.save()
self.assertIn(name, config.name)
return config
def test_no_content_groups_by_default(self):
"""
Scenario: Ensure that message telling me to create a new content group is
shown when no content groups exist.
Given I have a course without content groups
When I go to the Group Configuration page in Studio
Then I see "You have not created any content groups yet." message
"""
self.group_configurations_page.visit()
self.assertTrue(self.group_configurations_page.no_content_groups_message_is_present)
self.assertIn(
"You have not created any content groups yet.",
self.group_configurations_page.no_content_groups_message_text
)
def test_can_create_and_edit_content_groups(self):
"""
Scenario: Ensure that the content groups can be created and edited correctly.
Given I have a course without content groups
When I click button 'Add your first Content Group'
And I set new the name and click the button 'Create'
Then I see the new content is added and has correct data
And I click 'New Content Group' button
And I set the name and click the button 'Create'
Then I see the second content group is added and has correct data
When I edit the second content group
And I change the name and click the button 'Save'
Then I see the second content group is saved successfully and has the new name
"""
self.group_configurations_page.visit()
self.create_and_verify_content_group("New Content Group", 0)
second_config = self.create_and_verify_content_group("Second Content Group", 1)
# Edit the second content group
second_config.edit()
second_config.name = "Updated Second Content Group"
self.assertEqual(second_config.get_text('.action-primary'), "Save")
second_config.save()
self.assertIn("Updated Second Content Group", second_config.name)
def test_cannot_delete_used_content_group(self):
"""
Scenario: Ensure that the user cannot delete used content group.
Given I have a course with 1 Content Group
And I go to the Group Configuration page
When I try to delete the Content Group with name "New Content Group"
Then I see the delete button is disabled.
"""
self.course_fixture._update_xblock(self.course_fixture._course_location, {
"metadata": {
u"user_partitions": [
create_user_partition_json(
0,
'Configuration alpha,',
'Content Group Partition',
[Group("0", 'alpha')],
scheme="cohort"
)
],
},
})
problem_data = dedent("""
<problem markdown="Simple Problem" max_attempts="" weight="">
<p>Choose Yes.</p>
<choiceresponse>
<checkboxgroup>
<choice correct="true">Yes</choice>
</checkboxgroup>
</choiceresponse>
</problem>
""")
vertical = self.course_fixture.get_nested_xblocks(category="vertical")[0]
self.course_fixture.create_xblock(
vertical.locator,
XBlockFixtureDesc('problem', "VISIBLE TO ALPHA", data=problem_data, metadata={"group_access": {0: [0]}}),
)
self.group_configurations_page.visit()
config = self.group_configurations_page.content_groups[0]
self.assertTrue(config.delete_button_is_disabled)
def test_can_delete_unused_content_group(self):
"""
Scenario: Ensure that the user can delete unused content group.
Given I have a course with 1 Content Group
And I go to the Group Configuration page
When I delete the Content Group with name "New Content Group"
Then I see that there is no Content Group
When I refresh the page
Then I see that the content group has been deleted
"""
self.group_configurations_page.visit()
config = self.create_and_verify_content_group("New Content Group", 0)
self.assertTrue(config.delete_button_is_present)
self.assertEqual(len(self.group_configurations_page.content_groups), 1)
# Delete content group
config.delete()
self.assertEqual(len(self.group_configurations_page.content_groups), 0)
self.group_configurations_page.visit()
self.assertEqual(len(self.group_configurations_page.content_groups), 0)
def test_must_supply_name(self):
"""
Scenario: Ensure that validation of the content group works correctly.
Given I have a course without content groups
And I create new content group without specifying a name click the button 'Create'
Then I see error message "Content Group name is required."
When I set a name and click the button 'Create'
Then I see the content group is saved successfully
"""
self.group_configurations_page.visit()
self.group_configurations_page.create_first_content_group()
config = self.group_configurations_page.content_groups[0]
config.save()
self.assertEqual(config.mode, 'edit')
self.assertEqual("Group name is required", config.validation_message)
config.name = "Content Group Name"
config.save()
self.assertIn("Content Group Name", config.name)
def test_can_cancel_creation_of_content_group(self):
"""
Scenario: Ensure that creation of a content group can be canceled correctly.
Given I have a course without content groups
When I click button 'Add your first Content Group'
And I set new the name and click the button 'Cancel'
Then I see that there is no content groups in the course
"""
self.group_configurations_page.visit()
self.group_configurations_page.create_first_content_group()
config = self.group_configurations_page.content_groups[0]
config.name = "Content Group"
config.cancel()
self.assertEqual(0, len(self.group_configurations_page.content_groups))
def test_content_group_empty_usage(self):
"""
Scenario: When content group is not used, ensure that the link to outline page works correctly.
Given I have a course without content group
And I create new content group
Then I see a link to the outline page
When I click on the outline link
Then I see the outline page
"""
self.group_configurations_page.visit()
config = self.create_and_verify_content_group("New Content Group", 0)
config.toggle()
config.click_outline_anchor()
# Waiting for the page load and verify that we've landed on course outline page
self.outline_page.wait_for_page()
@attr(shard=5)
class EnrollmentTrackModeTest(StudioCourseTest):
def setUp(self, is_staff=True, test_xss=True):
super(EnrollmentTrackModeTest, self).setUp(is_staff=is_staff)
self.audit_track = "Audit"
self.verified_track = "Verified"
self.staff_user = self.user
def test_all_course_modes_present(self):
"""
This test is meant to ensure that all the course modes show up as groups
on the Group configuration page within the Enrollment Tracks section.
It also checks to make sure that the edit buttons are not available.
"""
add_enrollment_course_modes(self.browser, self.course_id, ['audit', 'verified'])
group_configurations_page = GroupConfigurationsPage(
self.browser,
self.course_info['org'],
self.course_info['number'],
self.course_info['run']
)
group_configurations_page.visit()
self.assertTrue(group_configurations_page.enrollment_track_section_present)
# Make sure the edit buttons are not available.
self.assertFalse(group_configurations_page.enrollment_track_edit_present)
groups = group_configurations_page.get_enrollment_groups()
for g in [self.audit_track, self.verified_track]:
self.assertTrue(g in groups)
def test_one_course_mode(self):
"""
The purpose of this test is to ensure that when there is 1 or fewer course modes
the enrollment track section is not shown.
"""
add_enrollment_course_modes(self.browser, self.course_id, ['audit'])
group_configurations_page = GroupConfigurationsPage(
self.browser,
self.course_info['org'],
self.course_info['number'],
self.course_info['run']
)
group_configurations_page.visit()
self.assertFalse(group_configurations_page.enrollment_track_section_present)
groups = group_configurations_page.get_enrollment_groups()
self.assertEqual(len(groups), 0)
@attr(shard=8)
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))
@attr(shard=1)
class ContentLicenseTest(StudioCourseTest):
"""
Tests for course-level licensing (that is, setting the license,
for an entire course's content, to All Rights Reserved or Creative Commons)
"""
def setUp(self): # pylint: disable=arguments-differ
super(ContentLicenseTest, self).setUp()
self.outline_page = CourseOutlinePage(
self.browser,
self.course_info['org'],
self.course_info['number'],
self.course_info['run']
)
self.settings_page = SettingsPage(
self.browser,
self.course_info['org'],
self.course_info['number'],
self.course_info['run']
)
self.lms_courseware = CoursewarePage(
self.browser,
self.course_id,
)
self.settings_page.visit()
def test_empty_license(self):
"""
When I visit the Studio settings page,
I see that the course license is "All Rights Reserved" by default.
Then I visit the LMS courseware page,
and I see that the default course license is displayed.
"""
self.assertEqual(self.settings_page.course_license, "All Rights Reserved")
self.lms_courseware.visit()
self.assertEqual(self.lms_courseware.course_license, "© All Rights Reserved")
def test_arr_license(self):
"""
When I visit the Studio settings page,
and I set the course license to "All Rights Reserved",
and I refresh the page,
I see that the course license is "All Rights Reserved".
Then I visit the LMS courseware page,
and I see that the course license is "All Rights Reserved".
"""
self.settings_page.course_license = "All Rights Reserved"
self.settings_page.save_changes()
self.settings_page.refresh_and_wait_for_load()
self.assertEqual(self.settings_page.course_license, "All Rights Reserved")
self.lms_courseware.visit()
self.assertEqual(self.lms_courseware.course_license, "© All Rights Reserved")
def test_cc_license(self):
"""
When I visit the Studio settings page,
and I set the course license to "Creative Commons",
and I refresh the page,
I see that the course license is "Creative Commons".
Then I visit the LMS courseware page,
and I see that the course license is "Some Rights Reserved".
"""
self.settings_page.course_license = "Creative Commons"
self.settings_page.save_changes()
self.settings_page.refresh_and_wait_for_load()
self.assertEqual(self.settings_page.course_license, "Creative Commons")
self.lms_courseware.visit()
# The course_license text will include a bunch of screen reader text to explain
# the selected options
self.assertIn("Some Rights Reserved", self.lms_courseware.course_license)
@attr('a11y')
class StudioSettingsA11yTest(StudioCourseTest):
"""
Class to test Studio pages accessibility.
"""
def setUp(self): # pylint: disable=arguments-differ
super(StudioSettingsA11yTest, self).setUp()
self.settings_page = SettingsPage(self.browser, self.course_info['org'], self.course_info['number'],
self.course_info['run'])
def test_studio_settings_page_a11y(self):
"""
Check accessibility of SettingsPage.
"""
self.settings_page.visit()
self.settings_page.wait_for_page()
self.settings_page.a11y_audit.config.set_rules({
"ignore": [
'link-href', # TODO: AC-590
],
})
self.settings_page.a11y_audit.check_for_accessibility_errors()
@attr('a11y')
class StudioSubsectionSettingsA11yTest(StudioCourseTest):
"""
Class to test accessibility on the subsection settings modals.
"""
def setUp(self): # pylint: disable=arguments-differ
browser = os.environ.get('SELENIUM_BROWSER', 'firefox')
# This test will fail if run using phantomjs < 2.0, due to an issue with bind()
# See https://github.com/ariya/phantomjs/issues/10522 for details.
# The course_outline uses this function, and as such will not fully load when run
# under phantomjs 1.9.8. So, to prevent this test from timing out at course_outline.visit(),
# force the use of firefox vs the standard a11y test usage of phantomjs 1.9.8.
# TODO: remove this block once https://openedx.atlassian.net/browse/TE-1047 is resolved.
if browser == 'phantomjs':
browser = 'firefox'
with patch.dict(os.environ, {'SELENIUM_BROWSER': browser}):
super(StudioSubsectionSettingsA11yTest, self).setUp(is_staff=True)
self.course_outline = CourseOutlinePage(
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({
"enable_proctored_exams": {"value": "true"}
})
course_fixture.add_children(
XBlockFixtureDesc('chapter', 'Test Section 1').add_children(
XBlockFixtureDesc('sequential', 'Test Subsection 1').add_children(
XBlockFixtureDesc('problem', 'Test Problem 1')
)
)
)
def test_special_exams_menu_a11y(self):
"""
Given that I am a staff member
And I am editing settings on the special exams menu
Then that menu is accessible
"""
self.course_outline.visit()
self.course_outline.open_subsection_settings_dialog()
self.course_outline.select_advanced_tab()
# limit the scope of the audit to the special exams tab on the modal dialog
self.course_outline.a11y_audit.config.set_scope(
include=['section.edit-settings-timed-examination']
)
self.course_outline.a11y_audit.check_for_accessibility_errors()
@attr(shard=1)
class StudioSettingsImageUploadTest(StudioCourseTest):
"""
Class to test course settings image uploads.
"""
def setUp(self): # pylint: disable=arguments-differ
super(StudioSettingsImageUploadTest, self).setUp()
self.settings_page = SettingsPage(self.browser, self.course_info['org'], self.course_info['number'],
self.course_info['run'])
self.settings_page.visit()
# Ensure jquery is loaded before running a jQuery
self.settings_page.wait_for_ajax()
# This text appears towards the end of the work that jQuery is performing on the page
self.settings_page.wait_for_jquery_value('input#course-name:text', 'test_run')
def test_upload_course_card_image(self):
# upload image
file_to_upload = 'image.jpg'
self.settings_page.upload_image('#upload-course-image', file_to_upload)
self.assertIn(file_to_upload, self.settings_page.get_uploaded_image_path('#course-image'))
def test_upload_course_banner_image(self):
# upload image
file_to_upload = 'image.jpg'
self.settings_page.upload_image('#upload-banner-image', file_to_upload)
self.assertIn(file_to_upload, self.settings_page.get_uploaded_image_path('#banner-image'))
def test_upload_course_video_thumbnail_image(self):
# upload image
file_to_upload = 'image.jpg'
self.settings_page.upload_image('#upload-video-thumbnail-image', file_to_upload)
self.assertIn(file_to_upload, self.settings_page.get_uploaded_image_path('#video-thumbnail-image'))
@attr(shard=1)
class CourseSettingsTest(StudioCourseTest):
"""
Class to test course settings.
"""
COURSE_START_DATE_CSS = "#course-start-date"
COURSE_END_DATE_CSS = "#course-end-date"
ENROLLMENT_START_DATE_CSS = "#course-enrollment-start-date"
ENROLLMENT_END_DATE_CSS = "#course-enrollment-end-date"
COURSE_START_TIME_CSS = "#course-start-time"
COURSE_END_TIME_CSS = "#course-end-time"
ENROLLMENT_START_TIME_CSS = "#course-enrollment-start-time"
ENROLLMENT_END_TIME_CSS = "#course-enrollment-end-time"
course_start_date = '12/20/2013'
course_end_date = '12/26/2013'
enrollment_start_date = '12/01/2013'
enrollment_end_date = '12/10/2013'
dummy_time = "15:30"
def setUp(self, is_staff=False, test_xss=True):
super(CourseSettingsTest, self).setUp()
self.settings_page = SettingsPage(
self.browser,
self.course_info['org'],
self.course_info['number'],
self.course_info['run']
)
# Before every test, make sure to visit the page first
self.settings_page.visit()
self.ensure_input_fields_are_loaded()
def set_course_dates(self):
"""
Set dates for the course.
"""
dates_dictionary = {
self.COURSE_START_DATE_CSS: self.course_start_date,
self.COURSE_END_DATE_CSS: self.course_end_date,
self.ENROLLMENT_START_DATE_CSS: self.enrollment_start_date,
self.ENROLLMENT_END_DATE_CSS: self.enrollment_end_date
}
self.settings_page.set_element_values(dates_dictionary)
def ensure_input_fields_are_loaded(self):
"""
Ensures values in input fields are loaded.
"""
EmptyPromise(
lambda: self.settings_page.q(css='#course-organization').attrs('value')[0],
"Waiting for input fields to be loaded"
).fulfill()
def test_user_can_set_course_date(self):
"""
Scenario: User can set course dates
Given I have opened a new course in Studio
When I select Schedule and Details
And I set course dates
And I press the "Save" notification button
And I reload the page
Then I see the set dates
"""
# Set dates
self.set_course_dates()
# Set times
time_dictionary = {
self.COURSE_START_TIME_CSS: self.dummy_time,
self.ENROLLMENT_END_TIME_CSS: self.dummy_time
}
self.settings_page.set_element_values(time_dictionary)
# Save changes
self.settings_page.save_changes()
self.settings_page.refresh_and_wait_for_load()
self.ensure_input_fields_are_loaded()
css_selectors = [self.COURSE_START_DATE_CSS, self.COURSE_END_DATE_CSS,
self.ENROLLMENT_START_DATE_CSS, self.ENROLLMENT_END_DATE_CSS,
self.COURSE_START_TIME_CSS, self.ENROLLMENT_END_TIME_CSS]
expected_values = [self.course_start_date, self.course_end_date,
self.enrollment_start_date, self.enrollment_end_date,
self.dummy_time, self.dummy_time]
# Assert changes have been persistent.
self.assertEqual(
[get_input_value(self.settings_page, css_selector) for css_selector in css_selectors],
expected_values
)
def test_clear_previously_set_course_dates(self):
"""
Scenario: User can clear previously set course dates (except start date)
Given I have set course dates
And I clear all the dates except start
And I press the "Save" notification button
And I reload the page
Then I see cleared dates
"""
# Set dates
self.set_course_dates()
# Clear all dates except start date
values_to_set = {
self.COURSE_END_DATE_CSS: '',
self.ENROLLMENT_START_DATE_CSS: '',
self.ENROLLMENT_END_DATE_CSS: ''
}
self.settings_page.set_element_values(values_to_set)
# Save changes and refresh the page
self.settings_page.save_changes()
self.settings_page.refresh_and_wait_for_load()
self.ensure_input_fields_are_loaded()
css_selectors = [self.COURSE_START_DATE_CSS, self.COURSE_END_DATE_CSS,
self.ENROLLMENT_START_DATE_CSS, self.ENROLLMENT_END_DATE_CSS]
expected_values = [self.course_start_date, '', '', '']
# Assert changes have been persistent.
self.assertEqual(
[get_input_value(self.settings_page, css_selector) for css_selector in css_selectors],
expected_values
)
def test_cannot_clear_the_course_start_date(self):
"""
Scenario: User cannot clear the course start date
Given I have set course dates
And I press the "Save" notification button
And I clear the course start date
Then I receive a warning about course start date
And I reload the page
And the previously set start date is shown
"""
# Set dates
self.set_course_dates()
# Save changes
self.settings_page.save_changes()
# Get default start date
default_start_date = get_input_value(self.settings_page, self.COURSE_START_DATE_CSS)
# Set course start date to empty
self.settings_page.set_element_values({self.COURSE_START_DATE_CSS: ''})
# Make sure error message is show with appropriate message
error_message_css = '.message-error'
self.settings_page.wait_for_element_presence(error_message_css, 'Error message is present')
self.assertEqual(element_has_text(self.settings_page, error_message_css,
"The course must have an assigned start date."), True)
# Refresh the page and assert start date has not changed.
self.settings_page.refresh_and_wait_for_load()
self.ensure_input_fields_are_loaded()
self.assertEqual(
get_input_value(self.settings_page, self.COURSE_START_DATE_CSS),
default_start_date
)
def test_user_can_correct_course_start_date_warning(self):
"""
Scenario: User can correct the course start date warning
Given I have tried to clear the course start
And I have entered a new course start date
And I press the "Save" notification button
Then The warning about course start date goes away
And I reload the page
Then my new course start date is shown
"""
# Set course start date to empty
self.settings_page.set_element_values({self.COURSE_START_DATE_CSS: ''})
# Make sure we get error message
error_message_css = '.message-error'
self.settings_page.wait_for_element_presence(error_message_css, 'Error message is present')
self.assertEqual(element_has_text(self.settings_page, error_message_css,
"The course must have an assigned start date."), True)
# Set new course start value
self.settings_page.set_element_values({self.COURSE_START_DATE_CSS: self.course_start_date})
self.settings_page.un_focus_input_field()
# Error message disappears
self.settings_page.wait_for_element_absence(error_message_css, 'Error message is not present')
# Save the changes and refresh the page.
self.settings_page.save_changes()
self.settings_page.refresh_and_wait_for_load()
self.ensure_input_fields_are_loaded()
# Assert changes are persistent.
self.assertEqual(
get_input_value(self.settings_page, self.COURSE_START_DATE_CSS),
self.course_start_date
)
def test_settings_are_only_persisted_when_saved(self):
"""
Scenario: Settings are only persisted when saved
Given I have set course dates
And I press the "Save" notification button
When I change fields
And I reload the page
Then I do not see the changes
"""
# Set course dates.
self.set_course_dates()
# Save changes.
self.settings_page.save_changes()
default_value_enrollment_start_date = get_input_value(self.settings_page,
self.ENROLLMENT_START_TIME_CSS)
# Set the value of enrollment start time and
# reload the page without saving.
self.settings_page.set_element_values({self.ENROLLMENT_START_TIME_CSS: self.dummy_time})
self.settings_page.refresh_and_wait_for_load()
self.ensure_input_fields_are_loaded()
css_selectors = [self.COURSE_START_DATE_CSS, self.COURSE_END_DATE_CSS,
self.ENROLLMENT_START_DATE_CSS, self.ENROLLMENT_END_DATE_CSS,
self.ENROLLMENT_START_TIME_CSS]
expected_values = [self.course_start_date, self.course_end_date,
self.enrollment_start_date, self.enrollment_end_date,
default_value_enrollment_start_date]
# Assert that value of enrolment start time
# is not saved.
self.assertEqual(
[get_input_value(self.settings_page, css_selector) for css_selector in css_selectors],
expected_values
)
def test_settings_are_reset_on_cancel(self):
"""
Scenario: Settings are reset on cancel
Given I have set course dates
And I press the "Save" notification button
When I change fields
And I press the "Cancel" notification button
Then I do not see the changes
"""
# Set course date
self.set_course_dates()
# Save changes
self.settings_page.save_changes()
default_value_enrollment_start_date = get_input_value(self.settings_page,
self.ENROLLMENT_START_TIME_CSS)
# Set value but don't save it.
self.settings_page.set_element_values({self.ENROLLMENT_START_TIME_CSS: self.dummy_time})
self.settings_page.click_button("cancel")
# Make sure changes are not saved after cancel.
css_selectors = [self.COURSE_START_DATE_CSS, self.COURSE_END_DATE_CSS,
self.ENROLLMENT_START_DATE_CSS, self.ENROLLMENT_END_DATE_CSS,
self.ENROLLMENT_START_TIME_CSS]
expected_values = [self.course_start_date, self.course_end_date,
self.enrollment_start_date, self.enrollment_end_date,
default_value_enrollment_start_date]
self.assertEqual(
[get_input_value(self.settings_page, css_selector) for css_selector in css_selectors],
expected_values
)
def test_confirmation_is_shown_on_save(self):
"""
Scenario: Confirmation is shown on save
Given I have opened a new course in Studio
When I select Schedule and Details
And I change the "<field>" field to "<value>"
And I press the "Save" notification button
Then I see a confirmation that my changes have been saved
"""
# Set date
self.settings_page.set_element_values({self.COURSE_START_DATE_CSS: self.course_start_date})
# Confirmation is showed upon save.
# Save_changes function ensures that save
# confirmation is shown.
self.settings_page.save_changes()
def test_changes_in_course_overview_show_a_confirmation(self):
"""
Scenario: Changes in Course Overview show a confirmation
Given I have opened a new course in Studio
When I select Schedule and Details
And I change the course overview
And I press the "Save" notification button
Then I see a confirmation that my changes have been saved
"""
# Change the value of course overview
self.settings_page.change_course_description('Changed overview')
# Save changes
# Save_changes function ensures that save
# confirmation is shown.
self.settings_page.save_changes()
def test_user_cannot_save_invalid_settings(self):
"""
Scenario: User cannot save invalid settings
Given I have opened a new course in Studio
When I select Schedule and Details
And I change the "Course Start Date" field to ""
Then the save notification button is disabled
"""
# Change the course start date to invalid date.
self.settings_page.set_element_values({self.COURSE_START_DATE_CSS: ''})
# Confirm that save button is disabled.
self.assertEqual(self.settings_page.is_element_present(".action-primary.action-save.is-disabled"), True)