feat: update recommendations api (#31259)
- updated status codes - for control group return general recommendations VAN-1154
This commit is contained in:
@@ -823,6 +823,21 @@ class TestCourseRecommendationApiView(SharedModuleStoreTestCase):
|
||||
password = "test"
|
||||
url = reverse_lazy("learner_home:courses")
|
||||
|
||||
GENERAL_RECOMMENDATIONS = [
|
||||
{
|
||||
"course_key": "HogwartsX+6.00.1x",
|
||||
"logo_image_url": random_url(),
|
||||
"marketing_url": random_url(),
|
||||
"title": "Defense Against the Dark Arts",
|
||||
},
|
||||
{
|
||||
"course_key": "MonstersX+SC101EN",
|
||||
"logo_image_url": random_url(),
|
||||
"marketing_url": random_url(),
|
||||
"title": "Scaring 101",
|
||||
},
|
||||
]
|
||||
|
||||
def setUp(self):
|
||||
super().setUp()
|
||||
self.user = UserFactory()
|
||||
@@ -849,10 +864,10 @@ class TestCourseRecommendationApiView(SharedModuleStoreTestCase):
|
||||
@override_waffle_flag(ENABLE_LEARNER_HOME_AMPLITUDE_RECOMMENDATIONS, active=False)
|
||||
def test_waffle_flag_off(self):
|
||||
"""
|
||||
Verify API returns 400 if waffle flag is off.
|
||||
Verify API returns 404 if waffle flag is off.
|
||||
"""
|
||||
response = self.client.get(self.url)
|
||||
self.assertEqual(response.status_code, 400)
|
||||
self.assertEqual(response.status_code, 404)
|
||||
self.assertEqual(response.data, None)
|
||||
|
||||
@override_waffle_flag(ENABLE_LEARNER_HOME_AMPLITUDE_RECOMMENDATIONS, active=True)
|
||||
@@ -864,13 +879,25 @@ class TestCourseRecommendationApiView(SharedModuleStoreTestCase):
|
||||
self, mocked_get_course_data, mocked_get_personalized_course_recommendations
|
||||
):
|
||||
"""
|
||||
Verify API returns 400 if no course recommendations from amplitude.
|
||||
Verify API returns 404 if no course recommendations from amplitude.
|
||||
"""
|
||||
mocked_get_personalized_course_recommendations.return_value = [False, []]
|
||||
mocked_get_course_data.return_value = self.course_data
|
||||
|
||||
response = self.client.get(self.url)
|
||||
self.assertEqual(response.status_code, 400)
|
||||
self.assertEqual(response.status_code, 404)
|
||||
self.assertEqual(response.data, None)
|
||||
|
||||
@override_waffle_flag(ENABLE_LEARNER_HOME_AMPLITUDE_RECOMMENDATIONS, active=True)
|
||||
@mock.patch(
|
||||
"lms.djangoapps.learner_home.views.get_personalized_course_recommendations", Mock(side_effect=Exception)
|
||||
)
|
||||
def test_amplitude_api_unexpected_error(self):
|
||||
"""
|
||||
Test that if the Amplitude API gives an unexpected error, 500 is returned.
|
||||
"""
|
||||
response = self.client.get(self.url)
|
||||
self.assertEqual(response.status_code, 500)
|
||||
self.assertEqual(response.data, None)
|
||||
|
||||
@override_waffle_flag(ENABLE_LEARNER_HOME_AMPLITUDE_RECOMMENDATIONS, active=True)
|
||||
@@ -898,6 +925,25 @@ class TestCourseRecommendationApiView(SharedModuleStoreTestCase):
|
||||
len(response.data.get("courses")), expected_recommendations_length
|
||||
)
|
||||
|
||||
@override_waffle_flag(ENABLE_LEARNER_HOME_AMPLITUDE_RECOMMENDATIONS, active=True)
|
||||
@mock.patch("django.conf.settings.GENERAL_RECOMMENDATIONS", GENERAL_RECOMMENDATIONS)
|
||||
@mock.patch(
|
||||
"lms.djangoapps.learner_home.views.get_personalized_course_recommendations"
|
||||
)
|
||||
def test_general_recommendations(self, mocked_get_personalized_course_recommendations):
|
||||
"""
|
||||
Test that a user gets general recommendations for the control group.
|
||||
"""
|
||||
mocked_get_personalized_course_recommendations.return_value = [
|
||||
True,
|
||||
self.recommended_courses,
|
||||
]
|
||||
|
||||
response = self.client.get(self.url)
|
||||
self.assertEqual(response.status_code, 200)
|
||||
self.assertEqual(response.data.get("is_personalized_recommendation"), False)
|
||||
self.assertEqual(response.data.get("courses"), self.GENERAL_RECOMMENDATIONS)
|
||||
|
||||
@override_waffle_flag(ENABLE_LEARNER_HOME_AMPLITUDE_RECOMMENDATIONS, active=True)
|
||||
@mock.patch(
|
||||
"lms.djangoapps.learner_home.views.get_personalized_course_recommendations"
|
||||
|
||||
@@ -93,16 +93,13 @@ def get_personalized_course_recommendations(user_id):
|
||||
"get_recs": True,
|
||||
"rec_id": settings.REC_ID,
|
||||
}
|
||||
try:
|
||||
response = requests.get(settings.AMPLITUDE_URL, params=params, headers=headers)
|
||||
if response.status_code == 200:
|
||||
response = response.json()
|
||||
recommendations = response.get("userData", {}).get("recommendations", [])
|
||||
if recommendations:
|
||||
is_control = recommendations[0].get("is_control")
|
||||
recommended_course_keys = recommendations[0].get("items")
|
||||
return is_control, recommended_course_keys
|
||||
except Exception as ex: # pylint: disable=broad-except
|
||||
log.warning(f"Cannot get recommendations from Amplitude: {ex}")
|
||||
response = requests.get(settings.AMPLITUDE_URL, params=params, headers=headers)
|
||||
if response.status_code == 200:
|
||||
response = response.json()
|
||||
recommendations = response.get("userData", {}).get("recommendations", [])
|
||||
if recommendations:
|
||||
is_control = recommendations[0].get("is_control")
|
||||
recommended_course_keys = recommendations[0].get("items")
|
||||
return is_control, recommended_course_keys
|
||||
|
||||
return True, []
|
||||
|
||||
@@ -543,6 +543,8 @@ class InitializeView(RetrieveAPIView): # pylint: disable=unused-argument
|
||||
|
||||
class CourseRecommendationApiView(APIView):
|
||||
"""
|
||||
API to get personalized recommendations from Amplitude.
|
||||
|
||||
**Example Request**
|
||||
|
||||
GET /api/learner_home/recommendation/courses/
|
||||
@@ -555,12 +557,18 @@ class CourseRecommendationApiView(APIView):
|
||||
permission_classes = (IsAuthenticated,)
|
||||
|
||||
def get(self, request):
|
||||
"""Retrieves course recommendations details of a user in a specified course."""
|
||||
"""
|
||||
Retrieves course recommendations details.
|
||||
"""
|
||||
if not should_show_learner_home_amplitude_recommendations():
|
||||
return Response(status=400)
|
||||
return Response(status=404)
|
||||
|
||||
user_id = request.user.id
|
||||
is_control, course_keys = get_personalized_course_recommendations(user_id)
|
||||
try:
|
||||
user_id = request.user.id
|
||||
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 Response(status=500)
|
||||
|
||||
# Emits an event to track student dashboard page visits.
|
||||
segment.track(
|
||||
@@ -571,8 +579,17 @@ class CourseRecommendationApiView(APIView):
|
||||
},
|
||||
)
|
||||
|
||||
if is_control or not course_keys:
|
||||
return Response(status=400)
|
||||
if is_control:
|
||||
return Response(
|
||||
{
|
||||
"courses": settings.GENERAL_RECOMMENDATIONS,
|
||||
"is_personalized_recommendation": False,
|
||||
},
|
||||
status=200,
|
||||
)
|
||||
|
||||
if not course_keys:
|
||||
return Response(status=404)
|
||||
|
||||
recommended_courses = []
|
||||
user_enrolled_course_keys = set()
|
||||
|
||||
@@ -4753,8 +4753,11 @@ EDX_BRAZE_API_SERVER = None
|
||||
AMPLITUDE_URL = ''
|
||||
AMPLITUDE_API_KEY = ''
|
||||
REC_ID = ''
|
||||
# Keeping this for back compatibility with learner dashboard api
|
||||
GENERAL_RECOMMENDATION = {}
|
||||
|
||||
GENERAL_RECOMMENDATIONS = []
|
||||
|
||||
############### Settings for Retirement #####################
|
||||
# .. setting_name: RETIRED_USERNAME_PREFIX
|
||||
# .. setting_default: retired__user_
|
||||
|
||||
Reference in New Issue
Block a user