feat: added endpoint for context needed for recommendations experiment (#32645)
* feat: added endpoint for context needed for recommendations experiment * chore: Removed unnecessary decorator
This commit is contained in:
@@ -86,6 +86,12 @@ class AboutPageRecommendationsSerializer(serializers.Serializer):
|
||||
)
|
||||
|
||||
|
||||
class RecommendationsContextSerializer(serializers.Serializer):
|
||||
"""Serializer for recommendations context"""
|
||||
|
||||
countryCode = serializers.CharField(allow_blank=True)
|
||||
|
||||
|
||||
class CrossProductRecommendationsSerializer(serializers.Serializer):
|
||||
"""
|
||||
Cross product recommendation courses for course about page
|
||||
|
||||
@@ -6,6 +6,7 @@ from django.test import TestCase
|
||||
|
||||
from lms.djangoapps.learner_recommendations.serializers import (
|
||||
DashboardRecommendationsSerializer,
|
||||
RecommendationsContextSerializer,
|
||||
CrossProductRecommendationsSerializer,
|
||||
CrossProductAndAmplitudeRecommendationsSerializer,
|
||||
AmplitudeRecommendationsSerializer
|
||||
@@ -91,6 +92,42 @@ class TestDashboardRecommendationsSerializer(TestCase):
|
||||
)
|
||||
|
||||
|
||||
class TestRecommendationsContextSerializer(TestCase):
|
||||
"""Tests for RecommendationsContextSerializer"""
|
||||
|
||||
def test_successful_serialization(self):
|
||||
"""Test that context data serializes correctly"""
|
||||
|
||||
serialized_data = RecommendationsContextSerializer(
|
||||
{
|
||||
"countryCode": "US",
|
||||
}
|
||||
).data
|
||||
|
||||
self.assertDictEqual(
|
||||
serialized_data,
|
||||
{
|
||||
"countryCode": "US",
|
||||
},
|
||||
)
|
||||
|
||||
def test_empty_response_serialization(self):
|
||||
"""Test that an empty response serializes correctly"""
|
||||
|
||||
serialized_data = RecommendationsContextSerializer(
|
||||
{
|
||||
"countryCode": "",
|
||||
}
|
||||
).data
|
||||
|
||||
self.assertDictEqual(
|
||||
serialized_data,
|
||||
{
|
||||
"countryCode": "",
|
||||
},
|
||||
)
|
||||
|
||||
|
||||
class TestCrossProductRecommendationsSerializers(TestCase):
|
||||
"""
|
||||
Tests for the CrossProductRecommendationsSerializer,
|
||||
|
||||
@@ -157,6 +157,36 @@ class TestAboutPageRecommendationsView(TestRecommendationsBase):
|
||||
assert segment_mock.call_args[0][1] == "edx.bi.user.recommendations.viewed"
|
||||
|
||||
|
||||
class TestRecommendationsContextView(APITestCase):
|
||||
"""Unit tests for the Recommendations Context View"""
|
||||
|
||||
def setUp(self):
|
||||
super().setUp()
|
||||
self.user = UserFactory()
|
||||
self.password = "test"
|
||||
self.url = reverse_lazy("learner_recommendations:recommendations_context")
|
||||
|
||||
@mock.patch("lms.djangoapps.learner_recommendations.views.country_code_from_ip")
|
||||
def test_successful_response(self, country_code_from_ip_mock):
|
||||
"""Test that country code gets sent back when authenticated"""
|
||||
|
||||
country_code_from_ip_mock.return_value = "za"
|
||||
self.client.login(username=self.user.username, password=self.password)
|
||||
|
||||
response = self.client.get(self.url)
|
||||
response_data = json.loads(response.content)
|
||||
|
||||
self.assertEqual(response_data["countryCode"], "za")
|
||||
|
||||
def test_unauthenticated_response(self):
|
||||
"""
|
||||
Test that a 401 is sent back if an anauthenticated user calls endpoint
|
||||
"""
|
||||
response = self.client.get(self.url)
|
||||
|
||||
self.assertEqual(response.status_code, 401)
|
||||
|
||||
|
||||
class TestCrossProductRecommendationsView(APITestCase):
|
||||
"""Unit tests for the Cross Product Recommendations View"""
|
||||
|
||||
|
||||
@@ -25,4 +25,7 @@ urlpatterns = [
|
||||
re_path(r"^courses/$",
|
||||
views.DashboardRecommendationsApiView.as_view(),
|
||||
name="courses"),
|
||||
re_path(r'^recommendations_context/$',
|
||||
views.RecommendationsContextView.as_view(),
|
||||
name='recommendations_context'),
|
||||
]
|
||||
|
||||
@@ -37,6 +37,7 @@ from lms.djangoapps.learner_recommendations.utils import (
|
||||
from lms.djangoapps.learner_recommendations.serializers import (
|
||||
AboutPageRecommendationsSerializer,
|
||||
DashboardRecommendationsSerializer,
|
||||
RecommendationsContextSerializer,
|
||||
CrossProductAndAmplitudeRecommendationsSerializer,
|
||||
CrossProductRecommendationsSerializer,
|
||||
AmplitudeRecommendationsSerializer,
|
||||
@@ -195,6 +196,37 @@ class CrossProductRecommendationsView(APIView):
|
||||
)
|
||||
|
||||
|
||||
class RecommendationsContextView(APIView):
|
||||
"""
|
||||
*Example Request*
|
||||
|
||||
GET /api/learner_recommendations/recommendations_context/
|
||||
"""
|
||||
|
||||
authentication_classes = (
|
||||
JwtAuthentication,
|
||||
SessionAuthenticationAllowInactiveUser,
|
||||
)
|
||||
permission_classes = (IsAuthenticated, NotJwtRestrictedApplication)
|
||||
|
||||
def get(self, request):
|
||||
"""
|
||||
Returns the context needed for the recommendations experiment:
|
||||
- Country Code
|
||||
"""
|
||||
ip_address = get_client_ip(request)[0]
|
||||
country_code = country_code_from_ip(ip_address)
|
||||
|
||||
return Response(
|
||||
RecommendationsContextSerializer(
|
||||
{
|
||||
"countryCode": country_code,
|
||||
}
|
||||
).data,
|
||||
status=200,
|
||||
)
|
||||
|
||||
|
||||
class ProductRecommendationsView(APIView):
|
||||
"""
|
||||
**Example Request**
|
||||
|
||||
Reference in New Issue
Block a user