fix: VAN-1223 - Add is_control property to recommendations viewed event
This commit is contained in:
@@ -6,6 +6,7 @@ import json
|
||||
from unittest import mock
|
||||
from unittest.mock import Mock
|
||||
|
||||
import ddt
|
||||
from django.urls import reverse_lazy
|
||||
from edx_toggles.toggles.testutils import override_waffle_flag
|
||||
|
||||
@@ -24,6 +25,7 @@ from xmodule.modulestore.tests.django_utils import (
|
||||
)
|
||||
|
||||
|
||||
@ddt.ddt
|
||||
class TestCourseRecommendationApiView(SharedModuleStoreTestCase):
|
||||
"""Unit tests for the course recommendations on learner home page."""
|
||||
|
||||
@@ -115,7 +117,7 @@ class TestCourseRecommendationApiView(SharedModuleStoreTestCase):
|
||||
"""
|
||||
Verify API returns general recommendations if no course recommendations from amplitude.
|
||||
"""
|
||||
mocked_get_personalized_course_recommendations.return_value = [False, []]
|
||||
mocked_get_personalized_course_recommendations.return_value = [False, True, []]
|
||||
|
||||
response = self.client.get(self.url)
|
||||
self.assertEqual(response.status_code, 200)
|
||||
@@ -161,6 +163,7 @@ class TestCourseRecommendationApiView(SharedModuleStoreTestCase):
|
||||
"""
|
||||
mocked_get_personalized_course_recommendations.return_value = [
|
||||
False,
|
||||
True,
|
||||
self.recommended_courses,
|
||||
]
|
||||
mocked_get_course_data.return_value = self.course_data
|
||||
@@ -187,6 +190,7 @@ class TestCourseRecommendationApiView(SharedModuleStoreTestCase):
|
||||
Test that a user gets general recommendations for the control group.
|
||||
"""
|
||||
mocked_get_personalized_course_recommendations.return_value = [
|
||||
True,
|
||||
True,
|
||||
self.recommended_courses,
|
||||
]
|
||||
@@ -214,6 +218,7 @@ class TestCourseRecommendationApiView(SharedModuleStoreTestCase):
|
||||
"""
|
||||
mocked_get_personalized_course_recommendations.return_value = [
|
||||
False,
|
||||
True,
|
||||
self.recommended_courses,
|
||||
]
|
||||
mocked_get_course_data.return_value = self.course_data
|
||||
@@ -244,6 +249,7 @@ class TestCourseRecommendationApiView(SharedModuleStoreTestCase):
|
||||
"""
|
||||
mocked_get_personalized_course_recommendations.return_value = [
|
||||
False,
|
||||
True,
|
||||
self.recommended_courses,
|
||||
]
|
||||
mocked_get_course_data.return_value = self.course_data
|
||||
@@ -261,3 +267,40 @@ class TestCourseRecommendationApiView(SharedModuleStoreTestCase):
|
||||
response_content.get("courses"),
|
||||
self.SERIALIZED_GENERAL_RECOMMENDATIONS,
|
||||
)
|
||||
|
||||
@ddt.data(
|
||||
(True, False, None),
|
||||
(False, True, False),
|
||||
(False, False, None),
|
||||
(True, True, True),
|
||||
)
|
||||
@mock.patch("lms.djangoapps.learner_home.recommendations.views.segment.track")
|
||||
@mock.patch("lms.djangoapps.learner_home.recommendations.views.get_course_data")
|
||||
@mock.patch(
|
||||
"lms.djangoapps.learner_home.recommendations.views.get_personalized_course_recommendations"
|
||||
)
|
||||
@override_waffle_flag(ENABLE_LEARNER_HOME_AMPLITUDE_RECOMMENDATIONS, active=True)
|
||||
@ddt.unpack
|
||||
def test_recommendations_viewed_segment_event(
|
||||
self,
|
||||
is_control,
|
||||
has_is_control,
|
||||
expected_is_control,
|
||||
mocked_get_personalized_course_recommendations,
|
||||
mocked_get_course_data,
|
||||
segment_track_mock
|
||||
):
|
||||
"""
|
||||
Test that Segment event is emitted with desired properties.
|
||||
"""
|
||||
mocked_get_personalized_course_recommendations.return_value = [
|
||||
is_control,
|
||||
has_is_control,
|
||||
self.recommended_courses,
|
||||
]
|
||||
mocked_get_course_data.return_value = self.course_data
|
||||
self.client.get(self.url)
|
||||
|
||||
assert segment_track_mock.call_count == 1
|
||||
assert segment_track_mock.call_args[0][1] == "edx.bi.user.recommendations.viewed"
|
||||
self.assertEqual(segment_track_mock.call_args[0][2]["is_control"], expected_is_control)
|
||||
|
||||
@@ -25,7 +25,8 @@ def get_personalized_course_recommendations(user_id):
|
||||
recommendations = response.get("userData", {}).get("recommendations", [])
|
||||
if recommendations:
|
||||
is_control = recommendations[0].get("is_control")
|
||||
has_is_control = recommendations[0].get("has_is_control")
|
||||
recommended_course_keys = recommendations[0].get("items")
|
||||
return is_control, recommended_course_keys
|
||||
return is_control, has_is_control, recommended_course_keys
|
||||
|
||||
return True, []
|
||||
return True, False, []
|
||||
|
||||
@@ -52,6 +52,7 @@ class CourseRecommendationApiView(APIView):
|
||||
if not should_show_learner_home_amplitude_recommendations():
|
||||
return Response(status=404)
|
||||
|
||||
recommended_courses = []
|
||||
general_recommendations_response = Response(
|
||||
CourseRecommendationSerializer(
|
||||
{
|
||||
@@ -64,24 +65,17 @@ class CourseRecommendationApiView(APIView):
|
||||
|
||||
try:
|
||||
user_id = request.user.id
|
||||
is_control, course_keys = get_personalized_course_recommendations(user_id)
|
||||
is_control, has_is_control, course_keys = get_personalized_course_recommendations(user_id)
|
||||
except Exception as ex: # pylint: disable=broad-except
|
||||
logger.warning(f"Cannot get recommendations from Amplitude: {ex}")
|
||||
return general_recommendations_response
|
||||
|
||||
# Emits an event to track student dashboard page visits.
|
||||
segment.track(
|
||||
user_id,
|
||||
"edx.bi.user.recommendations.viewed",
|
||||
{
|
||||
"is_personalized_recommendation": not is_control,
|
||||
},
|
||||
)
|
||||
|
||||
if is_control or not course_keys:
|
||||
self._emit_recommendations_viewed_event(
|
||||
user_id, is_control, has_is_control, recommended_courses
|
||||
)
|
||||
return general_recommendations_response
|
||||
|
||||
recommended_courses = []
|
||||
user_enrolled_course_keys = set()
|
||||
fields = ["title", "owners", "marketing_url"]
|
||||
|
||||
@@ -105,6 +99,9 @@ class CourseRecommendationApiView(APIView):
|
||||
"marketing_url": course_data.get("marketing_url"),
|
||||
}
|
||||
)
|
||||
self._emit_recommendations_viewed_event(
|
||||
user_id, is_control, has_is_control, recommended_courses
|
||||
)
|
||||
|
||||
# If no courses are left after filtering already enrolled courses from
|
||||
# the list of amplitude recommendations, show general recommendations
|
||||
@@ -121,3 +118,15 @@ class CourseRecommendationApiView(APIView):
|
||||
).data,
|
||||
status=200,
|
||||
)
|
||||
|
||||
def _emit_recommendations_viewed_event(self, user_id, is_control, has_is_control, recommended_courses):
|
||||
"""Emits an event to track Learner Home page visits."""
|
||||
segment.track(
|
||||
user_id,
|
||||
"edx.bi.user.recommendations.viewed",
|
||||
{
|
||||
"is_personalized_recommendation": not is_control,
|
||||
"is_control": is_control if has_is_control else None,
|
||||
"course_key_array": [course["course_key"] for course in recommended_courses],
|
||||
},
|
||||
)
|
||||
|
||||
Reference in New Issue
Block a user