From 30848dfe34bb027c40ae1902623bd2fb675f6424 Mon Sep 17 00:00:00 2001 From: Malcolm Tredinnick Date: Sun, 11 Nov 2007 03:54:21 +0000 Subject: [PATCH] When using assertRedirect(), allow the caller to specify relative URLs and automatically fill in the hostname and scheme (host can be passed in, if different from the default). git-svn-id: http://code.djangoproject.com/svn/django/trunk@6661 bcc190cf-cafb-0310-a4f2-bffc1f526a37 --- django/test/testcases.py | 8 ++- tests/modeltests/test_client/models.py | 97 +++++++++++++------------- 2 files changed, 56 insertions(+), 49 deletions(-) diff --git a/django/test/testcases.py b/django/test/testcases.py index 732e713d4ae..2aa0a0783d2 100644 --- a/django/test/testcases.py +++ b/django/test/testcases.py @@ -1,6 +1,6 @@ import re import unittest -from urlparse import urlsplit +from urlparse import urlsplit, urlunsplit from django.http import QueryDict from django.db import transaction @@ -74,7 +74,7 @@ class TestCase(unittest.TestCase): super(TestCase, self).__call__(result) def assertRedirects(self, response, expected_url, status_code=302, - target_status_code=200): + target_status_code=200, host=None): """Asserts that a response redirected to a specific URL, and that the redirect URL can be loaded. @@ -86,6 +86,10 @@ class TestCase(unittest.TestCase): " (expected %d)" % (response.status_code, status_code))) url = response['Location'] scheme, netloc, path, query, fragment = urlsplit(url) + 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)) self.assertEqual(url, expected_url, "Response redirected to '%s', expected '%s'" % (url, expected_url)) diff --git a/tests/modeltests/test_client/models.py b/tests/modeltests/test_client/models.py index 95f68c67446..c7aaaff67d4 100644 --- a/tests/modeltests/test_client/models.py +++ b/tests/modeltests/test_client/models.py @@ -4,7 +4,7 @@ The test client is a class that can act like a simple browser for testing purposes. - + It allows the user to compose GET and POST requests, and obtain the response that the server gave to those requests. The server Response objects are annotated with the details @@ -15,8 +15,8 @@ Client objects are stateful - they will retain cookie (and thus session) details for the lifetime of the Client instance. This is not intended as a replacement for Twill,Selenium, or -other browser automation frameworks - it is here to allow -testing against the contexts and templates produced by a view, +other browser automation frameworks - it is here to allow +testing against the contexts and templates produced by a view, rather than the HTML rendered to the end-user. """ @@ -25,14 +25,14 @@ from django.core import mail class ClientTest(TestCase): fixtures = ['testdata.json'] - + def test_get_view(self): "GET a view" # The data is ignored, but let's check it doesn't crash the system # anyway. data = {'var': u'\xf2'} response = self.client.get('/test_client/get_view/', data) - + # Check some response details self.assertContains(response, 'This is a test') self.assertEqual(response.context['var'], u'\xf2') @@ -41,36 +41,36 @@ class ClientTest(TestCase): def test_get_post_view(self): "GET a view that normally expects POSTs" response = self.client.get('/test_client/post_view/', {}) - + # Check some response details self.assertEqual(response.status_code, 200) self.assertEqual(response.template.name, 'Empty GET Template') self.assertTemplateUsed(response, 'Empty GET Template') self.assertTemplateNotUsed(response, 'Empty POST Template') - + def test_empty_post(self): "POST an empty dictionary to a view" response = self.client.post('/test_client/post_view/', {}) - + # Check some response details self.assertEqual(response.status_code, 200) self.assertEqual(response.template.name, 'Empty POST Template') self.assertTemplateNotUsed(response, 'Empty GET Template') self.assertTemplateUsed(response, 'Empty POST Template') - + def test_post(self): "POST some data to a view" post_data = { 'value': 37 } response = self.client.post('/test_client/post_view/', post_data) - + # Check some response details self.assertEqual(response.status_code, 200) self.assertEqual(response.context['data'], '37') self.assertEqual(response.template.name, 'POST Template') self.failUnless('Data received' in response.content) - + def test_raw_post(self): "POST raw data (with a content type) to a view" test_doc = """BlinkMalcolm Gladwell""" @@ -83,18 +83,21 @@ class ClientTest(TestCase): def test_redirect(self): "GET a URL that redirects elsewhere" response = self.client.get('/test_client/redirect_view/') - # Check that the response was a 302 (redirect) - self.assertRedirects(response, 'http://testserver/test_client/get_view/') - - client_providing_host = Client(HTTP_HOST='django.testserver') + # Check that the response was a 302 (redirect) and that + # assertRedirect() understands to put an implicit http://testserver/ in + # front of non-absolute URLs. + self.assertRedirects(response, '/test_client/get_view/') + + host = 'django.testserver' + client_providing_host = Client(HTTP_HOST=host) response = client_providing_host.get('/test_client/redirect_view/') # Check that the response was a 302 (redirect) with absolute URI - self.assertRedirects(response, 'http://django.testserver/test_client/get_view/') - + self.assertRedirects(response, '/test_client/get_view/', host=host) + def test_redirect_with_query(self): "GET a URL that redirects with given GET parameters" response = self.client.get('/test_client/redirect_view/', {'var': 'value'}) - + # Check if parameters are intact self.assertRedirects(response, 'http://testserver/test_client/get_view/?var=value') @@ -112,7 +115,7 @@ class ClientTest(TestCase): def test_redirect_to_strange_location(self): "GET a URL that redirects to a non-200 page" response = self.client.get('/test_client/double_redirect_view/') - + # Check that the response was a 302, and that # the attempt to get the redirection location returned 301 when retrieved self.assertRedirects(response, 'http://testserver/test_client/permanent_redirect_view/', target_status_code=301) @@ -120,7 +123,7 @@ class ClientTest(TestCase): def test_notfound_response(self): "GET a URL that responds as '404:Not Found'" response = self.client.get('/test_client/bad_view/') - + # Check that the response was a 404, and that the content contains MAGIC self.assertContains(response, 'MAGIC', status_code=404) @@ -148,12 +151,12 @@ class ClientTest(TestCase): self.assertTemplateUsed(response, "Form GET Template") # Check that the multi-value data has been rolled out ok self.assertContains(response, 'Select a valid choice.', 0) - + def test_incomplete_data_form(self): "POST incomplete data to a form" post_data = { 'text': 'Hello World', - 'value': 37 + 'value': 37 } response = self.client.post('/test_client/form_view/', post_data) self.assertContains(response, 'This field is required.', 3) @@ -198,7 +201,7 @@ class ClientTest(TestCase): "POST incomplete data to a form using multiple templates" post_data = { 'text': 'Hello World', - 'value': 37 + 'value': 37 } response = self.client.post('/test_client/form_view_with_template/', post_data) self.assertContains(response, 'POST data has errors') @@ -226,21 +229,21 @@ class ClientTest(TestCase): self.assertTemplateNotUsed(response, "Invalid POST Template") self.assertFormError(response, 'form', 'email', 'Enter a valid e-mail address.') - + def test_unknown_page(self): "GET an invalid URL" response = self.client.get('/test_client/unknown_view/') - + # Check that the response was a 404 self.assertEqual(response.status_code, 404) - + def test_view_with_login(self): "Request a page that is protected with @login_required" - + # Get the page without logging in. Should result in 302. response = self.client.get('/test_client/login_protected_view/') self.assertRedirects(response, 'http://testserver/accounts/login/?next=/test_client/login_protected_view/') - + # Log in login = self.client.login(username='testclient', password='password') self.failUnless(login, 'Could not log in') @@ -252,11 +255,11 @@ class ClientTest(TestCase): def test_view_with_method_login(self): "Request a page that is protected with a @login_required method" - + # Get the page without logging in. Should result in 302. response = self.client.get('/test_client/login_protected_method_view/') self.assertRedirects(response, 'http://testserver/accounts/login/?next=/test_client/login_protected_method_view/') - + # Log in login = self.client.login(username='testclient', password='password') self.failUnless(login, 'Could not log in') @@ -268,7 +271,7 @@ class ClientTest(TestCase): def test_view_with_login_and_custom_redirect(self): "Request a page that is protected with @login_required(redirect_field_name='redirect_to')" - + # Get the page without logging in. Should result in 302. response = self.client.get('/test_client/login_protected_view_custom_redirect/') self.assertRedirects(response, 'http://testserver/accounts/login/?redirect_to=/test_client/login_protected_view_custom_redirect/') @@ -313,11 +316,11 @@ class ClientTest(TestCase): def test_view_with_permissions(self): "Request a page that is protected with @permission_required" - + # Get the page without logging in. Should result in 302. response = self.client.get('/test_client/permission_protected_view/') self.assertRedirects(response, 'http://testserver/accounts/login/?next=/test_client/permission_protected_view/') - + # Log in login = self.client.login(username='testclient', password='password') self.failUnless(login, 'Could not log in') @@ -330,11 +333,11 @@ class ClientTest(TestCase): def test_view_with_method_permissions(self): "Request a page that is protected with a @permission_required method" - + # Get the page without logging in. Should result in 302. response = self.client.get('/test_client/permission_protected_method_view/') self.assertRedirects(response, 'http://testserver/accounts/login/?next=/test_client/permission_protected_method_view/') - + # Log in login = self.client.login(username='testclient', password='password') self.failUnless(login, 'Could not log in') @@ -353,53 +356,53 @@ class ClientTest(TestCase): self.fail("Shouldn't have a session value") except KeyError: pass - + from django.contrib.sessions.models import Session response = self.client.post('/test_client/session_view/') - + # Check that the session was modified self.assertEquals(self.client.session['tobacconist'], 'hovercraft') def test_view_with_exception(self): "Request a page that is known to throw an error" self.assertRaises(KeyError, self.client.get, "/test_client/broken_view/") - + #Try the same assertion, a different way try: self.client.get('/test_client/broken_view/') self.fail('Should raise an error') except KeyError: pass - + def test_mail_sending(self): "Test that mail is redirected to a dummy outbox during test setup" - + response = self.client.get('/test_client/mail_sending_view/') self.assertEqual(response.status_code, 200) - + self.assertEqual(len(mail.outbox), 1) self.assertEqual(mail.outbox[0].subject, 'Test message') self.assertEqual(mail.outbox[0].body, 'This is a test email') - self.assertEqual(mail.outbox[0].from_email, 'from@example.com') + self.assertEqual(mail.outbox[0].from_email, 'from@example.com') self.assertEqual(mail.outbox[0].to[0], 'first@example.com') self.assertEqual(mail.outbox[0].to[1], 'second@example.com') def test_mass_mail_sending(self): "Test that mass mail is redirected to a dummy outbox during test setup" - + response = self.client.get('/test_client/mass_mail_sending_view/') self.assertEqual(response.status_code, 200) - + self.assertEqual(len(mail.outbox), 2) self.assertEqual(mail.outbox[0].subject, 'First Test message') self.assertEqual(mail.outbox[0].body, 'This is the first test email') - self.assertEqual(mail.outbox[0].from_email, 'from@example.com') + self.assertEqual(mail.outbox[0].from_email, 'from@example.com') self.assertEqual(mail.outbox[0].to[0], 'first@example.com') self.assertEqual(mail.outbox[0].to[1], 'second@example.com') self.assertEqual(mail.outbox[1].subject, 'Second Test message') self.assertEqual(mail.outbox[1].body, 'This is the second test email') - self.assertEqual(mail.outbox[1].from_email, 'from@example.com') + self.assertEqual(mail.outbox[1].from_email, 'from@example.com') self.assertEqual(mail.outbox[1].to[0], 'second@example.com') self.assertEqual(mail.outbox[1].to[1], 'third@example.com') - +