diff --git a/cms/djangoapps/contentstore/rest_api/v1/views/tests/test_proctoring.py b/cms/djangoapps/contentstore/rest_api/v1/views/tests/test_proctoring.py index 66b5f46128..8e220a334c 100644 --- a/cms/djangoapps/contentstore/rest_api/v1/views/tests/test_proctoring.py +++ b/cms/djangoapps/contentstore/rest_api/v1/views/tests/test_proctoring.py @@ -277,18 +277,14 @@ class ProctoringExamSettingsPostTests( # response is correct assert response.status_code == status.HTTP_400_BAD_REQUEST - self.assertDictEqual( - response.data, + self.assertIn( { - "detail": [ - { - "proctoring_provider": ( - "The selected proctoring provider, notvalidprovider, is not a valid provider. " - "Please select from one of ['test_proctoring_provider']." - ) - } - ] + "proctoring_provider": ( + "The selected proctoring provider, notvalidprovider, is not a valid provider. " + "Please select from one of ['test_proctoring_provider']." + ) }, + response.data['detail'], ) # course settings have been updated @@ -408,18 +404,14 @@ class ProctoringExamSettingsPostTests( # response is correct assert response.status_code == status.HTTP_400_BAD_REQUEST - self.assertDictEqual( - response.data, + self.assertIn( { - "detail": [ - { - "proctoring_provider": ( - "The selected proctoring provider, lti_external, is not a valid provider. " - "Please select from one of ['null']." - ) - } - ] + "proctoring_provider": ( + "The selected proctoring provider, lti_external, is not a valid provider. " + "Please select from one of ['null']." + ) }, + response.data['detail'], ) # course settings have been updated diff --git a/cms/djangoapps/contentstore/views/tests/test_exam_settings_view.py b/cms/djangoapps/contentstore/views/tests/test_exam_settings_view.py index a7ee7f0ab0..0f38722e12 100644 --- a/cms/djangoapps/contentstore/views/tests/test_exam_settings_view.py +++ b/cms/djangoapps/contentstore/views/tests/test_exam_settings_view.py @@ -162,6 +162,39 @@ class TestExamSettingsView(CourseTestCase, UrlResetMixin): else: assert 'To update these settings go to the Advanced Settings page.' in alert_text + @override_settings( + PROCTORING_BACKENDS={ + 'DEFAULT': 'test_proctoring_provider', + 'proctortrack': {}, + 'test_proctoring_provider': {}, + }, + FEATURES=FEATURES_WITH_EXAM_SETTINGS_ENABLED, + ) + @ddt.data( + "advanced_settings_handler", + "course_handler", + ) + def test_invalid_provider_alert(self, page_handler): + """ + An alert should appear if the course has a proctoring provider that is not valid. + """ + # create an error by setting an invalid proctoring provider + self.course.proctoring_provider = 'invalid_provider' + self.course.enable_proctored_exams = True + self.save_course() + + url = reverse_course_url(page_handler, self.course.id) + resp = self.client.get(url, HTTP_ACCEPT='text/html') + alert_text = self._get_exam_settings_alert_text(resp.content) + assert ( + 'This course has proctored exam settings that are incomplete or invalid.' + in alert_text + ) + assert ( + 'The proctoring provider configured for this course, \'invalid_provider\', is not valid.' + in alert_text + ) + @ddt.data( "advanced_settings_handler", "course_handler", diff --git a/cms/djangoapps/models/settings/course_metadata.py b/cms/djangoapps/models/settings/course_metadata.py index 07ee360ed7..5d4ac5a4a3 100644 --- a/cms/djangoapps/models/settings/course_metadata.py +++ b/cms/djangoapps/models/settings/course_metadata.py @@ -490,6 +490,24 @@ class CourseMetadata: enable_proctoring = block.enable_proctored_exams if enable_proctoring: + + if proctoring_provider_model: + proctoring_provider = proctoring_provider_model.get('value') + else: + proctoring_provider = block.proctoring_provider + + # If the proctoring provider stored in the course block no longer + # matches the available providers for this instance, show an error + if proctoring_provider not in available_providers: + message = ( + f'The proctoring provider configured for this course, \'{proctoring_provider}\', is not valid.' + ) + errors.append({ + 'key': 'proctoring_provider', + 'message': message, + 'model': proctoring_provider_model + }) + # Require a valid escalation email if Proctortrack is chosen as the proctoring provider escalation_email_model = settings_dict.get('proctoring_escalation_email') if escalation_email_model: @@ -497,11 +515,6 @@ class CourseMetadata: else: escalation_email = block.proctoring_escalation_email - if proctoring_provider_model: - proctoring_provider = proctoring_provider_model.get('value') - else: - proctoring_provider = block.proctoring_provider - missing_escalation_email_msg = 'Provider \'{provider}\' requires an exam escalation contact.' if proctoring_provider_model and proctoring_provider == 'proctortrack': if not escalation_email: