fix: enrollment should still display if IDV is disabled (#29819)
MST-1317. The enrollment mode of a learner should still display on the course listing, even if IDV is disabled. Right now, all enrollment messaging is disabled if IDV is turned off, as we are no longer returning the verifications status for a learner in that case. We should still return the enrollment mode if IDV is disabled, but exclude any IDV messaging.
This commit is contained in:
@@ -11,6 +11,7 @@ from slumber.exceptions import SlumberBaseException
|
||||
|
||||
from common.djangoapps.course_modes.models import CourseMode
|
||||
from common.djangoapps.student.helpers import VERIFY_STATUS_APPROVED, VERIFY_STATUS_NEED_TO_VERIFY, VERIFY_STATUS_SUBMITTED # lint-amnesty, pylint: disable=line-too-long
|
||||
from openedx.core.djangoapps.agreements.toggles import is_integrity_signature_enabled
|
||||
from openedx.core.djangoapps.commerce.utils import ecommerce_api_client
|
||||
|
||||
DISPLAY_VERIFIED = "verified"
|
||||
@@ -41,16 +42,16 @@ def enrollment_mode_display(mode, verification_status, course_id):
|
||||
display_mode = _enrollment_mode_display(mode, verification_status, course_id)
|
||||
|
||||
if display_mode == DISPLAY_VERIFIED:
|
||||
if verification_status in [VERIFY_STATUS_NEED_TO_VERIFY, VERIFY_STATUS_SUBMITTED]:
|
||||
enrollment_title = _("Your verification is pending")
|
||||
enrollment_value = _("Verified: Pending Verification")
|
||||
show_image = True
|
||||
image_alt = _("ID verification pending")
|
||||
elif verification_status == VERIFY_STATUS_APPROVED:
|
||||
if is_integrity_signature_enabled(course_id) or verification_status == VERIFY_STATUS_APPROVED:
|
||||
enrollment_title = _("You're enrolled as a verified student")
|
||||
enrollment_value = _("Verified")
|
||||
show_image = True
|
||||
image_alt = _("ID Verified Ribbon/Badge")
|
||||
elif verification_status in [VERIFY_STATUS_NEED_TO_VERIFY, VERIFY_STATUS_SUBMITTED]:
|
||||
enrollment_title = _("Your verification is pending")
|
||||
enrollment_value = _("Verified: Pending Verification")
|
||||
show_image = True
|
||||
image_alt = _("ID verification pending")
|
||||
elif display_mode == DISPLAY_HONOR:
|
||||
enrollment_title = _("You're enrolled as an honor code student")
|
||||
enrollment_value = _("Honor Code")
|
||||
@@ -63,7 +64,7 @@ def enrollment_mode_display(mode, verification_status, course_id):
|
||||
'enrollment_value': str(enrollment_value),
|
||||
'show_image': show_image,
|
||||
'image_alt': str(image_alt),
|
||||
'display_mode': _enrollment_mode_display(mode, verification_status, course_id)
|
||||
'display_mode': display_mode
|
||||
}
|
||||
|
||||
|
||||
@@ -79,7 +80,10 @@ def _enrollment_mode_display(enrollment_mode, verification_status, course_id):
|
||||
course_mode_slugs = [mode.slug for mode in CourseMode.modes_for_course(course_id)]
|
||||
|
||||
if enrollment_mode == CourseMode.VERIFIED:
|
||||
if verification_status in [VERIFY_STATUS_NEED_TO_VERIFY, VERIFY_STATUS_SUBMITTED, VERIFY_STATUS_APPROVED]:
|
||||
if (
|
||||
is_integrity_signature_enabled(course_id)
|
||||
or verification_status in [VERIFY_STATUS_NEED_TO_VERIFY, VERIFY_STATUS_SUBMITTED, VERIFY_STATUS_APPROVED]
|
||||
):
|
||||
display_mode = DISPLAY_VERIFIED
|
||||
elif DISPLAY_HONOR in course_mode_slugs:
|
||||
display_mode = DISPLAY_HONOR
|
||||
|
||||
@@ -14,6 +14,7 @@ import ddt
|
||||
from django.core.exceptions import ValidationError
|
||||
from django.test import TestCase, override_settings
|
||||
from django.utils.timezone import now
|
||||
from edx_toggles.toggles.testutils import override_waffle_flag
|
||||
from opaque_keys.edx.locator import CourseLocator
|
||||
|
||||
from common.djangoapps.course_modes.helpers import enrollment_mode_display
|
||||
@@ -24,6 +25,7 @@ from common.djangoapps.course_modes.models import (
|
||||
invalidate_course_mode_cache
|
||||
)
|
||||
from common.djangoapps.course_modes.tests.factories import CourseModeFactory
|
||||
from openedx.core.djangoapps.agreements.toggles import ENABLE_INTEGRITY_SIGNATURE
|
||||
from openedx.core.djangoapps.content.course_overviews.models import CourseOverview
|
||||
from xmodule.modulestore.tests.django_utils import ModuleStoreTestCase # lint-amnesty, pylint: disable=wrong-import-order
|
||||
from xmodule.modulestore.tests.factories import CourseFactory # lint-amnesty, pylint: disable=wrong-import-order
|
||||
@@ -341,36 +343,49 @@ class CourseModeModelTest(TestCase):
|
||||
assert exc.messages == ['Professional education modes are not allowed to have expiration_datetime set.']
|
||||
|
||||
@ddt.data(
|
||||
("verified", "verify_need_to_verify"),
|
||||
("verified", "verify_submitted"),
|
||||
("verified", "verify_approved"),
|
||||
("verified", 'dummy'),
|
||||
("verified", None),
|
||||
('honor', None),
|
||||
('honor', 'dummy'),
|
||||
('audit', None),
|
||||
('professional', None),
|
||||
('no-id-professional', None),
|
||||
('no-id-professional', 'dummy')
|
||||
("verified", "verify_need_to_verify", True),
|
||||
("verified", "verify_submitted", True),
|
||||
("verified", "verify_approved", True),
|
||||
("verified", 'dummy', True),
|
||||
("verified", None, True),
|
||||
('honor', None, True),
|
||||
('honor', 'dummy', True),
|
||||
('audit', None, True),
|
||||
('professional', None, True),
|
||||
('no-id-professional', None, True),
|
||||
('no-id-professional', 'dummy', True),
|
||||
("verified", "verify_need_to_verify", False),
|
||||
("verified", "verify_submitted", False),
|
||||
("verified", "verify_approved", False),
|
||||
("verified", 'dummy', False),
|
||||
("verified", None, False),
|
||||
('honor', None, False),
|
||||
('honor', 'dummy', False),
|
||||
('audit', None, False),
|
||||
('professional', None, False),
|
||||
('no-id-professional', None, False),
|
||||
('no-id-professional', 'dummy', False)
|
||||
)
|
||||
@ddt.unpack
|
||||
def test_enrollment_mode_display(self, mode, verification_status):
|
||||
if mode == "verified":
|
||||
assert enrollment_mode_display(mode, verification_status, self.course_key) ==\
|
||||
self._enrollment_display_modes_dicts(verification_status)
|
||||
assert enrollment_mode_display(mode, verification_status, self.course_key) ==\
|
||||
self._enrollment_display_modes_dicts(verification_status)
|
||||
assert enrollment_mode_display(mode, verification_status, self.course_key) ==\
|
||||
self._enrollment_display_modes_dicts(verification_status)
|
||||
elif mode == "honor":
|
||||
assert enrollment_mode_display(mode, verification_status, self.course_key) ==\
|
||||
self._enrollment_display_modes_dicts(mode)
|
||||
elif mode == "audit":
|
||||
assert enrollment_mode_display(mode, verification_status, self.course_key) ==\
|
||||
self._enrollment_display_modes_dicts(mode)
|
||||
elif mode == "professional":
|
||||
assert enrollment_mode_display(mode, verification_status, self.course_key) ==\
|
||||
self._enrollment_display_modes_dicts(mode)
|
||||
def test_enrollment_mode_display(self, mode, verification_status, enable_flag):
|
||||
|
||||
with override_waffle_flag(ENABLE_INTEGRITY_SIGNATURE, active=enable_flag):
|
||||
if mode == "verified":
|
||||
assert enrollment_mode_display(mode, verification_status, self.course_key) ==\
|
||||
self._enrollment_display_modes_dicts(mode, verification_status, enable_flag)
|
||||
assert enrollment_mode_display(mode, verification_status, self.course_key) ==\
|
||||
self._enrollment_display_modes_dicts(mode, verification_status, enable_flag)
|
||||
assert enrollment_mode_display(mode, verification_status, self.course_key) ==\
|
||||
self._enrollment_display_modes_dicts(mode, verification_status, enable_flag)
|
||||
elif mode == "honor":
|
||||
assert enrollment_mode_display(mode, verification_status, self.course_key) ==\
|
||||
self._enrollment_display_modes_dicts(mode, mode, enable_flag)
|
||||
elif mode == "audit":
|
||||
assert enrollment_mode_display(mode, verification_status, self.course_key) ==\
|
||||
self._enrollment_display_modes_dicts(mode, mode, enable_flag)
|
||||
elif mode == "professional":
|
||||
assert enrollment_mode_display(mode, verification_status, self.course_key) ==\
|
||||
self._enrollment_display_modes_dicts(mode, mode, enable_flag)
|
||||
|
||||
@ddt.data(
|
||||
(['honor', 'verified', 'credit'], ['honor', 'verified']),
|
||||
@@ -394,7 +409,7 @@ class CourseModeModelTest(TestCase):
|
||||
all_modes = CourseMode.modes_for_course_dict(self.course_key, only_selectable=False)
|
||||
self.assertCountEqual(list(all_modes.keys()), available_modes)
|
||||
|
||||
def _enrollment_display_modes_dicts(self, dict_type):
|
||||
def _enrollment_display_modes_dicts(self, mode, dict_type, enable_flag):
|
||||
"""
|
||||
Helper function to generate the enrollment display mode dict.
|
||||
"""
|
||||
@@ -410,7 +425,9 @@ class CourseModeModelTest(TestCase):
|
||||
"professional": ["You're enrolled as a professional education student", "Professional Ed", False, '',
|
||||
'professional']
|
||||
}
|
||||
if dict_type in ['verify_need_to_verify', 'verify_submitted']:
|
||||
if mode == 'verified' and enable_flag:
|
||||
return dict(list(zip(dict_keys, display_values.get('verify_approved'))))
|
||||
elif dict_type in ['verify_need_to_verify', 'verify_submitted']:
|
||||
return dict(list(zip(dict_keys, display_values.get('verify_need_to_verify'))))
|
||||
elif dict_type is None or dict_type == 'dummy':
|
||||
return dict(list(zip(dict_keys, display_values.get('verify_none'))))
|
||||
|
||||
@@ -332,19 +332,19 @@ class TestCourseVerificationStatus(UrlResetMixin, ModuleStoreTestCase):
|
||||
else:
|
||||
self._setup_mode_and_enrollment(None, "verified")
|
||||
|
||||
self._assert_course_verification_status(None)
|
||||
self._assert_course_verification_status(None, "verified")
|
||||
|
||||
attempt = SoftwareSecurePhotoVerification.objects.create(user=self.user)
|
||||
self._assert_course_verification_status(None)
|
||||
self._assert_course_verification_status(None, "verified")
|
||||
attempt.mark_ready()
|
||||
self._assert_course_verification_status(None)
|
||||
self._assert_course_verification_status(None, "verified")
|
||||
attempt.submit()
|
||||
self._assert_course_verification_status(None)
|
||||
self._assert_course_verification_status(None, "verified")
|
||||
attempt.approve()
|
||||
self._assert_course_verification_status(None)
|
||||
self._assert_course_verification_status(None, "verified")
|
||||
attempt.expiration_date = self.DATES[self.PAST] - timedelta(days=900)
|
||||
attempt.save()
|
||||
self._assert_course_verification_status(None)
|
||||
self._assert_course_verification_status(None, "verified")
|
||||
|
||||
@ddt.data(True, False)
|
||||
def test_integrity_disables_sidebar(self, integrity_flag):
|
||||
@@ -416,7 +416,7 @@ class TestCourseVerificationStatus(UrlResetMixin, ModuleStoreTestCase):
|
||||
VERIFY_STATUS_RESUBMITTED: "audit"
|
||||
}
|
||||
|
||||
def _assert_course_verification_status(self, status):
|
||||
def _assert_course_verification_status(self, status, enrollment_mode=None):
|
||||
"""Check whether the specified verification status is shown on the dashboard.
|
||||
|
||||
Arguments:
|
||||
@@ -437,10 +437,12 @@ class TestCourseVerificationStatus(UrlResetMixin, ModuleStoreTestCase):
|
||||
if alt_text:
|
||||
self.assertContains(response, alt_text)
|
||||
|
||||
mode = enrollment_mode if enrollment_mode else self.MODE_CLASSES[status]
|
||||
|
||||
# Verify that the correct banner color is rendered
|
||||
self.assertContains(
|
||||
response,
|
||||
f"<article class=\"course {self.MODE_CLASSES[status]}\""
|
||||
f"<article class=\"course {mode}\""
|
||||
)
|
||||
|
||||
# Verify that the correct copy is rendered on the dashboard
|
||||
|
||||
Reference in New Issue
Block a user