Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse files

Fixed #13725 -- take url scheme into account in assertRedirects

Scheme is handled correctly when making comparisons between two URLs. If
there isn't any scheme specified in the location where we are redirected to,
the original request's scheme is used. If present, the scheme in
``expected_url`` is the one used to make the comparations to.
  • Loading branch information...
commit 9c5f6cd565f1bc519dec20e3e44313cb8d8e0e94 1 parent 9b95fa7
@unaizalakain unaizalakain authored
View
14 django/test/testcases.py
@@ -246,6 +246,8 @@ def assertRedirects(self, response, expected_url, status_code=302,
if msg_prefix:
msg_prefix += ": "
+ e_scheme, e_netloc, e_path, e_query, e_fragment = urlsplit(expected_url)
+
if hasattr(response, 'redirect_chain'):
# The request was a followed redirect
self.assertTrue(len(response.redirect_chain) > 0,
@@ -259,6 +261,7 @@ def assertRedirects(self, response, expected_url, status_code=302,
(response.redirect_chain[0][1], status_code))
url, status_code = response.redirect_chain[-1]
+ scheme, netloc, path, query, fragment = urlsplit(url)
self.assertEqual(response.status_code, target_status_code,
msg_prefix + "Response didn't redirect as expected: Final"
@@ -276,7 +279,8 @@ def assertRedirects(self, response, expected_url, status_code=302,
scheme, netloc, path, query, fragment = urlsplit(url)
if fetch_redirect_response:
- redirect_response = response.client.get(path, QueryDict(query))
+ redirect_response = response.client.get(path, QueryDict(query),
+ secure=(scheme == 'https'))
# Get the redirection page, using the same client that was used
# to obtain the original response.
@@ -285,10 +289,10 @@ def assertRedirects(self, response, expected_url, status_code=302,
" response code was %d (expected %d)" %
(path, redirect_response.status_code, target_status_code))
- e_scheme, e_netloc, e_path, e_query, e_fragment = urlsplit(expected_url)
- if not (e_scheme or e_netloc):
- expected_url = urlunsplit(('http', host or 'testserver', e_path,
- e_query, e_fragment))
+ e_scheme = e_scheme if e_scheme else scheme or 'http'
+ e_netloc = e_netloc if e_netloc else host or 'testserver'
+ expected_url = urlunsplit((e_scheme, e_netloc, e_path, e_query,
+ e_fragment))
self.assertEqual(url, expected_url,
msg_prefix + "Response redirected to '%s', expected '%s'" %
View
3  docs/releases/1.7.txt
@@ -444,6 +444,9 @@ Tests
client can't fetch externals URLs, this allows you to use ``assertRedirects``
with redirects that aren't part of your Django app.
+* Correct handling of scheme when making comparisons in
+ :meth:`~django.test.SimpleTestCase.assertRedirects`.
+
* The ``secure`` argument was added to all the request methods of
:class:`~django.test.Client`. If ``True``, the request will be made
through HTTPS.
View
7 docs/topics/testing/overview.txt
@@ -1576,6 +1576,13 @@ your test suite.
loaded. Since the test client can't fetch externals URLs, this is
particularly useful if ``expected_url`` isn't part of your Django app.
+ .. versionadded:: 1.7
+
+ Scheme is handled correctly when making comparisons between two URLs. If
+ there isn't any scheme specified in the location where we are redirected to,
+ the original request's scheme is used. If present, the scheme in
+ ``expected_url`` is the one used to make the comparisons to.
+
.. method:: SimpleTestCase.assertHTMLEqual(html1, html2, msg=None)
Asserts that the strings ``html1`` and ``html2`` are equal. The comparison
View
19 tests/test_client_regress/tests.py
@@ -5,6 +5,7 @@
from __future__ import unicode_literals
import os
+import itertools
from django.core.urlresolvers import reverse
from django.template import (TemplateSyntaxError,
@@ -433,6 +434,24 @@ def test_redirect_on_non_redirect_page(self):
except AssertionError as e:
self.assertIn("abc: Response didn't redirect as expected: Response code was 200 (expected 302)", str(e))
+ def test_redirect_scheme(self):
+ "An assertion is raised if the response doesn't have the scheme specified in expected_url"
+
+ # Assure that original request scheme is preserved if no scheme specified in the redirect location
+ response = self.client.get('/test_client/redirect_view/', secure=True)
+ self.assertRedirects(response, 'https://testserver/test_client/get_view/')
+
+ # For all possible True/False combinations of follow and secure
+ for follow, secure in itertools.product([True, False], repeat=2):
+ # always redirects to https
+ response = self.client.get('/test_client/https_redirect_view/', follow=follow, secure=secure)
+ # no scheme to compare too, always succeeds
+ self.assertRedirects(response, '/test_client/secure_view/', status_code=301)
+ # the goal scheme is https
+ self.assertRedirects(response, 'https://testserver/test_client/secure_view/', status_code=301)
+ with self.assertRaises(AssertionError):
+ self.assertRedirects(response, 'http://testserver/test_client/secure_view/', status_code=301)
+
class AssertFormErrorTests(TestCase):
def test_unknown_form(self):
Please sign in to comment.
Something went wrong with that request. Please try again.