Fixed #18924 -- Made test.Client.logout send user_logged_out signal.

Thanks awsum for the suggestion and Pavel Ponomarev and
Florian Hahn for the patch.
This commit is contained in:
Tim Graham 2013-06-04 12:37:44 -04:00
parent e71b63e280
commit a35ed20241
5 changed files with 102 additions and 7 deletions

View File

@ -13,7 +13,7 @@ except ImportError: # Python 2
from urlparse import urlparse, urlsplit from urlparse import urlparse, urlsplit
from django.conf import settings from django.conf import settings
from django.contrib.auth import authenticate, login from django.contrib.auth import authenticate, login, logout, get_user_model
from django.core.handlers.base import BaseHandler from django.core.handlers.base import BaseHandler
from django.core.handlers.wsgi import WSGIRequest from django.core.handlers.wsgi import WSGIRequest
from django.core.signals import (request_started, request_finished, from django.core.signals import (request_started, request_finished,
@ -571,11 +571,17 @@ class Client(RequestFactory):
Causes the authenticated user to be logged out. Causes the authenticated user to be logged out.
""" """
session = import_module(settings.SESSION_ENGINE).SessionStore() request = HttpRequest()
session_cookie = self.cookies.get(settings.SESSION_COOKIE_NAME) engine = import_module(settings.SESSION_ENGINE)
if session_cookie: UserModel = get_user_model()
session.delete(session_key=session_cookie.value) if self.session:
self.cookies = SimpleCookie() request.session = self.session
uid = self.session.get("_auth_user_id")
if uid:
request.user = UserModel._default_manager.get(pk=uid)
else:
request.session = engine.SessionStore()
logout(request)
def _handle_redirects(self, response, **extra): def _handle_redirects(self, response, **extra):
"Follows any redirects by requesting responses from the server using GET." "Follows any redirects by requesting responses from the server using GET."

View File

@ -623,6 +623,10 @@ Miscellaneous
raises NoReverseMatch. There is no change to {% url %} tag, it causes raises NoReverseMatch. There is no change to {% url %} tag, it causes
template rendering to fail like always when NoReverseMatch is risen. template rendering to fail like always when NoReverseMatch is risen.
* :meth:`django.test.client.Client.logout` now calls
:meth:`django.contrib.auth.logout` which will send the
:func:`~django.contrib.auth.signals.user_logged_out` signal.
Features deprecated in 1.6 Features deprecated in 1.6
========================== ==========================

View File

@ -696,7 +696,7 @@ Use the ``django.test.client.Client`` class to make requests.
After you call this method, the test client will have all the cookies After you call this method, the test client will have all the cookies
and session data cleared to defaults. Subsequent requests will appear and session data cleared to defaults. Subsequent requests will appear
to come from an AnonymousUser. to come from an :class:`~django.contrib.auth.models.AnonymousUser`.
Testing responses Testing responses
~~~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~~~

View File

@ -0,0 +1,12 @@
from django.db import models
from django.contrib.auth.models import AbstractBaseUser, BaseUserManager
class CustomUser(AbstractBaseUser):
email = models.EmailField(verbose_name='email address', max_length=255, unique=True)
custom_objects = BaseUserManager()
USERNAME_FIELD = 'email'
class Meta:
app_label = 'test_client_regress'

View File

@ -17,7 +17,10 @@ from django.template.response import SimpleTemplateResponse
from django.utils._os import upath from django.utils._os import upath
from django.utils.translation import ugettext_lazy from django.utils.translation import ugettext_lazy
from django.http import HttpResponse from django.http import HttpResponse
from django.contrib.auth.signals import user_logged_out, user_logged_in
from django.contrib.auth.models import User
from .models import CustomUser
from .views import CustomTestException from .views import CustomTestException
@override_settings( @override_settings(
@ -961,6 +964,76 @@ class SessionTests(TestCase):
self.client.logout() self.client.logout()
self.client.logout() self.client.logout()
def test_logout_with_user(self):
"""Logout should send user_logged_out signal if user was logged in."""
def listener(*args, **kwargs):
listener.executed = True
self.assertEqual(kwargs['sender'], User)
listener.executed = False
user_logged_out.connect(listener)
self.client.login(username='testclient', password='password')
self.client.logout()
user_logged_out.disconnect(listener)
self.assertTrue(listener.executed)
@override_settings(AUTH_USER_MODEL='test_client_regress.CustomUser')
def test_logout_with_custom_user(self):
"""Logout should send user_logged_out signal if custom user was logged in."""
def listener(*args, **kwargs):
self.assertEqual(kwargs['sender'], CustomUser)
listener.executed = True
listener.executed = False
u = CustomUser.custom_objects.create(email='test@test.com')
u.set_password('password')
u.save()
user_logged_out.connect(listener)
self.client.login(username='test@test.com', password='password')
self.client.logout()
user_logged_out.disconnect(listener)
self.assertTrue(listener.executed)
def test_logout_without_user(self):
"""Logout should send signal even if user not authenticated."""
def listener(user, *args, **kwargs):
listener.user = user
listener.executed = True
listener.executed = False
user_logged_out.connect(listener)
self.client.login(username='incorrect', password='password')
self.client.logout()
user_logged_out.disconnect(listener)
self.assertTrue(listener.executed)
self.assertIsNone(listener.user)
def test_login_with_user(self):
"""Login should send user_logged_in signal on successful login."""
def listener(*args, **kwargs):
listener.executed = True
listener.executed = False
user_logged_in.connect(listener)
self.client.login(username='testclient', password='password')
user_logged_out.disconnect(listener)
self.assertTrue(listener.executed)
def test_login_without_signal(self):
"""Login shouldn't send signal if user wasn't logged in"""
def listener(*args, **kwargs):
listener.executed = True
listener.executed = False
user_logged_in.connect(listener)
self.client.login(username='incorrect', password='password')
user_logged_in.disconnect(listener)
self.assertFalse(listener.executed)
class RequestMethodTests(TestCase): class RequestMethodTests(TestCase):
def test_get(self): def test_get(self):
"Request a view via request method GET" "Request a view via request method GET"