From 5aab63782dd9126c86b5012ab52560738b5cd570 Mon Sep 17 00:00:00 2001 From: andrey-canon Date: Mon, 15 Jul 2024 16:18:19 -0500 Subject: [PATCH] refactor: replace generic list create api view with generic viewset and mixins --- eox_nelp/pearson_vue/api/v1/urls.py | 23 ++++++++++--------- eox_nelp/pearson_vue/api/v1/views.py | 17 ++++++++------ .../pearson_vue/tests/api/v1/test_views.py | 14 +++++------ 3 files changed, 29 insertions(+), 25 deletions(-) diff --git a/eox_nelp/pearson_vue/api/v1/urls.py b/eox_nelp/pearson_vue/api/v1/urls.py index 46aedcae..cab00e79 100644 --- a/eox_nelp/pearson_vue/api/v1/urls.py +++ b/eox_nelp/pearson_vue/api/v1/urls.py @@ -13,7 +13,7 @@ - revokeResult: Endpoint for revoking a result. - unrevokeResult: Endpoint for unrevoking a result. """ -from django.urls import path +from rest_framework.routers import DefaultRouter from eox_nelp.pearson_vue.api.v1.views import ( CancelAppointmentView, @@ -38,13 +38,14 @@ app_name = "eox_nelp" # pylint: disable=invalid-name -urlpatterns = [ - path('resultNotification/', ResultNotificationView.as_view(), name=RESULT_NOTIFICATION), - path('placeHold/', PlaceHoldView.as_view(), name=PLACE_HOLD), - path('releaseHold/', ReleaseHoldView.as_view(), name=RELEASE_HOLD), - path('modifyResultStatus/', ModifyResultStatusView.as_view(), name=MODIFY_RESULT_STATUS), - path('revokeResult/', RevokeResultView.as_view(), name=REVOKE_RESULT), - path('unrevokeResult/', UnrevokeResultView.as_view(), name=UNREVOKE_RESULT), - path('modifyAppointment/', ModifyAppointmentView.as_view(), name=MODIFY_APPOINTMENT), - path('cancelAppointment/', CancelAppointmentView.as_view(), name=CANCEL_APPOINTMENT), -] +router = DefaultRouter() +router.register('resultNotification', ResultNotificationView, basename=RESULT_NOTIFICATION) +router.register('placeHold', PlaceHoldView, basename=PLACE_HOLD) +router.register('releaseHold', ReleaseHoldView, basename=RELEASE_HOLD) +router.register('modifyResultStatus', ModifyResultStatusView, basename=MODIFY_RESULT_STATUS) +router.register('revokeResult', RevokeResultView, basename=REVOKE_RESULT) +router.register('unrevokeResult', UnrevokeResultView, basename=UNREVOKE_RESULT) +router.register('modifyAppointment', ModifyAppointmentView, basename=MODIFY_APPOINTMENT) +router.register('cancelAppointment', CancelAppointmentView, basename=CANCEL_APPOINTMENT) + +urlpatterns = router.urls diff --git a/eox_nelp/pearson_vue/api/v1/views.py b/eox_nelp/pearson_vue/api/v1/views.py index b1f2f4d6..19abc231 100644 --- a/eox_nelp/pearson_vue/api/v1/views.py +++ b/eox_nelp/pearson_vue/api/v1/views.py @@ -18,9 +18,11 @@ from django.http import Http404 from edx_rest_framework_extensions.auth.jwt.authentication import JwtAuthentication from eox_core.edxapp_wrapper.bearer_authentication import BearerAuthentication -from rest_framework import generics, status +from rest_framework import status +from rest_framework.mixins import CreateModelMixin, ListModelMixin from rest_framework.permissions import IsAuthenticated from rest_framework.response import Response +from rest_framework.viewsets import GenericViewSet from eox_nelp.edxapp_wrapper.student import AnonymousUserId from eox_nelp.pearson_vue.api.v1.serializers import PearsonRTENSerializer @@ -39,7 +41,7 @@ from eox_nelp.pearson_vue.rti_backend import ResultNotificationBackend -class PearsonRTENBaseView(generics.ListCreateAPIView): +class PearsonRTENBaseView(CreateModelMixin, ListModelMixin, GenericViewSet): """ Base view for Pearson RTEN (Real Time Event Notification) API endpoints. @@ -124,11 +126,12 @@ def create(self, request, *args, **kwargs): Returns: Response: Response object with status code 201 and an empty dictionary. """ - serializer = self.get_serializer(data=request.data) - serializer.is_valid(raise_exception=True) - self.perform_create(serializer) - headers = self.get_success_headers(serializer.data) - return Response({}, status=status.HTTP_200_OK, headers=headers) + response = super().create(request, *args, **kwargs) + + if response.status_code == status.HTTP_201_CREATED: + return Response({}, status=status.HTTP_200_OK, headers=response.headers) + + return response def get_candidate(self): """ diff --git a/eox_nelp/pearson_vue/tests/api/v1/test_views.py b/eox_nelp/pearson_vue/tests/api/v1/test_views.py index 573add55..4faad7a3 100644 --- a/eox_nelp/pearson_vue/tests/api/v1/test_views.py +++ b/eox_nelp/pearson_vue/tests/api/v1/test_views.py @@ -84,7 +84,7 @@ def test_create_result_notification_event(self, enrollment_from_id_mock): AnonymousUserId.objects.get.return_value.user = self.user response = self.client.post( - reverse(f"pearson-vue-api:v1:{self.event_type}"), + reverse(f"pearson-vue-api:v1:{self.event_type}-list"), { "clientCandidateID": "NELC123456", "authorization": { @@ -122,7 +122,7 @@ def test_create_result_notification_event_without_user(self): AnonymousUserId.DoesNotExist = ObjectDoesNotExist AnonymousUserId.objects.get.side_effect = AnonymousUserId.DoesNotExist - response = self.client.post(reverse(f"pearson-vue-api:v1:{self.event_type}"), {}, format="json") + response = self.client.post(reverse(f"pearson-vue-api:v1:{self.event_type}-list"), {}, format="json") final_count = PearsonRTENEvent.objects.filter(event_type=self.event_type, candidate=None).count() @@ -151,7 +151,7 @@ def test_create_result_notification_event_with_invalid_authorization_id(self, en enrollment_from_id_mock.return_value = {} response = self.client.post( - reverse(f"pearson-vue-api:v1:{self.event_type}"), + reverse(f"pearson-vue-api:v1:{self.event_type}-list"), {"authorization": {"clientAuthorizationID": "1584-4785"}}, format="json", ) @@ -185,7 +185,7 @@ def test_get_event(self): 'created_at': event.created_at.isoformat(), }) - response = self.client.get(reverse(f"pearson-vue-api:v1:{self.event_type}"), format="json") + response = self.client.get(reverse(f"pearson-vue-api:v1:{self.event_type}-list"), format="json") self.assertEqual(response.status_code, status.HTTP_200_OK) self.assertEqual(response.data["count"], len(events)) @@ -201,7 +201,7 @@ def test_create_result_notification_event_disabled(self): """ initial_count = PearsonRTENEvent.objects.filter(event_type=self.event_type).count() # pylint: disable=no-member - response = self.client.post(reverse(f"pearson-vue-api:v1:{self.event_type}"), {}, format="json") + response = self.client.post(reverse(f"pearson-vue-api:v1:{self.event_type}-list"), {}, format="json") final_count = PearsonRTENEvent.objects.filter(event_type=self.event_type).count() # pylint: disable=no-member @@ -216,7 +216,7 @@ def test_get_event_disabled(self): Expected behavior: - Response returns a 404 status code. """ - response = self.client.get(reverse(f"pearson-vue-api:v1:{self.event_type}"), format="json") + response = self.client.get(reverse(f"pearson-vue-api:v1:{self.event_type}-list"), format="json") self.assertEqual(response.status_code, status.HTTP_404_NOT_FOUND) @@ -253,7 +253,7 @@ def test_pipeline_execution(self, result_notification_mock): } } - response = self.client.post(reverse(f"pearson-vue-api:v1:{self.event_type}"), payload, format="json") + response = self.client.post(reverse(f"pearson-vue-api:v1:{self.event_type}-list"), payload, format="json") final_count = PearsonRTENEvent.objects.filter(event_type=self.event_type).count()