diff options
| author | Boulder Sprinters <boulder-sprinters@djangoproject.com> | 2007-05-07 15:50:55 +0000 |
|---|---|---|
| committer | Boulder Sprinters <boulder-sprinters@djangoproject.com> | 2007-05-07 15:50:55 +0000 |
| commit | a275d3da8ed8cea8c2c92fc15151f43fb56b42ce (patch) | |
| tree | 9f9a7c291956a17587b898772c5949b7a44864cd /django | |
| parent | 0f22c6a7c8a089e2381a058b4c472cf92699950e (diff) | |
boulder-oracle-sprint: Merged to [5156]
git-svn-id: http://code.djangoproject.com/svn/django/branches/boulder-oracle-sprint@5157 bcc190cf-cafb-0310-a4f2-bffc1f526a37
Diffstat (limited to 'django')
| -rw-r--r-- | django/db/models/query.py | 2 | ||||
| -rw-r--r-- | django/test/client.py | 80 | ||||
| -rw-r--r-- | django/test/testcases.py | 90 |
3 files changed, 129 insertions, 43 deletions
diff --git a/django/db/models/query.py b/django/db/models/query.py index 93dcdd1776..d31ccf003e 100644 --- a/django/db/models/query.py +++ b/django/db/models/query.py @@ -998,7 +998,7 @@ def lookup_inner(path, lookup_type, value, opts, table, column): field_choices(current_opts.get_all_related_many_to_many_objects(), True) + \ field_choices(current_opts.get_all_related_objects(), True) + \ field_choices(current_opts.fields, False) - raise TypeError, "Cannot resolve keyword '%s' into field, choices are: %s" % (name, ", ".join(choices)) + raise TypeError, "Cannot resolve keyword '%s' into field. Choices are: %s" % (name, ", ".join(choices)) # Check whether an intermediate join is required between current_table # and new_table. diff --git a/django/test/client.py b/django/test/client.py index 95d3b85922..c3110f02ec 100644 --- a/django/test/client.py +++ b/django/test/client.py @@ -1,12 +1,16 @@ +import datetime import sys from cStringIO import StringIO from urlparse import urlparse from django.conf import settings +from django.contrib.auth import authenticate, login +from django.contrib.sessions.models import Session +from django.contrib.sessions.middleware import SessionWrapper from django.core.handlers.base import BaseHandler from django.core.handlers.wsgi import WSGIRequest from django.core.signals import got_request_exception from django.dispatch import dispatcher -from django.http import urlencode, SimpleCookie +from django.http import urlencode, SimpleCookie, HttpRequest from django.test import signals from django.utils.functional import curry @@ -113,7 +117,6 @@ class Client: self.handler = ClientHandler() self.defaults = defaults self.cookies = SimpleCookie() - self.session = {} self.exc_info = None def store_exc_info(self, *args, **kwargs): @@ -123,6 +126,15 @@ class Client: """ self.exc_info = sys.exc_info() + def _session(self): + "Obtain the current session variables" + if 'django.contrib.sessions' in settings.INSTALLED_APPS: + cookie = self.cookies.get(settings.SESSION_COOKIE_NAME, None) + if cookie: + return SessionWrapper(cookie.value) + return {} + session = property(_session) + def request(self, **request): """ The master request method. Composes the environment dictionary @@ -171,16 +183,10 @@ class Client: if self.exc_info: raise self.exc_info[1], None, self.exc_info[2] - # Update persistent cookie and session data + # Update persistent cookie data if response.cookies: self.cookies.update(response.cookies) - if 'django.contrib.sessions' in settings.INSTALLED_APPS: - from django.contrib.sessions.middleware import SessionWrapper - cookie = self.cookies.get(settings.SESSION_COOKIE_NAME, None) - if cookie: - self.session = SessionWrapper(cookie.value) - return response def get(self, path, data={}, **extra): @@ -215,42 +221,34 @@ class Client: return self.request(**r) - def login(self, path, username, password, **extra): - """ - A specialized sequence of GET and POST to log into a view that - is protected by a @login_required access decorator. + def login(self, **credentials): + """Set the Client to appear as if it has sucessfully logged into a site. - path should be the URL of the page that is login protected. - - Returns the response from GETting the requested URL after - login is complete. Returns False if login process failed. + Returns True if login is possible; False if the provided credentials + are incorrect, or if the Sessions framework is not available. """ - # First, GET the page that is login protected. - # This page will redirect to the login page. - response = self.get(path) - if response.status_code != 302: - return False + user = authenticate(**credentials) + if user and 'django.contrib.sessions' in settings.INSTALLED_APPS: + obj = Session.objects.get_new_session_object() - _, _, login_path, _, data, _= urlparse(response['Location']) - next = data.split('=')[1] + # Create a fake request to store login details + request = HttpRequest() + request.session = SessionWrapper(obj.session_key) + login(request, user) - # Second, GET the login page; required to set up cookies - response = self.get(login_path, **extra) - if response.status_code != 200: - return False + # Set the cookie to represent the session + self.cookies[settings.SESSION_COOKIE_NAME] = obj.session_key + self.cookies[settings.SESSION_COOKIE_NAME]['max-age'] = None + self.cookies[settings.SESSION_COOKIE_NAME]['path'] = '/' + self.cookies[settings.SESSION_COOKIE_NAME]['domain'] = settings.SESSION_COOKIE_DOMAIN + self.cookies[settings.SESSION_COOKIE_NAME]['secure'] = settings.SESSION_COOKIE_SECURE or None + self.cookies[settings.SESSION_COOKIE_NAME]['expires'] = None - # Last, POST the login data. - form_data = { - 'username': username, - 'password': password, - 'next' : next, - } - response = self.post(login_path, data=form_data, **extra) + # Set the session values + Session.objects.save(obj.session_key, request.session._session, + datetime.datetime.now() + datetime.timedelta(seconds=settings.SESSION_COOKIE_AGE)) - # Login page should 302 redirect to the originally requested page - if (response.status_code != 302 or - urlparse(response['Location'])[2] != path): + return True + else: return False - - # Since we are logged in, request the actual page again - return self.get(path) +
\ No newline at end of file diff --git a/django/test/testcases.py b/django/test/testcases.py index 2bfb9a733a..80f55b20d3 100644 --- a/django/test/testcases.py +++ b/django/test/testcases.py @@ -1,8 +1,10 @@ import re, doctest, unittest +from urlparse import urlparse from django.db import transaction from django.core import management from django.db.models import get_apps - +from django.test.client import Client + normalize_long_ints = lambda s: re.sub(r'(?<![\w])(\d+)L(?![\w])', '\\1', s) class OutputChecker(doctest.OutputChecker): @@ -46,5 +48,91 @@ class TestCase(unittest.TestCase): super(). """ + self.client = Client() self.install_fixtures() super(TestCase, self).run(result) + + def assertRedirects(self, response, expected_path): + """Assert that a response redirected to a specific URL, and that the + redirect URL can be loaded. + + """ + self.assertEqual(response.status_code, 302, + "Response didn't redirect: Reponse code was %d" % response.status_code) + scheme, netloc, path, params, query, fragment = urlparse(response['Location']) + self.assertEqual(path, expected_path, + "Response redirected to '%s', expected '%s'" % (path, expected_path)) + redirect_response = self.client.get(path) + self.assertEqual(redirect_response.status_code, 200, + "Couldn't retrieve redirection page '%s'" % path) + + def assertContains(self, response, text, count=1): + """Assert that a response indicates that a page was retreived successfully, + (i.e., the HTTP status code was 200), and that ``text`` occurs ``count`` + times in the content of the response. + + """ + self.assertEqual(response.status_code, 200, + "Couldn't retrieve page'") + real_count = response.content.count(text) + self.assertEqual(real_count, count, + "Could only find %d of %d instances of '%s' in response" % (real_count, count, text)) + + def assertFormError(self, response, form, field, errors): + "Assert that a form used to render the response has a specific field error" + if not response.context: + self.fail('Response did not use any contexts to render the response') + + # If there is a single context, put it into a list to simplify processing + if not isinstance(response.context, list): + contexts = [response.context] + else: + contexts = response.context + + # If a single error string is provided, make it a list to simplify processing + if not isinstance(errors, list): + errors = [errors] + + # Search all contexts for the error. + found_form = False + for i,context in enumerate(contexts): + if form in context: + found_form = True + try: + for err in errors: + if field: + self.assertTrue(err in context[form].errors[field], + "The field '%s' on form '%s' in context %d does not contain the error '%s' (actual errors: %s)" % + (field, form, i, err, list(context[form].errors[field]))) + else: + self.assertTrue(err in context[form].non_field_errors(), + "The form '%s' in context %d does not contain the non-field error '%s' (actual errors: %s)" % + (form, i, err, list(context[form].non_field_errors()))) + except KeyError: + self.fail("The form '%s' in context %d does not contain the field '%s'" % (form, i, field)) + if not found_form: + self.fail("The form '%s' was not used to render the response" % form) + + def assertTemplateUsed(self, response, template_name): + "Assert that the template with the provided name was used in rendering the response" + if isinstance(response.template, list): + template_names = [t.name for t in response.template] + self.assertTrue(template_name in template_names, + "Template '%s' was not one of the templates used to render the response. Templates used: %s" % + (template_name, template_names)) + elif response.template: + self.assertEqual(template_name, response.template.name, + "Template '%s' was not used to render the response. Actual template was '%s'" % + (template_name, response.template.name)) + else: + self.fail('No templates used to render the response') + + def assertTemplateNotUsed(self, response, template_name): + "Assert that the template with the provided name was NOT used in rendering the response" + if isinstance(response.template, list): + self.assertFalse(template_name in [t.name for t in response.template], + "Template '%s' was used unexpectedly in rendering the response" % template_name) + elif response.template: + self.assertNotEqual(template_name, response.template.name, + "Template '%s' was used unexpectedly in rendering the response" % template_name) +
\ No newline at end of file |
