diff --git a/lms/djangoapps/learner_home/serializers.py b/lms/djangoapps/learner_home/serializers.py index f7eed25d22e9..68f812e7c8d4 100644 --- a/lms/djangoapps/learner_home/serializers.py +++ b/lms/djangoapps/learner_home/serializers.py @@ -13,6 +13,7 @@ from openedx_filters.learning.filters import CourseEnrollmentAPIRenderStarted, CourseRunAPIRenderStarted from common.djangoapps.course_modes.models import CourseMode +from openedx.core.djangoapps.catalog.utils import get_course_uuid_for_course from openedx.features.course_experience import course_home_url from xmodule.data import CertificatesDisplayBehaviors from lms.djangoapps.learner_home.utils import course_progress_url @@ -93,6 +94,7 @@ class CourseRunSerializer(serializers.Serializer): isStarted = serializers.SerializerMethodField() isArchived = serializers.SerializerMethodField() courseId = serializers.CharField(source="course_id") + courseUuid = serializers.SerializerMethodField() minPassingGrade = serializers.DecimalField( max_digits=5, decimal_places=2, source="course_overview.lowest_passing_grade" ) @@ -114,6 +116,10 @@ def get_isStarted(self, instance): def get_isArchived(self, instance): return instance.course_overview.has_ended() + def get_courseUuid(self, instance): + course_uuid = get_course_uuid_for_course(instance.course_id) + return str(course_uuid) if course_uuid else None + def get_homeUrl(self, instance): return course_home_url(instance.course_id) diff --git a/lms/djangoapps/learner_home/test_serializers.py b/lms/djangoapps/learner_home/test_serializers.py index 7b8268b42c76..fc27c9c6b579 100644 --- a/lms/djangoapps/learner_home/test_serializers.py +++ b/lms/djangoapps/learner_home/test_serializers.py @@ -203,7 +203,10 @@ def create_test_context(self, course_id): }, } - def test_with_data(self): + @mock.patch("lms.djangoapps.learner_home.serializers.get_course_uuid_for_course") + def test_with_data(self, mock_get_course_uuid_for_course): + # Mocked so courseUuid is populated, same as every other field + mock_get_course_uuid_for_course.return_value = uuid4() input_data = self.create_test_enrollment() input_context = self.create_test_context(input_data.course.id) @@ -227,6 +230,34 @@ def test_missing_resume_url(self): # Then the resumeUrl is None, which is allowed self.assertIsNone(output_data["resumeUrl"]) + @mock.patch("lms.djangoapps.learner_home.serializers.get_course_uuid_for_course") + def test_course_uuid(self, mock_get_course_uuid_for_course): + # Given the catalog has a UUID for this course + course_uuid = uuid4() + mock_get_course_uuid_for_course.return_value = course_uuid + input_data = self.create_test_enrollment() + input_context = self.create_test_context(input_data.course.id) + + # When I serialize + output_data = CourseRunSerializer(input_data, context=input_context).data + + # Then courseUuid is the stringified catalog UUID, looked up by course_id + self.assertEqual(output_data["courseUuid"], str(course_uuid)) + mock_get_course_uuid_for_course.assert_called_once_with(input_data.course_id) + + @mock.patch("lms.djangoapps.learner_home.serializers.get_course_uuid_for_course") + def test_missing_course_uuid(self, mock_get_course_uuid_for_course): + # Given the catalog has no UUID for this course (e.g. no catalog integration configured) + mock_get_course_uuid_for_course.return_value = None + input_data = self.create_test_enrollment() + input_context = self.create_test_context(input_data.course.id) + + # When I serialize + output_data = CourseRunSerializer(input_data, context=input_context).data + + # Then courseUuid is None, which is allowed + self.assertIsNone(output_data["courseUuid"]) + def is_progress_url_matching_course_home_mfe_progress_tab_is_active(self): """ Compares the progress URL generated by CourseRunSerializer to the expected progress URL.