diff --git a/lms/djangoapps/courseware/toggles.py b/lms/djangoapps/courseware/toggles.py index 51220c4561..a1d9450008 100644 --- a/lms/djangoapps/courseware/toggles.py +++ b/lms/djangoapps/courseware/toggles.py @@ -113,6 +113,30 @@ COURSEWARE_OPTIMIZED_RENDER_XBLOCK = CourseWaffleFlag( WAFFLE_FLAG_NAMESPACE, 'optimized_render_xblock', __name__ ) +# .. toggle_name: courseware.mfe_special_exams +# .. toggle_implementation: CourseWaffleFlag +# .. toggle_default: False +# .. toggle_description: Waffle flag to enable special exams experience without +# redirecting students to LMS. +# .. toggle_use_cases: temporary +# .. toggle_creation_date: 2021-4-29 +# .. toggle_target_removal_date: 2021-6-30 +# .. toggle_warnings: None +COURSEWARE_MICROFRONTEND_SPECIAL_EXAMS = CourseWaffleFlag( + WAFFLE_FLAG_NAMESPACE, 'mfe_special_exams', __name__ +) + + +def mfe_special_exams_is_active(course_key: CourseKey) -> bool: + """ + Can we see a course special exams in the Learning MFE? + """ + # DENY: Old Mongo courses don't work in the MFE. + if course_key.deprecated: + return False + # OTHERWISE: Defer to value of waffle flag for this course run and user. + return COURSEWARE_MICROFRONTEND_SPECIAL_EXAMS.is_enabled(course_key) + def courseware_mfe_is_active(course_key: CourseKey) -> bool: """ diff --git a/openedx/core/djangoapps/courseware_api/serializers.py b/openedx/core/djangoapps/courseware_api/serializers.py index bd055fe0ff..dad21fd24f 100644 --- a/openedx/core/djangoapps/courseware_api/serializers.py +++ b/openedx/core/djangoapps/courseware_api/serializers.py @@ -116,6 +116,7 @@ class CourseInfoSerializer(serializers.Serializer): # pylint: disable=abstract- verify_identity_url = AbsoluteURLField() verification_status = serializers.CharField() linkedin_add_to_profile_url = serializers.URLField() + is_mfe_special_exams_enabled = serializers.BooleanField() def __init__(self, *args, **kwargs): """ diff --git a/openedx/core/djangoapps/courseware_api/tests/test_views.py b/openedx/core/djangoapps/courseware_api/tests/test_views.py index a869040849..c9a5b31e18 100644 --- a/openedx/core/djangoapps/courseware_api/tests/test_views.py +++ b/openedx/core/djangoapps/courseware_api/tests/test_views.py @@ -24,7 +24,8 @@ from lms.djangoapps.courseware.tests.helpers import MasqueradeMixin from lms.djangoapps.courseware.toggles import ( COURSEWARE_MICROFRONTEND_PROGRESS_MILESTONES, COURSEWARE_MICROFRONTEND_PROGRESS_MILESTONES_STREAK_CELEBRATION, - REDIRECT_TO_COURSEWARE_MICROFRONTEND + REDIRECT_TO_COURSEWARE_MICROFRONTEND, + COURSEWARE_MICROFRONTEND_SPECIAL_EXAMS, ) from lms.djangoapps.verify_student.services import IDVerificationService from common.djangoapps.student.models import ( @@ -288,6 +289,23 @@ class CourseApiTestViews(BaseCoursewareTests, MasqueradeMixin): celebrations = response.json()['celebrations'] assert 'streak_length_to_celebrate' in celebrations + @ddt.data( + (False, False), + (False, True), + (True, False), + (True, True), + ) + @ddt.unpack + def test_special_exams_enabled_for_course(self, is_globaly_enabled, is_waffle_enabled): + """ Ensure that special exams flag present in courseware meta data with expected value """ + with mock.patch.dict('django.conf.settings.FEATURES', {'ENABLE_SPECIAL_EXAMS': is_globaly_enabled}): + with override_waffle_flag(COURSEWARE_MICROFRONTEND_SPECIAL_EXAMS, active=is_waffle_enabled): + response = self.client.get(self.url) + assert response.status_code == 200 + courseware_data = response.json() + assert 'is_mfe_special_exams_enabled' in courseware_data + assert courseware_data['is_mfe_special_exams_enabled'] == (is_globaly_enabled and is_waffle_enabled) + class SequenceApiTestViews(BaseCoursewareTests): """ diff --git a/openedx/core/djangoapps/courseware_api/views.py b/openedx/core/djangoapps/courseware_api/views.py index 7c10e7a138..70681c4414 100644 --- a/openedx/core/djangoapps/courseware_api/views.py +++ b/openedx/core/djangoapps/courseware_api/views.py @@ -6,6 +6,7 @@ import json from completion.exceptions import UnavailableCompletionData from completion.utilities import get_key_to_last_completed_block +from django.conf import settings from django.urls import reverse from django.utils.translation import ugettext as _ from edx_rest_framework_extensions.auth.jwt.authentication import JwtAuthentication @@ -36,7 +37,8 @@ from lms.djangoapps.courseware.tabs import get_course_tab_list from lms.djangoapps.courseware.toggles import ( courseware_legacy_is_visible, courseware_mfe_is_visible, - course_exit_page_is_active + course_exit_page_is_active, + mfe_special_exams_is_active, ) from lms.djangoapps.courseware.views.views import get_cert_data from lms.djangoapps.grades.api import CourseGradeFactory @@ -115,6 +117,10 @@ class CoursewareMeta: is_course_staff=self.original_user_is_staff ) + @property + def is_mfe_special_exams_enabled(self): + return settings.FEATURES.get('ENABLE_SPECIAL_EXAMS', False) and mfe_special_exams_is_active(self.course_key) + @property def enrollment(self): """