summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorUnai Zalakain <unai@gisa-elkartea.org>2013-10-29 18:31:54 +0100
committerAnssi Kääriäinen <akaariai@gmail.com>2013-11-19 09:04:20 +0200
commit4fdd51b73240bf9c8d9472fcc45df699f0714755 (patch)
tree50e7cb8ea392bce529da22eb84a22b95a4220382
parent9348fc5628ccbbe156e9523b5eb8ba3ce783166e (diff)
Fixed #15179 -- middlewares not applied for test client login()
Requests made with django.test.Client.login() and logout() respect defaults defined in django.test.Client instantiation and are processed through middleware. Thanks to Loic for the reviews.
-rw-r--r--django/test/client.py22
-rw-r--r--docs/releases/1.7.txt5
-rw-r--r--docs/topics/testing/overview.txt14
-rw-r--r--tests/test_client_regress/tests.py44
4 files changed, 79 insertions, 6 deletions
diff --git a/django/test/client.py b/django/test/client.py
index c916b7dbe0..bf099e5b37 100644
--- a/django/test/client.py
+++ b/django/test/client.py
@@ -15,7 +15,7 @@ from django.core.handlers.wsgi import WSGIRequest
from django.core.signals import (request_started, request_finished,
got_request_exception)
from django.db import close_old_connections
-from django.http import SimpleCookie, HttpRequest, QueryDict
+from django.http import SimpleCookie, QueryDict
from django.template import TemplateDoesNotExist
from django.test import signals
from django.utils.functional import curry
@@ -83,8 +83,9 @@ def closing_iterator_wrapper(iterable, close):
class ClientHandler(BaseHandler):
"""
A HTTP Handler that can be used for testing purposes.
- Uses the WSGI interface to compose requests, but returns
- the raw HttpResponse object
+ Uses the WSGI interface to compose requests, but returns the raw
+ HttpResponse object with the originating WSGIRequest attached to its
+ ``request_instance`` attribute.
"""
def __init__(self, enforce_csrf_checks=True, *args, **kwargs):
self.enforce_csrf_checks = enforce_csrf_checks
@@ -105,7 +106,13 @@ class ClientHandler(BaseHandler):
# required for backwards compatibility with external tests against
# admin views.
request._dont_enforce_csrf_checks = not self.enforce_csrf_checks
+
+ # Request goes through middleware.
response = self.get_response(request)
+ # Attach the originating request to the response so that it could be
+ # later retrieved.
+ response.request_instance = request
+
# We're emulating a WSGI server; we must call the close method
# on completion.
if response.streaming:
@@ -546,8 +553,9 @@ class Client(RequestFactory):
'django.contrib.sessions' in settings.INSTALLED_APPS):
engine = import_module(settings.SESSION_ENGINE)
- # Create a fake request to store login details.
- request = HttpRequest()
+ # Create a fake request that goes through request middleware
+ request = self.request().request_instance
+
if self.session:
request.session = self.session
else:
@@ -579,7 +587,9 @@ class Client(RequestFactory):
Causes the authenticated user to be logged out.
"""
- request = HttpRequest()
+ # Create a fake request that goes through request middleware
+ request = self.request().request_instance
+
engine = import_module(settings.SESSION_ENGINE)
UserModel = get_user_model()
if self.session:
diff --git a/docs/releases/1.7.txt b/docs/releases/1.7.txt
index 8428c1853a..749a843a5a 100644
--- a/docs/releases/1.7.txt
+++ b/docs/releases/1.7.txt
@@ -496,6 +496,11 @@ Tests
:class:`~django.test.Client`. If ``True``, the request will be made
through HTTPS.
+* Requests made with :meth:`Client.login() <django.test.Client.login>` and
+ :meth:`Client.logout() <django.test.Client.logout>` respect defaults defined
+ in :class:`~django.test.Client` instantiation and are processed through
+ middleware.
+
Backwards incompatible changes in 1.7
=====================================
diff --git a/docs/topics/testing/overview.txt b/docs/topics/testing/overview.txt
index 133931559e..c221702005 100644
--- a/docs/topics/testing/overview.txt
+++ b/docs/topics/testing/overview.txt
@@ -663,6 +663,13 @@ Use the ``django.test.Client`` class to make requests.
:meth:`~django.contrib.auth.models.UserManager.create_user` helper
method to create a new user with a correctly hashed password.
+ .. versionadded:: 1.7
+
+ Requests made with :meth:`~django.test.Client.login` go through the
+ request middleware. If you need to control the environment, you can
+ do so at :class:`~django.test.Client` instantiation or with the
+ `Client.defaults` attribute.
+
.. method:: Client.logout()
If your site uses Django's :doc:`authentication system</topics/auth/index>`,
@@ -673,6 +680,13 @@ Use the ``django.test.Client`` class to make requests.
and session data cleared to defaults. Subsequent requests will appear
to come from an :class:`~django.contrib.auth.models.AnonymousUser`.
+ .. versionadded:: 1.7
+
+ Requests made with :meth:`~django.test.Client.logout` go through the
+ request middleware. If you need to control the environment, you can
+ do so at :class:`~django.test.Client` instantiation or with the
+ `Client.defaults` attribute.
+
Testing responses
~~~~~~~~~~~~~~~~~
diff --git a/tests/test_client_regress/tests.py b/tests/test_client_regress/tests.py
index 5f907925ba..1bee0b95e7 100644
--- a/tests/test_client_regress/tests.py
+++ b/tests/test_client_regress/tests.py
@@ -7,6 +7,7 @@ from __future__ import unicode_literals
import os
import itertools
+from django.conf import settings
from django.core.urlresolvers import reverse
from django.template import (TemplateSyntaxError,
Context, Template, loader)
@@ -761,6 +762,11 @@ class AssertFormsetErrorTests(TestCase):
**kwargs)
+class ProcessedMiddleware(object):
+ def process_request(self, request):
+ request.has_been_processed = True
+
+
@override_settings(PASSWORD_HASHERS=('django.contrib.auth.hashers.SHA1PasswordHasher',))
class LoginTests(TestCase):
fixtures = ['testdata']
@@ -781,6 +787,24 @@ class LoginTests(TestCase):
# default client.
self.assertRedirects(response, "http://testserver/test_client_regress/get_view/")
+ @override_settings(
+ MIDDLEWARE_CLASSES=list(settings.MIDDLEWARE_CLASSES) +
+ ['test_client_regress.tests.ProcessedMiddleware'])
+ def test_request_middleware(self):
+ "Check that the request middleware is executed on login request"
+
+ def listener(sender, signal, **kwargs):
+ request = kwargs['request']
+ self.assertTrue(hasattr(request, 'has_been_processed'))
+
+ # Unlike other Client request performing methods, login and logout don't
+ # return the response, therefore we must use signals to get it
+ user_logged_in.connect(listener)
+ try:
+ self.client.login(username='testclient', password='password')
+ finally:
+ user_logged_in.disconnect(listener)
+
@override_settings(
PASSWORD_HASHERS=('django.contrib.auth.hashers.SHA1PasswordHasher',),
@@ -1260,12 +1284,32 @@ class UploadedFileEncodingTest(TestCase):
class RequestHeadersTest(TestCase):
+ fixtures = ['testdata']
+
def test_client_headers(self):
"A test client can receive custom headers"
response = self.client.get("/test_client_regress/check_headers/", HTTP_X_ARG_CHECK='Testing 123')
self.assertEqual(response.content, b"HTTP_X_ARG_CHECK: Testing 123")
self.assertEqual(response.status_code, 200)
+ @override_settings(PASSWORD_HASHERS=('django.contrib.auth.hashers.SHA1PasswordHasher',))
+ def test_client_login_headers(self):
+ "Test client headers are used in login"
+
+ client = Client(HTTP_HOST='different')
+
+ def listener(sender, signal, **kwargs):
+ request = kwargs['request']
+ self.assertEqual(request.get_host(), 'different')
+
+ # Unlike other Client request performing methods, login and logout don't
+ # return the response, therefore we must use signals to get it
+ user_logged_in.connect(listener)
+ try:
+ client.login(username='testclient', password='password')
+ finally:
+ user_logged_in.disconnect(listener)
+
def test_client_headers_redirect(self):
"Test client headers are preserved through redirects"
response = self.client.get("/test_client_regress/check_headers_redirect/", follow=True, HTTP_X_ARG_CHECK='Testing 123')