From d2f7660683f9ee1e7aa7f284f54358bf4ec1591e Mon Sep 17 00:00:00 2001 From: Oliver Sauder Date: Sat, 12 Mar 2022 22:07:24 +0400 Subject: [PATCH] Convert ReadOnlyModelViewSet to pytest --- example/tests/test_views.py | 81 ------------------------------------- tests/test_views.py | 41 ++++++++++++++++++- 2 files changed, 40 insertions(+), 82 deletions(-) diff --git a/example/tests/test_views.py b/example/tests/test_views.py index a3aa1444..592a72bc 100644 --- a/example/tests/test_views.py +++ b/example/tests/test_views.py @@ -3,15 +3,11 @@ from django.test import RequestFactory, override_settings from django.utils import timezone -from rest_framework import status -from rest_framework.decorators import action from rest_framework.exceptions import NotFound from rest_framework.request import Request -from rest_framework.response import Response from rest_framework.reverse import reverse from rest_framework.test import APIRequestFactory, APITestCase, force_authenticate -from rest_framework_json_api import serializers, views from rest_framework_json_api.utils import format_resource_type from example.factories import AuthorFactory, CommentFactory, EntryFactory @@ -713,80 +709,3 @@ def test_get_object_gives_correct_entry(self): } got = resp.json() self.assertEqual(got, expected) - - -class BasicAuthorSerializer(serializers.ModelSerializer): - class Meta: - model = Author - fields = ("name",) - - -class ReadOnlyViewSetWithCustomActions(views.ReadOnlyModelViewSet): - queryset = Author.objects.all() - serializer_class = BasicAuthorSerializer - - @action(detail=False, methods=["get", "post", "patch", "delete"]) - def group_action(self, request): - return Response(status=status.HTTP_204_NO_CONTENT) - - @action(detail=True, methods=["get", "post", "patch", "delete"]) - def item_action(self, request, pk): - return Response(status=status.HTTP_204_NO_CONTENT) - - -class TestReadonlyModelViewSet(TestBase): - """ - Test if ReadOnlyModelViewSet allows to have custom actions with POST, PATCH, DELETE methods - """ - - factory = RequestFactory() - viewset_class = ReadOnlyViewSetWithCustomActions - media_type = "application/vnd.api+json" - - def test_group_action_allows_get(self): - view = self.viewset_class.as_view({"get": "group_action"}) - request = self.factory.get("/") - response = view(request) - self.assertEqual(status.HTTP_204_NO_CONTENT, response.status_code) - - def test_group_action_allows_post(self): - view = self.viewset_class.as_view({"post": "group_action"}) - request = self.factory.post("/", "{}", content_type=self.media_type) - response = view(request) - self.assertEqual(status.HTTP_204_NO_CONTENT, response.status_code) - - def test_group_action_allows_patch(self): - view = self.viewset_class.as_view({"patch": "group_action"}) - request = self.factory.patch("/", "{}", content_type=self.media_type) - response = view(request) - self.assertEqual(status.HTTP_204_NO_CONTENT, response.status_code) - - def test_group_action_allows_delete(self): - view = self.viewset_class.as_view({"delete": "group_action"}) - request = self.factory.delete("/", "{}", content_type=self.media_type) - response = view(request) - self.assertEqual(status.HTTP_204_NO_CONTENT, response.status_code) - - def test_item_action_allows_get(self): - view = self.viewset_class.as_view({"get": "item_action"}) - request = self.factory.get("/") - response = view(request, pk="1") - self.assertEqual(status.HTTP_204_NO_CONTENT, response.status_code) - - def test_item_action_allows_post(self): - view = self.viewset_class.as_view({"post": "item_action"}) - request = self.factory.post("/", "{}", content_type=self.media_type) - response = view(request, pk="1") - self.assertEqual(status.HTTP_204_NO_CONTENT, response.status_code) - - def test_item_action_allows_patch(self): - view = self.viewset_class.as_view({"patch": "item_action"}) - request = self.factory.patch("/", "{}", content_type=self.media_type) - response = view(request, pk="1") - self.assertEqual(status.HTTP_204_NO_CONTENT, response.status_code) - - def test_item_action_allows_delete(self): - view = self.viewset_class.as_view({"delete": "item_action"}) - request = self.factory.delete("/", "{}", content_type=self.media_type) - response = view(request, pk="1") - self.assertEqual(status.HTTP_204_NO_CONTENT, response.status_code) diff --git a/tests/test_views.py b/tests/test_views.py index f8967982..c4466f72 100644 --- a/tests/test_views.py +++ b/tests/test_views.py @@ -1,6 +1,7 @@ import pytest from django.urls import path, reverse from rest_framework import status +from rest_framework.decorators import action from rest_framework.response import Response from rest_framework.views import APIView @@ -9,8 +10,9 @@ from rest_framework_json_api.relations import ResourceRelatedField from rest_framework_json_api.renderers import JSONRenderer from rest_framework_json_api.utils import format_link_segment -from rest_framework_json_api.views import ModelViewSet +from rest_framework_json_api.views import ModelViewSet, ReadOnlyModelViewSet from tests.models import BasicModel +from tests.serializers import BasicModelSerializer class TestModelViewSet: @@ -55,6 +57,43 @@ class RelatedFieldNameView(ModelViewSet): assert view.get_related_field_name() == related_model_field_name +class TestReadonlyModelViewSet: + @pytest.mark.parametrize( + "method", + ["get", "post", "patch", "delete"], + ) + @pytest.mark.parametrize( + "custom_action,action_kwargs", + [("list_action", {}), ("detail_action", {"pk": 1})], + ) + def test_custom_action_allows_all_methods( + self, rf, method, custom_action, action_kwargs + ): + """ + Test that write methods are allowed on custom list actions. + + Even though a read only view only allows reading, custom actions + should be allowed to define other methods which are allowed. + """ + + class ReadOnlyModelViewSetWithCustomActions(ReadOnlyModelViewSet): + serializer_class = BasicModelSerializer + queryset = BasicModel.objects.all() + + @action(detail=False, methods=["get", "post", "patch", "delete"]) + def list_action(self, request): + return Response(status=status.HTTP_204_NO_CONTENT) + + @action(detail=True, methods=["get", "post", "patch", "delete"]) + def detail_action(self, request, pk): + return Response(status=status.HTTP_204_NO_CONTENT) + + view = ReadOnlyModelViewSetWithCustomActions.as_view({method: custom_action}) + request = getattr(rf, method)("/", data={}) + response = view(request, **action_kwargs) + assert response.status_code == status.HTTP_204_NO_CONTENT + + class TestAPIView: @pytest.mark.urls(__name__) def test_patch(self, client):