Changeset 5152
- Timestamp:
- 05/05/07 10:16:15 (1 year ago)
- Files:
-
- django/trunk/django/test/client.py (modified) (5 diffs)
- django/trunk/docs/testing.txt (modified) (1 diff)
- django/trunk/tests/modeltests/test_client/models.py (modified) (1 diff)
Legend:
- Unmodified
- Added
- Removed
- Modified
- Copied
- Moved
django/trunk/django/test/client.py
r4774 r5152 1 import datetime 1 2 import sys 2 3 from cStringIO import StringIO 3 4 from urlparse import urlparse 4 5 from django.conf import settings 6 from django.contrib.auth import authenticate, login 7 from django.contrib.sessions.models import Session 8 from django.contrib.sessions.middleware import SessionWrapper 5 9 from django.core.handlers.base import BaseHandler 6 10 from django.core.handlers.wsgi import WSGIRequest 7 11 from django.core.signals import got_request_exception 8 12 from django.dispatch import dispatcher 9 from django.http import urlencode, SimpleCookie 13 from django.http import urlencode, SimpleCookie, HttpRequest 10 14 from django.test import signals 11 15 from django.utils.functional import curry … … 114 118 self.defaults = defaults 115 119 self.cookies = SimpleCookie() 116 self.session = {}117 120 self.exc_info = None 118 121 … … 124 127 self.exc_info = sys.exc_info() 125 128 129 def _session(self): 130 "Obtain the current session variables" 131 if 'django.contrib.sessions' in settings.INSTALLED_APPS: 132 cookie = self.cookies.get(settings.SESSION_COOKIE_NAME, None) 133 if cookie: 134 return SessionWrapper(cookie.value) 135 return {} 136 session = property(_session) 137 126 138 def request(self, **request): 127 139 """ … … 172 184 raise self.exc_info[1], None, self.exc_info[2] 173 185 174 # Update persistent cookie and sessiondata186 # Update persistent cookie data 175 187 if response.cookies: 176 188 self.cookies.update(response.cookies) 177 189 178 if 'django.contrib.sessions' in settings.INSTALLED_APPS:179 from django.contrib.sessions.middleware import SessionWrapper180 cookie = self.cookies.get(settings.SESSION_COOKIE_NAME, None)181 if cookie:182 self.session = SessionWrapper(cookie.value)183 184 190 return response 185 191 … … 216 222 return self.request(**r) 217 223 218 def login(self, path, username, password, **extra): 219 """ 220 A specialized sequence of GET and POST to log into a view that 221 is protected by a @login_required access decorator. 222 223 path should be the URL of the page that is login protected. 224 225 Returns the response from GETting the requested URL after 226 login is complete. Returns False if login process failed. 227 """ 228 # First, GET the page that is login protected. 229 # This page will redirect to the login page. 230 response = self.get(path) 231 if response.status_code != 302: 224 def login(self, **credentials): 225 """Set the Client to appear as if it has sucessfully logged into a site. 226 227 Returns True if login is possible; False if the provided credentials 228 are incorrect, or if the Sessions framework is not available. 229 """ 230 user = authenticate(**credentials) 231 if user and 'django.contrib.sessions' in settings.INSTALLED_APPS: 232 obj = Session.objects.get_new_session_object() 233 234 # Create a fake request to store login details 235 request = HttpRequest() 236 request.session = SessionWrapper(obj.session_key) 237 login(request, user) 238 239 # Set the cookie to represent the session 240 self.cookies[settings.SESSION_COOKIE_NAME] = obj.session_key 241 self.cookies[settings.SESSION_COOKIE_NAME]['max-age'] = None 242 self.cookies[settings.SESSION_COOKIE_NAME]['path'] = '/' 243 self.cookies[settings.SESSION_COOKIE_NAME]['domain'] = settings.SESSION_COOKIE_DOMAIN 244 self.cookies[settings.SESSION_COOKIE_NAME]['secure'] = settings.SESSION_COOKIE_SECURE or None 245 self.cookies[settings.SESSION_COOKIE_NAME]['expires'] = None 246 247 # Set the session values 248 Session.objects.save(obj.session_key, request.session._session, 249 datetime.datetime.now() + datetime.timedelta(seconds=settings.SESSION_COOKIE_AGE)) 250 251 return True 252 else: 232 253 return False 233 234 _, _, login_path, _, data, _= urlparse(response['Location']) 235 next = data.split('=')[1] 236 237 # Second, GET the login page; required to set up cookies 238 response = self.get(login_path, **extra) 239 if response.status_code != 200: 240 return False 241 242 # Last, POST the login data. 243 form_data = { 244 'username': username, 245 'password': password, 246 'next' : next, 247 } 248 response = self.post(login_path, data=form_data, **extra) 249 250 # Login page should 302 redirect to the originally requested page 251 if (response.status_code != 302 or 252 urlparse(response['Location'])[2] != path): 253 return False 254 255 # Since we are logged in, request the actual page again 256 return self.get(path) 254 django/trunk/docs/testing.txt
r5150 r5152 247 247 need to manually close the file after it has been provided to the POST. 248 248 249 ``login(path, username, password)`` 250 In a production site, it is likely that some views will be protected with 251 the @login_required decorator provided by ``django.contrib.auth``. Interacting 252 with a URL that has been login protected is a slightly complex operation, 253 so the Test Client provides a simple method to automate the login process. A 254 call to ``login()`` stimulates the series of GET and POST calls required 255 to log a user into a @login_required protected view. 256 257 If login is possible, the final return value of ``login()`` is the response 258 that is generated by issuing a GET request on the protected URL. If login 259 is not possible, ``login()`` returns False. 260 249 ``login(**credentials)`` 250 ** New in Django development version ** 251 252 On a production site, it is likely that some views will be protected from 253 anonymous access through the use of the @login_required decorator, or some 254 other login checking mechanism. The ``login()`` method can be used to 255 simulate the effect of a user logging into the site. As a result of calling 256 this method, the Client will have all the cookies and session data required 257 to pass any login-based tests that may form part of a view. 258 259 In most cases, the ``credentials`` required by this method are the username 260 and password of the user that wants to log in, provided as keyword 261 arguments:: 262 263 c = Client() 264 c.login(username='fred', password='secret') 265 # Now you can access a login protected view 266 267 If you are using a different authentication backend, this method may 268 require different credentials. 269 270 ``login()`` returns ``True`` if it the credentials were accepted and login 271 was successful. 272 261 273 Note that since the test suite will be executed using the test database, 262 which contains no users by default. As a result, logins for your production 263 site will not work. You will need to create users as part of the test suite 264 to be able to test logins to your application. 274 which contains no users by default. As a result, logins that are valid 275 on your production site will not work under test conditions. You will 276 need to create users as part of the test suite (either manually, or 277 using a test fixture). 265 278 266 279 Testing Responses django/trunk/tests/modeltests/test_client/models.py
r5150 r5152 128 128 self.assertRedirects(response, '/accounts/login/') 129 129 130 # Log in 131 self.client.login(username='testclient', password='password') 132 130 133 # Request a page that requires a login 131 response = self.client.login('/test_client/login_protected_view/', 'testclient', 'password') 132 self.failUnless(response) 134 response = self.client.get('/test_client/login_protected_view/') 133 135 self.assertEqual(response.status_code, 200) 134 136 self.assertEqual(response.context['user'].username, 'testclient') 135 self.assertEqual(response.template.name, 'Login Template')136 137 137 138 def test_view_with_bad_login(self): 138 139 "Request a page that is protected with @login, but use bad credentials" 139 140 140 response = self.client.login('/test_client/login_protected_view/', 'otheruser','nopassword')141 self.failIf( response)141 login = self.client.login(username='otheruser', password='nopassword') 142 self.failIf(login) 142 143 143 144 def test_session_modifying_view(self):
