1+ import itertools
12from io import BytesIO
3+ from unittest .mock import patch
24
35import django
46from django .contrib .auth .models import User
7+ from django .http import HttpResponseRedirect
58from django .shortcuts import redirect
69from django .test import TestCase , override_settings
710from django .urls import path
1417)
1518
1619
17- @api_view (['GET' , 'POST' ])
20+ @api_view (['GET' , 'POST' , 'PUT' , 'PATCH' , 'DELETE' , 'OPTIONS' ])
1821def view (request ):
1922 return Response ({
2023 'auth' : request .META .get ('HTTP_AUTHORIZATION' , b'' ),
@@ -36,6 +39,11 @@ def redirect_view(request):
3639 return redirect ('/view/' )
3740
3841
42+ @api_view (['GET' , 'POST' , 'PUT' , 'PATCH' , 'DELETE' , 'OPTIONS' ])
43+ def redirect_307_308_view (request , code ):
44+ return HttpResponseRedirect ('/view/' , status = code )
45+
46+
3947class BasicSerializer (serializers .Serializer ):
4048 flag = fields .BooleanField (default = lambda : True )
4149
@@ -51,6 +59,7 @@ def post_view(request):
5159 path ('view/' , view ),
5260 path ('session-view/' , session_view ),
5361 path ('redirect-view/' , redirect_view ),
62+ path ('redirect-view/<int:code>/' , redirect_307_308_view ),
5463 path ('post-view/' , post_view )
5564]
5665
@@ -146,41 +155,32 @@ def test_follow_redirect(self):
146155 """
147156 Follow redirect by setting follow argument.
148157 """
149- response = self .client .get ('/redirect-view/' )
150- assert response .status_code == 302
151- response = self .client .get ('/redirect-view/' , follow = True )
152- assert response .redirect_chain is not None
153- assert response .status_code == 200
154-
155- response = self .client .post ('/redirect-view/' )
156- assert response .status_code == 302
157- response = self .client .post ('/redirect-view/' , follow = True )
158- assert response .redirect_chain is not None
159- assert response .status_code == 200
160-
161- response = self .client .put ('/redirect-view/' )
162- assert response .status_code == 302
163- response = self .client .put ('/redirect-view/' , follow = True )
164- assert response .redirect_chain is not None
165- assert response .status_code == 200
166-
167- response = self .client .patch ('/redirect-view/' )
168- assert response .status_code == 302
169- response = self .client .patch ('/redirect-view/' , follow = True )
170- assert response .redirect_chain is not None
171- assert response .status_code == 200
172-
173- response = self .client .delete ('/redirect-view/' )
174- assert response .status_code == 302
175- response = self .client .delete ('/redirect-view/' , follow = True )
176- assert response .redirect_chain is not None
177- assert response .status_code == 200
178-
179- response = self .client .options ('/redirect-view/' )
180- assert response .status_code == 302
181- response = self .client .options ('/redirect-view/' , follow = True )
182- assert response .redirect_chain is not None
183- assert response .status_code == 200
158+ for method in ('get' , 'post' , 'put' , 'patch' , 'delete' , 'options' ):
159+ with self .subTest (method = method ):
160+ req_method = getattr (self .client , method )
161+ response = req_method ('/redirect-view/' )
162+ assert response .status_code == 302
163+ response = req_method ('/redirect-view/' , follow = True )
164+ assert response .redirect_chain is not None
165+ assert response .status_code == 200
166+
167+ def test_follow_307_308_preserve_kwargs (self , * mocked_methods ):
168+ """
169+ Follow redirect by setting follow argument, and make sure the following
170+ method called with appropriate kwargs.
171+ """
172+ methods = ('get' , 'post' , 'put' , 'patch' , 'delete' , 'options' )
173+ codes = (307 , 308 )
174+ for method , code in itertools .product (methods , codes ):
175+ subtest_ctx = self .subTest (method = method , code = code )
176+ patch_ctx = patch .object (self .client , method , side_effect = getattr (self .client , method ))
177+ with subtest_ctx , patch_ctx as req_method :
178+ kwargs = {'data' : {'example' : 'test' }, 'format' : 'json' }
179+ response = req_method ('/redirect-view/%s/' % code , follow = True , ** kwargs )
180+ assert response .redirect_chain is not None
181+ assert response .status_code == 200
182+ for _ , call_args , call_kwargs in req_method .mock_calls :
183+ assert all (call_kwargs [k ] == kwargs [k ] for k in kwargs if k in call_kwargs )
184184
185185 def test_invalid_multipart_data (self ):
186186 """
0 commit comments