File: test_extend_schema_view.py

package info (click to toggle)
python-drf-spectacular 0.28.0-2
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid
  • size: 1,748 kB
  • sloc: python: 14,174; javascript: 114; sh: 61; makefile: 30
file content (123 lines) | stat: -rw-r--r-- 4,330 bytes parent folder | download | duplicates (2)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
import pytest
from django.db import models
from rest_framework import mixins, routers, serializers, viewsets
from rest_framework.decorators import action
from rest_framework.response import Response
from rest_framework.test import APIClient

from drf_spectacular.generators import SchemaGenerator
from drf_spectacular.types import OpenApiTypes
from drf_spectacular.utils import extend_schema, extend_schema_view
from tests import assert_schema


class ESVModel(models.Model):
    pass


class ESVSerializer(serializers.ModelSerializer):
    class Meta:
        model = ESVModel
        fields = '__all__'


class DualMethodActionParamsSerializer(serializers.Serializer):
    message = serializers.CharField()


@extend_schema(tags=['global-tag'])
@extend_schema_view(
    list=extend_schema(description='view list description'),
    retrieve=extend_schema(description='view retrieve description'),
    extended_action=extend_schema(description='view extended action description'),
    raw_action=extend_schema(description='view raw action description'),
    dual_method_action=[
        extend_schema(parameters=[DualMethodActionParamsSerializer], methods=['GET']),
        extend_schema(request=DualMethodActionParamsSerializer, methods=['POST']),
    ]
)
class XViewSet(mixins.ListModelMixin, mixins.RetrieveModelMixin, viewsets.GenericViewSet):
    queryset = ESVModel.objects.all()
    serializer_class = ESVSerializer

    @extend_schema(tags=['custom-retrieve-tag'])
    def retrieve(self, request, *args, **kwargs):
        return super().retrieve(request, *args, **kwargs)

    @extend_schema(responses=OpenApiTypes.DATE)
    @action(detail=False)
    def extended_action(self, request):
        return Response('2020-10-31')

    @action(detail=False, methods=['GET'])
    def raw_action(self, request):
        return Response('2019-03-01')

    @extend_schema(description='view dual method action description')
    @action(detail=False, methods=['GET', 'POST'])
    def dual_method_action(self, request):
        if request.method == 'POST':
            data = request.data
        else:
            data = request.query_params
        return Response(data['message'])


# view to make sure there is no cross-talk
class YViewSet(viewsets.ModelViewSet):
    serializer_class = ESVSerializer
    queryset = ESVModel.objects.all()


# view to make sure that schema applied to a subclass does not affect its parent.
@extend_schema_view(
    list=extend_schema(exclude=True),
    retrieve=extend_schema(description='overridden description for child only'),
    extended_action=extend_schema(responses={200: {'type': 'string', 'pattern': r'^[0-9]{4}(?:-[0-9]{2}){2}$'}}),
    raw_action=extend_schema(summary="view raw action summary"),
)
class ZViewSet(XViewSet):
    @extend_schema(tags=['child-tag'])
    @action(detail=False, methods=['GET'])
    def raw_action(self, request):
        return Response('2019-03-01')  # pragma: no cover


router = routers.SimpleRouter()
router.register('x', XViewSet)
router.register('y', YViewSet, basename='alt1')
router.register('z', ZViewSet, basename='alt2')
urlpatterns = router.urls


@pytest.mark.urls(__name__)
def test_extend_schema_view(no_warnings):
    assert_schema(
        SchemaGenerator().get_schema(request=None, public=True),
        'tests/test_extend_schema_view.yml'
    )


@pytest.mark.urls(__name__)
@pytest.mark.django_db
def test_extend_schema_view_call_transparency(no_warnings):
    ESVModel.objects.create()

    response = APIClient().get('/x/')
    assert response.status_code == 200
    assert response.content == b'[{"id":1}]'
    response = APIClient().get('/x/1/')
    assert response.status_code == 200
    assert response.content == b'{"id":1}'
    response = APIClient().get('/x/extended_action/')
    assert response.status_code == 200
    assert response.content == b'"2020-10-31"'
    response = APIClient().get('/x/raw_action/')
    assert response.status_code == 200
    assert response.content == b'"2019-03-01"'
    response = APIClient().get('/x/dual_method_action/', {'message': 'foo bar'})
    assert response.status_code == 200
    assert response.content == b'"foo bar"'
    response = APIClient().post('/x/dual_method_action/', {'message': 'foo bar'})
    assert response.status_code == 200
    assert response.content == b'"foo bar"'