Skip to content

Convert ReadOnlyModelViewSet to pytest style #1058

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Mar 12, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
81 changes: 0 additions & 81 deletions example/tests/test_views.py
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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)
41 changes: 40 additions & 1 deletion tests/test_views.py
Original file line number Diff line number Diff line change
@@ -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

Expand All @@ -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:
Expand Down Expand Up @@ -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):
Expand Down