forked from encode/django-rest-framework
-
Notifications
You must be signed in to change notification settings - Fork 0
/
test_testing.py
312 lines (261 loc) · 10.9 KB
/
test_testing.py
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
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
# encoding: utf-8
from __future__ import unicode_literals
from io import BytesIO
from django.conf.urls import url
from django.contrib.auth.models import User
from django.shortcuts import redirect
from django.test import TestCase, override_settings
from rest_framework import fields, serializers
from rest_framework.decorators import api_view
from rest_framework.response import Response
from rest_framework.test import (
APIClient, APIRequestFactory, URLPatternsTestCase, force_authenticate
)
@api_view(['GET', 'POST'])
def view(request):
return Response({
'auth': request.META.get('HTTP_AUTHORIZATION', b''),
'user': request.user.username
})
@api_view(['GET', 'POST'])
def session_view(request):
active_session = request.session.get('active_session', False)
request.session['active_session'] = True
return Response({
'active_session': active_session
})
@api_view(['GET', 'POST', 'PUT', 'PATCH', 'DELETE', 'OPTIONS'])
def redirect_view(request):
return redirect('/view/')
class BasicSerializer(serializers.Serializer):
flag = fields.BooleanField(default=lambda: True)
@api_view(['POST'])
def post_view(request):
serializer = BasicSerializer(data=request.data)
serializer.is_valid(raise_exception=True)
return Response(serializer.validated_data)
urlpatterns = [
url(r'^view/$', view),
url(r'^session-view/$', session_view),
url(r'^redirect-view/$', redirect_view),
url(r'^post-view/$', post_view)
]
@override_settings(ROOT_URLCONF='tests.test_testing')
class TestAPITestClient(TestCase):
def setUp(self):
self.client = APIClient()
def test_credentials(self):
"""
Setting `.credentials()` adds the required headers to each request.
"""
self.client.credentials(HTTP_AUTHORIZATION='example')
for _ in range(0, 3):
response = self.client.get('/view/')
assert response.data['auth'] == 'example'
def test_force_authenticate(self):
"""
Setting `.force_authenticate()` forcibly authenticates each request.
"""
user = User.objects.create_user('example', '[email protected]')
self.client.force_authenticate(user)
response = self.client.get('/view/')
assert response.data['user'] == 'example'
def test_force_authenticate_with_sessions(self):
"""
Setting `.force_authenticate()` forcibly authenticates each request.
"""
user = User.objects.create_user('example', '[email protected]')
self.client.force_authenticate(user)
# First request does not yet have an active session
response = self.client.get('/session-view/')
assert response.data['active_session'] is False
# Subsequent requests have an active session
response = self.client.get('/session-view/')
assert response.data['active_session'] is True
# Force authenticating as `None` should also logout the user session.
self.client.force_authenticate(None)
response = self.client.get('/session-view/')
assert response.data['active_session'] is False
def test_csrf_exempt_by_default(self):
"""
By default, the test client is CSRF exempt.
"""
User.objects.create_user('example', '[email protected]', 'password')
self.client.login(username='example', password='password')
response = self.client.post('/view/')
assert response.status_code == 200
def test_explicitly_enforce_csrf_checks(self):
"""
The test client can enforce CSRF checks.
"""
client = APIClient(enforce_csrf_checks=True)
User.objects.create_user('example', '[email protected]', 'password')
client.login(username='example', password='password')
response = client.post('/view/')
expected = {'detail': 'CSRF Failed: CSRF cookie not set.'}
assert response.status_code == 403
assert response.data == expected
def test_can_logout(self):
"""
`logout()` resets stored credentials
"""
self.client.credentials(HTTP_AUTHORIZATION='example')
response = self.client.get('/view/')
assert response.data['auth'] == 'example'
self.client.logout()
response = self.client.get('/view/')
assert response.data['auth'] == b''
def test_logout_resets_force_authenticate(self):
"""
`logout()` resets any `force_authenticate`
"""
user = User.objects.create_user('example', '[email protected]', 'password')
self.client.force_authenticate(user)
response = self.client.get('/view/')
assert response.data['user'] == 'example'
self.client.logout()
response = self.client.get('/view/')
assert response.data['user'] == ''
def test_follow_redirect(self):
"""
Follow redirect by setting follow argument.
"""
response = self.client.get('/redirect-view/')
assert response.status_code == 302
response = self.client.get('/redirect-view/', follow=True)
assert response.redirect_chain is not None
assert response.status_code == 200
response = self.client.post('/redirect-view/')
assert response.status_code == 302
response = self.client.post('/redirect-view/', follow=True)
assert response.redirect_chain is not None
assert response.status_code == 200
response = self.client.put('/redirect-view/')
assert response.status_code == 302
response = self.client.put('/redirect-view/', follow=True)
assert response.redirect_chain is not None
assert response.status_code == 200
response = self.client.patch('/redirect-view/')
assert response.status_code == 302
response = self.client.patch('/redirect-view/', follow=True)
assert response.redirect_chain is not None
assert response.status_code == 200
response = self.client.delete('/redirect-view/')
assert response.status_code == 302
response = self.client.delete('/redirect-view/', follow=True)
assert response.redirect_chain is not None
assert response.status_code == 200
response = self.client.options('/redirect-view/')
assert response.status_code == 302
response = self.client.options('/redirect-view/', follow=True)
assert response.redirect_chain is not None
assert response.status_code == 200
def test_invalid_multipart_data(self):
"""
MultiPart encoding cannot support nested data, so raise a helpful
error if the user attempts to do so.
"""
self.assertRaises(
AssertionError, self.client.post,
path='/view/', data={'valid': 123, 'invalid': {'a': 123}}
)
def test_empty_post_uses_default_boolean_value(self):
response = self.client.post(
'/post-view/',
data=None,
content_type='application/json'
)
assert response.status_code == 200
assert response.data == {"flag": True}
class TestAPIRequestFactory(TestCase):
def test_csrf_exempt_by_default(self):
"""
By default, the test client is CSRF exempt.
"""
user = User.objects.create_user('example', '[email protected]', 'password')
factory = APIRequestFactory()
request = factory.post('/view/')
request.user = user
response = view(request)
assert response.status_code == 200
def test_explicitly_enforce_csrf_checks(self):
"""
The test client can enforce CSRF checks.
"""
user = User.objects.create_user('example', '[email protected]', 'password')
factory = APIRequestFactory(enforce_csrf_checks=True)
request = factory.post('/view/')
request.user = user
response = view(request)
expected = {'detail': 'CSRF Failed: CSRF cookie not set.'}
assert response.status_code == 403
assert response.data == expected
def test_invalid_format(self):
"""
Attempting to use a format that is not configured will raise an
assertion error.
"""
factory = APIRequestFactory()
self.assertRaises(
AssertionError, factory.post,
path='/view/', data={'example': 1}, format='xml'
)
def test_force_authenticate(self):
"""
Setting `force_authenticate()` forcibly authenticates the request.
"""
user = User.objects.create_user('example', '[email protected]')
factory = APIRequestFactory()
request = factory.get('/view')
force_authenticate(request, user=user)
response = view(request)
assert response.data['user'] == 'example'
def test_upload_file(self):
# This is a 1x1 black png
simple_png = BytesIO(b'\x89PNG\r\n\x1a\n\x00\x00\x00\rIHDR\x00\x00\x00\x01\x00\x00\x00\x01\x08\x06\x00\x00\x00\x1f\x15\xc4\x89\x00\x00\x00\rIDATx\x9cc````\x00\x00\x00\x05\x00\x01\xa5\xf6E@\x00\x00\x00\x00IEND\xaeB`\x82')
simple_png.name = 'test.png'
factory = APIRequestFactory()
factory.post('/', data={'image': simple_png})
def test_request_factory_url_arguments(self):
"""
This is a non regression test against #1461
"""
factory = APIRequestFactory()
request = factory.get('/view/?demo=test')
assert dict(request.GET) == {'demo': ['test']}
request = factory.get('/view/', {'demo': 'test'})
assert dict(request.GET) == {'demo': ['test']}
def test_request_factory_url_arguments_with_unicode(self):
factory = APIRequestFactory()
request = factory.get('/view/?demo=testé')
assert dict(request.GET) == {'demo': ['testé']}
request = factory.get('/view/', {'demo': 'testé'})
assert dict(request.GET) == {'demo': ['testé']}
def test_empty_request_content_type(self):
factory = APIRequestFactory()
request = factory.post(
'/post-view/',
data=None,
content_type='application/json',
)
assert request.META['CONTENT_TYPE'] == 'application/json'
class TestUrlPatternTestCase(URLPatternsTestCase):
urlpatterns = [
url(r'^$', view),
]
@classmethod
def setUpClass(cls):
assert urlpatterns is not cls.urlpatterns
super(TestUrlPatternTestCase, cls).setUpClass()
assert urlpatterns is cls.urlpatterns
@classmethod
def tearDownClass(cls):
assert urlpatterns is cls.urlpatterns
super(TestUrlPatternTestCase, cls).tearDownClass()
assert urlpatterns is not cls.urlpatterns
def test_urlpatterns(self):
assert self.client.get('/').status_code == 200
class TestExistingPatterns(TestCase):
def test_urlpatterns(self):
# sanity test to ensure that this test module does not have a '/' route
assert self.client.get('/').status_code == 404