From 8162d2156618732bb2a29ddffa0195af4feac531 Mon Sep 17 00:00:00 2001 From: Jansen Kantor Date: Fri, 16 Sep 2022 10:30:18 -0400 Subject: [PATCH] feat: add related program info to unfulfilled entitlements (#31011) --- lms/djangoapps/learner_home/serializers.py | 11 +++- .../learner_home/test_serializers.py | 60 ++++++++++++++----- lms/djangoapps/learner_home/views.py | 2 +- 3 files changed, 53 insertions(+), 20 deletions(-) diff --git a/lms/djangoapps/learner_home/serializers.py b/lms/djangoapps/learner_home/serializers.py index baa215ff25..a9a9b7005e 100644 --- a/lms/djangoapps/learner_home/serializers.py +++ b/lms/djangoapps/learner_home/serializers.py @@ -467,9 +467,7 @@ class UnfulfilledEntitlementSerializer(serializers.Serializer): entitlement = EntitlementSerializer(source="*") course = serializers.SerializerMethodField() courseProvider = serializers.SerializerMethodField() - - # Change after data is implemented. This data is required - programs = ProgramsSerializer(allow_null=True) + programs = serializers.SerializerMethodField() # These fields are literal values that do not change courseRun = LiteralField(None) @@ -500,6 +498,13 @@ class UnfulfilledEntitlementSerializer(serializers.Serializer): return CourseProviderSerializer(course_overview, allow_null=True).data + def get_programs(self, instance): + """ + If this entitlement is part of a program, include information about the program and related programs + """ + programs = self.context['programs'].get(str(instance.course_uuid), []) + return ProgramsSerializer({"relatedPrograms": programs}, context=self.context).data + class SuggestedCourseSerializer(serializers.Serializer): """Serializer for a suggested course""" diff --git a/lms/djangoapps/learner_home/test_serializers.py b/lms/djangoapps/learner_home/test_serializers.py index 445e6047a6..c3ee939d06 100644 --- a/lms/djangoapps/learner_home/test_serializers.py +++ b/lms/djangoapps/learner_home/test_serializers.py @@ -773,19 +773,8 @@ class TestLearnerEnrollmentsSerializer(LearnerDashboardBaseTest): class TestUnfulfilledEntitlementSerializer(LearnerDashboardBaseTest): """High-level tests for UnfulfilledEntitlementSerializer""" - @classmethod - def generate_test_entitlement_data(cls): - mock_enrollment = cls.create_test_enrollment(cls) - - return { - "courseProvider": TestCourseProviderSerializer.generate_test_provider_info(), - "course": mock_enrollment.course, - "entitlement": TestEntitlementSerializer.generate_test_entitlement_info(), - "programs": TestProgramsSerializer.generate_test_programs_info(), - } - - def test_happy_path(self): - """Test that nothing breaks and the output fields look correct""" + def make_unfulfilled_entitlement(self): + """ Create an unfulflled entitlement, along with a pseudo session and available sessions""" unfulfilled_entitlement = CourseEntitlementFactory.create() pseudo_sessions = { str(unfulfilled_entitlement.uuid): CatalogCourseRunFactory.create() @@ -793,18 +782,27 @@ class TestUnfulfilledEntitlementSerializer(LearnerDashboardBaseTest): available_sessions = { str(unfulfilled_entitlement.uuid): CatalogCourseRunFactory.create_batch(3) } + return unfulfilled_entitlement, pseudo_sessions, available_sessions - # create course overview for course provider info + def make_pseudo_session_course_overviews(self, unfulfilled_entitlement, pseudo_sessions): + """ Create course overview for course provider info """ course_key_str = pseudo_sessions[str(unfulfilled_entitlement.uuid)]["key"] course_key = CourseKey.from_string(course_key_str) course_overview = CourseOverviewFactory.create(id=course_key) + return {course_key: course_overview} - pseudo_session_course_overviews = {course_key: course_overview} - + def test_happy_path(self): + """Test that nothing breaks and the output fields look correct""" + unfulfilled_entitlement, pseudo_sessions, available_sessions = self.make_unfulfilled_entitlement() + pseudo_session_course_overviews = self.make_pseudo_session_course_overviews( + unfulfilled_entitlement, + pseudo_sessions + ) context = { "unfulfilled_entitlement_pseudo_sessions": pseudo_sessions, "course_entitlement_available_sessions": available_sessions, "pseudo_session_course_overviews": pseudo_session_course_overviews, + "programs": {} } output_data = UnfulfilledEntitlementSerializer( @@ -831,6 +829,35 @@ class TestUnfulfilledEntitlementSerializer(LearnerDashboardBaseTest): output_data["enrollment"] == UnfulfilledEntitlementSerializer.STATIC_ENTITLEMENT_ENROLLMENT_DATA ) + assert output_data["course"] is not None + assert output_data["courseProvider"] is not None + assert output_data["programs"] == {"relatedPrograms": []} + + def test_programs(self): + unfulfilled_entitlement, pseudo_sessions, available_sessions = self.make_unfulfilled_entitlement() + pseudo_session_course_overviews = self.make_pseudo_session_course_overviews( + unfulfilled_entitlement, + pseudo_sessions + ) + related_programs = ProgramFactory.create_batch(3) + programs = { + str(unfulfilled_entitlement.course_uuid): related_programs + } + + context = { + "unfulfilled_entitlement_pseudo_sessions": pseudo_sessions, + "course_entitlement_available_sessions": available_sessions, + "pseudo_session_course_overviews": pseudo_session_course_overviews, + "programs": programs + } + + output_data = UnfulfilledEntitlementSerializer( + unfulfilled_entitlement, context=context + ).data + + assert output_data["programs"] == ProgramsSerializer( + {"relatedPrograms": related_programs} + ).data def test_static_enrollment_data(self): """ @@ -1028,6 +1055,7 @@ class TestLearnerDashboardSerializer(LearnerDashboardBaseTest): course_overview = CourseOverviewFactory.create(id=course_key) pseudo_session_course_overviews[course_key] = course_overview + programs = { str(enrollment.course.id): ProgramFactory.create_batch(3) for enrollment in enrollments diff --git a/lms/djangoapps/learner_home/views.py b/lms/djangoapps/learner_home/views.py index e7d9313e80..f38ff94aa9 100644 --- a/lms/djangoapps/learner_home/views.py +++ b/lms/djangoapps/learner_home/views.py @@ -246,7 +246,7 @@ def get_course_programs(user, course_enrollments, site): } } """ - meter = ProgramProgressMeter(site, user, enrollments=course_enrollments) + meter = ProgramProgressMeter(site, user, enrollments=course_enrollments, include_course_entitlements=True) return meter.invert_programs()