diff --git a/django/test/client.py b/django/test/client.py index 12753d2eac..c3e221554f 100644 --- a/django/test/client.py +++ b/django/test/client.py @@ -182,6 +182,10 @@ class Client: if self.exc_info: raise self.exc_info[1], None, self.exc_info[2] + # Save the client and request that stimulated the response + response.client = self + response.request = request + # Add any rendered template detail to the response # If there was only one template rendered (the most likely case), # flatten the list to a single element diff --git a/django/test/testcases.py b/django/test/testcases.py index 2ed2e9ba26..400d66cfab 100644 --- a/django/test/testcases.py +++ b/django/test/testcases.py @@ -80,7 +80,9 @@ class TestCase(unittest.TestCase): self.assertEqual(url, expected_url, "Response redirected to '%s', expected '%s'" % (url, expected_url)) - redirect_response = self.client.get(path, QueryDict(query)) + # Get the redirection page, using the same client that was used + # to obtain the original response. + redirect_response = response.client.get(path, QueryDict(query)) self.assertEqual(redirect_response.status_code, target_status_code, "Couldn't retrieve redirection page '%s': response code was %d (expected %d)" % (path, redirect_response.status_code, target_status_code)) diff --git a/docs/testing.txt b/docs/testing.txt index bb62273bea..22a7e48a7a 100644 --- a/docs/testing.txt +++ b/docs/testing.txt @@ -577,13 +577,25 @@ Specifically, a ``Response`` object has the following attributes: =============== ========================================================== Attribute Description =============== ========================================================== - ``status_code`` The HTTP status of the response, as an integer. See - RFC2616_ for a full list of HTTP status codes. + ``client`` The test client that was used to make the request that + resulted in the response. ``content`` The body of the response, as a string. This is the final page content as rendered by the view, or any error message (such as the URL for a 302 redirect). + ``context`` The template ``Context`` instance that was used to render + the template that produced the response content. + + If the rendered page used multiple templates, then + ``context`` will be a list of ``Context`` + objects, in the order in which they were rendered. + + ``request`` The request data that stimulated the response. + + ``status_code`` The HTTP status of the response, as an integer. See + RFC2616_ for a full list of HTTP status codes. + ``template`` The ``Template`` instance that was used to render the final content. Use ``template.name`` to get the template's file name, if the template was loaded from a @@ -594,13 +606,6 @@ Specifically, a ``Response`` object has the following attributes: using `template inheritance`_ -- then ``template`` will be a list of ``Template`` instances, in the order in which they were rendered. - - ``context`` The template ``Context`` instance that was used to render - the template that produced the response content. - - As with ``template``, if the rendered page used multiple - templates, then ``context`` will be a list of ``Context`` - objects, in the order in which they were rendered. =============== ========================================================== .. _RFC2616: http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html @@ -828,7 +833,7 @@ useful for testing Web applications: ``assertRedirects(response, expected_url, status_code=302, target_status_code=200)`` Asserts that the response return a ``status_code`` redirect status, - it redirected to ``expected_url`` (including any GET data), and the subsequent + it redirected to ``expected_url`` (including any GET data), and the subsequent page was received with ``target_status_code``. ``assertTemplateUsed(response, template_name)`` diff --git a/tests/modeltests/test_client/models.py b/tests/modeltests/test_client/models.py index 200a71f6f9..2bc1dfe02b 100644 --- a/tests/modeltests/test_client/models.py +++ b/tests/modeltests/test_client/models.py @@ -234,7 +234,8 @@ class ClientTest(TestCase): self.assertRedirects(response, '/accounts/login/?next=/test_client/login_protected_view/') # Log in - self.client.login(username='testclient', password='password') + login = self.client.login(username='testclient', password='password') + self.assertTrue(login, 'Could not log in') # Request a page that requires a login response = self.client.get('/test_client/login_protected_view/') diff --git a/tests/regressiontests/test_client_regress/models.py b/tests/regressiontests/test_client_regress/models.py index e85544f285..aa18a48852 100644 --- a/tests/regressiontests/test_client_regress/models.py +++ b/tests/regressiontests/test_client_regress/models.py @@ -212,7 +212,7 @@ class AssertFormErrorTests(TestCase): except AssertionError, e: self.assertEqual(str(e), "The field 'email' on form 'form' in context 0 does not contain the error 'Some error.' (actual errors: [u'Enter a valid e-mail address.'])") -class AssertFileUploadTests(TestCase): +class FileUploadTests(TestCase): def test_simple_upload(self): fd = open(os.path.join(os.path.dirname(__file__), "views.py")) post_data = { @@ -221,3 +221,22 @@ class AssertFileUploadTests(TestCase): } response = self.client.post('/test_client_regress/file_upload/', post_data) self.assertEqual(response.status_code, 200) + +class LoginTests(TestCase): + fixtures = ['testdata'] + + def test_login_different_client(self): + "Check that using a different test client doesn't violate authentication" + + # Create a second client, and log in. + c = Client() + login = c.login(username='testclient', password='password') + self.assertTrue(login, 'Could not log in') + + # Get a redirection page with the second client. + response = c.get("/test_client_regress/login_protected_redirect_view/") + + # At this points, the self.client isn't logged in. + # Check that assertRedirects uses the original client, not the + # default client. + self.assertRedirects(response, "/test_client_regress/get_view/") diff --git a/tests/regressiontests/test_client_regress/urls.py b/tests/regressiontests/test_client_regress/urls.py index 160f9f992d..e771707f61 100644 --- a/tests/regressiontests/test_client_regress/urls.py +++ b/tests/regressiontests/test_client_regress/urls.py @@ -4,4 +4,6 @@ import views urlpatterns = patterns('', (r'^no_template_view/$', views.no_template_view), (r'^file_upload/$', views.file_upload_view), + (r'^get_view/$', views.get_view), + (r'^login_protected_redirect_view/$', views.login_protected_redirect_view) ) diff --git a/tests/regressiontests/test_client_regress/views.py b/tests/regressiontests/test_client_regress/views.py index d3fbcf8448..75efd212e1 100644 --- a/tests/regressiontests/test_client_regress/views.py +++ b/tests/regressiontests/test_client_regress/views.py @@ -1,5 +1,6 @@ +from django.contrib.auth.decorators import login_required from django.core.mail import EmailMessage, SMTPConnection -from django.http import HttpResponse, HttpResponseServerError +from django.http import HttpResponse, HttpResponseRedirect, HttpResponseServerError from django.shortcuts import render_to_response def no_template_view(request): @@ -18,3 +19,12 @@ def file_upload_view(request): else: return HttpResponseServerError() +def get_view(request): + "A simple login protected view" + return HttpResponse("Hello world") +get_view = login_required(get_view) + +def login_protected_redirect_view(request): + "A view that redirects all requests to the GET view" + return HttpResponseRedirect('/test_client_regress/get_view/') +login_protected_redirect_view = login_required(login_protected_redirect_view) \ No newline at end of file