From 86460b11cb8bfc948881822064686000b48020cd Mon Sep 17 00:00:00 2001 From: Floris Bartra Date: Sat, 27 Jul 2024 02:32:14 +0200 Subject: [PATCH] Add PUT, PATCH and DELETE method for the pizzas. --- insalan/pizza/tests.py | 127 ++++++++++++++++++++++++++++++++++++++-- insalan/pizza/views.py | 128 ++++++++++++++++++++++++++++++++++------- 2 files changed, 230 insertions(+), 25 deletions(-) diff --git a/insalan/pizza/tests.py b/insalan/pizza/tests.py index 3ce35337..d40b6399 100644 --- a/insalan/pizza/tests.py +++ b/insalan/pizza/tests.py @@ -25,7 +25,7 @@ def setUp(self): self.admin_user = User.objects.create( username="admin", email="admin@example.com", is_staff=True ) - + self.pizza1 = Pizza.objects.create(name="Test Pizza") self.pizza2 = Pizza.objects.create(name="Test Pizza 2") @@ -57,7 +57,7 @@ def test_pizza_list(self): self.assertEqual(len(response.data), 2) self.assertEqual(response.data[0], self.pizza1.id) self.assertEqual(response.data[1], self.pizza2.id) - + def test_pizza_post(self): """Test the pizza post endpoint""" client = APIClient() @@ -138,6 +138,125 @@ def test_pizza_by_timeslot_id_not_found(self): ) self.assertEqual(response.status_code, status.HTTP_404_NOT_FOUND) + def test_pizza_put(self) -> None: + """Test the pizza put endpoint""" + client = APIClient() + client.force_login(user=self.admin_user) + pizza_id: int = self.pizza1.id + response = client.put(reverse( + "pizza/detail", + kwargs={"pk": pizza_id} + ), {"name": "New Pizza Name"}) + self.assertEqual(response.status_code, status.HTTP_200_OK) + self.assertEqual(response.data, { + "id": pizza_id, + "name": "New Pizza Name", + "ingredients": None, + "allergens": None, + "image": None + }) + + def test_pizza_put_unauthorized(self) -> None: + """Test the pizza put endpoint with unauthorized user""" + client = APIClient() + pizza_id: int = self.pizza1.id + response = client.put(reverse( + "pizza/detail", + kwargs={"pk": pizza_id} + ), {"name": "New Pizza Name"}) + self.assertEqual(response.status_code, status.HTTP_403_FORBIDDEN) + self.assertEqual(response.data, { + "detail": "Informations d'authentification non fournies." + }) + self.assertEqual(Pizza.objects.get(id=pizza_id).name, "Test Pizza") + + def test_pizza_put_not_found(self) -> None: + "Test the pizza put endpoint with wrong id""" + client = APIClient() + client.force_login(user=self.admin_user) + response = client.put(reverse( + "pizza/detail", + kwargs={"pk": 999} + ), {"name": "New Pizza Name"}) + self.assertEqual(response.status_code, status.HTTP_404_NOT_FOUND) + self.assertEqual(response.data, { + "detail": "Pas trouvé." + }) + + def test_pizza_patch(self) -> None: + """Test the pizza patch endpoint""" + client = APIClient() + client.force_login(user=self.admin_user) + pizza_id: int = self.pizza1.id + response = client.patch(reverse( + "pizza/detail", + kwargs={"pk": pizza_id} + ), {"name": "New Pizza Name"}) + self.assertEqual(response.status_code, status.HTTP_200_OK) + self.assertEqual(response.data, { + "id": pizza_id, + "name": "New Pizza Name", + "ingredients": None, + "allergens": None, + "image": None + }) + + def test_pizza_patch_unauthorized(self) -> None: + """Test the pizza patch endpoint with unauthorized user""" + client = APIClient() + pizza_id: int = self.pizza1.id + response = client.patch(reverse( + "pizza/detail", + kwargs={"pk": pizza_id} + ), {"name": "New Pizza Name"}) + self.assertEqual(response.status_code, status.HTTP_403_FORBIDDEN) + self.assertEqual(response.data, { + "detail": "Informations d'authentification non fournies." + }) + self.assertEqual(Pizza.objects.get(id=pizza_id).name, "Test Pizza") + + def test_pizza_patch_not_found(self) -> None: + "Test the pizza patch endpoint with wrong id""" + client = APIClient() + client.force_login(user=self.admin_user) + response = client.patch(reverse( + "pizza/detail", + kwargs={"pk": 999} + ), {"name": "New Pizza Name"}) + self.assertEqual(response.status_code, status.HTTP_404_NOT_FOUND) + self.assertEqual(response.data, { + "detail": "Pas trouvé." + }) + + def test_pizza_delete(self) -> None: + """Test the pizza delete endpoint""" + client = APIClient() + client.force_login(user=self.admin_user) + response = client.delete( + reverse("pizza/detail", kwargs={"pk": self.pizza1.id}) + ) + self.assertEqual(response.status_code, status.HTTP_204_NO_CONTENT) + self.assertEqual(Pizza.objects.count(), 1) + + def test_pizza_delete_unauthorized(self) -> None: + """Test the pizza delete endpoint with unauthorized user""" + client = APIClient() + response = client.delete( + reverse("pizza/detail", kwargs={"pk": self.pizza1.id}) + ) + self.assertEqual(response.status_code, status.HTTP_403_FORBIDDEN) + self.assertEqual(Pizza.objects.count(), 2) + + def test_pizza_delete_not_found(self) -> None: + """Test the pizza delete endpoint with wrong id""" + client = APIClient() + client.force_login(user=self.admin_user) + response = client.delete( + reverse("pizza/detail", kwargs={"pk": 999}) + ) + self.assertEqual(response.status_code, status.HTTP_404_NOT_FOUND) + self.assertEqual(Pizza.objects.count(), 2) + def test_timeslot_list(self): """Test the timeslot list endpoint""" client = APIClient() @@ -307,7 +426,7 @@ def test_order_post_unauthorized(self): ) self.assertEqual(response.status_code, status.HTTP_403_FORBIDDEN) self.assertEqual(Order.objects.count(), 1) - + def test_order_post_not_found(self): """Test the order post endpoint with wrong id""" client = APIClient() @@ -481,4 +600,4 @@ def test_export_order_post_full(self): ) self.assertEqual(response.status_code, status.HTTP_200_OK) self.assertEqual(len(response.data), 1) - self.assertEqual(response.data[0]["orders"][self.order.pizza.all()[0].name], 1) \ No newline at end of file + self.assertEqual(response.data[0]["orders"][self.order.pizza.all()[0].name], 1) diff --git a/insalan/pizza/views.py b/insalan/pizza/views.py index 0edd1f07..9155fe6e 100644 --- a/insalan/pizza/views.py +++ b/insalan/pizza/views.py @@ -1,6 +1,6 @@ """ Views for the pizza module - WORK IN PROGRESS: + WORK IN PROGRESS: - missing tests """ from django.utils.translation import gettext_lazy as _ @@ -36,7 +36,7 @@ def get_serializer_class(self): if self.request.method == "GET": return serializers.PizzaIdSerializer return serializers.PizzaSerializer - + @swagger_auto_schema( responses={ 201: serializers.PizzaSerializer, @@ -48,13 +48,21 @@ def get_serializer_class(self): description=_("Données invalides") ) } - ) - } - ) + ), + 403: openapi.Schema( + type=openapi.TYPE_OBJECT, + properties={ + "err": openapi.Schema( + type=openapi.TYPE_STRING, + description=_("Vous n'êtes pas autorisé à créer une pizza") + ) + } + ) + + } + ) def post(self, request, *args, **kwargs): - """ - Create a pizza - """ + """Create a pizza.""" return super().post(request, *args, **kwargs) @swagger_auto_schema( @@ -68,9 +76,7 @@ def post(self, request, *args, **kwargs): } ) def get(self, request, *args, **kwargs): - """ - Get all pizzas - """ + """Get all pizzas.""" return super().get(request, *args, **kwargs) class PizzaListFull(generics.ListAPIView): @@ -80,12 +86,13 @@ class PizzaListFull(generics.ListAPIView): serializer_class = serializers.PizzaSerializer permission_classes = [ReadOnly] -class PizzaDetail(generics.RetrieveAPIView): + +class PizzaDetail(generics.RetrieveUpdateDestroyAPIView): """Find a pizza by its id""" pagination_class = None queryset = Pizza.objects.all() serializer_class = serializers.PizzaSerializer - permission_classes = [ReadOnly] + permission_classes = [permissions.IsAdminUser | ReadOnly] @swagger_auto_schema( responses={ @@ -102,11 +109,90 @@ class PizzaDetail(generics.RetrieveAPIView): } ) def get(self, request, *args, **kwargs): - """ - Get a pizza by its id - """ + """Get a pizza by its id.""" return super().get(request, *args, **kwargs) + @swagger_auto_schema( + responses={ + 200: serializers.PizzaSerializer, + 403: openapi.Schema( + type=openapi.TYPE_OBJECT, + properties={ + "detail": openapi.Schema( + type=openapi.TYPE_STRING, + description=_("Vous n'êtes pas autorisé à modifier cet pizza") + ) + } + ), + 404: openapi.Schema( + type=openapi.TYPE_OBJECT, + properties={ + "detail": openapi.Schema( + type=openapi.TYPE_STRING, + description=_("Pizza non trouvée") + ) + } + ) + } + ) + def put(self, request, *args, **kwargs): + """Update a pizza.""" + return super().put(request, *args, **kwargs) + + @swagger_auto_schema( + responses={ + 200: serializers.PizzaSerializer, + 403: openapi.Schema( + type=openapi.TYPE_OBJECT, + properties={ + "detail": openapi.Schema( + type=openapi.TYPE_STRING, + description=_("Vous n'êtes pas autorisé à modifier cet pizza") + ) + } + ), + 404: openapi.Schema( + type=openapi.TYPE_OBJECT, + properties={ + "detail": openapi.Schema( + type=openapi.TYPE_STRING, + description=_("Pizza non trouvée") + ) + } + ) + } + ) + def patch(self, request, *args, **kwargs): + """Partially update a pizza.""" + return super().patch(request, *args, **kwargs) + + @swagger_auto_schema( + responses={ + 403: openapi.Schema( + type=openapi.TYPE_OBJECT, + properties={ + "detail": openapi.Schema( + type=openapi.TYPE_STRING, + description=_("Vous n'êtes pas autorisé à supprimer cet pizza") + ) + } + ), + 404: openapi.Schema( + type=openapi.TYPE_OBJECT, + properties={ + "detail": openapi.Schema( + type=openapi.TYPE_STRING, + description=_("Pizza non trouvée") + ) + } + ) + } + ) + def delete(self, request, *args, **kwargs): + """Delete a pizza.""" + return super().delete(request, *args, **kwargs) + + class PizzaSearch(generics.ListAPIView): """Search a pizza by its name""" pagination_class = None @@ -116,7 +202,7 @@ class PizzaSearch(generics.ListAPIView): def get_queryset(self): partial_name = self.request.query_params.get("q", None) return Pizza.objects.filter(name__contains=partial_name) - + @swagger_auto_schema( manual_parameters=[ openapi.Parameter( @@ -267,7 +353,7 @@ def get_serializer_class(self): if self.request.method == "GET": return serializers.TimeSlotIdSerializer return serializers.TimeSlotSerializer - + @swagger_auto_schema( responses={ 201: serializers.TimeSlotSerializer, @@ -287,7 +373,7 @@ def post(self, request, *args, **kwargs): Create a timeslot """ return super().post(request, *args, **kwargs) - + @swagger_auto_schema( responses={ 200: openapi.Schema( @@ -353,7 +439,7 @@ def get(self, request, *args, **kwargs): serializer.pop("external_product") return Response(serializer) - + @swagger_auto_schema( responses={ 200: serializers.TimeSlotSerializer, @@ -405,7 +491,7 @@ def get_serializer_class(self): if self.request.method == "GET": return serializers.OrderIdSerializer return serializers.CreateOrderSerializer - + @swagger_auto_schema( responses={ 200: serializers.OrderIdSerializer,