Selaa lähdekoodia

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.
Tim Graham 11 vuotta sitten
vanhempi
commit
a35ed20241

+ 12 - 6
django/test/client.py

@@ -13,7 +13,7 @@ except ImportError:     # Python 2
     from urlparse import urlparse, urlsplit
 
 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.wsgi import WSGIRequest
 from django.core.signals import (request_started, request_finished,
@@ -571,11 +571,17 @@ class Client(RequestFactory):
 
         Causes the authenticated user to be logged out.
         """
-        session = import_module(settings.SESSION_ENGINE).SessionStore()
-        session_cookie = self.cookies.get(settings.SESSION_COOKIE_NAME)
-        if session_cookie:
-            session.delete(session_key=session_cookie.value)
-        self.cookies = SimpleCookie()
+        request = HttpRequest()
+        engine = import_module(settings.SESSION_ENGINE)
+        UserModel = get_user_model()
+        if self.session:
+            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):
         "Follows any redirects by requesting responses from the server using GET."

+ 4 - 0
docs/releases/1.6.txt

@@ -623,6 +623,10 @@ Miscellaneous
   raises NoReverseMatch. There is no change to {% url %} tag, it causes
   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
 ==========================
 

+ 1 - 1
docs/topics/testing/overview.txt

@@ -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
         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
 ~~~~~~~~~~~~~~~~~

+ 12 - 0
tests/test_client_regress/models.py

@@ -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'

+ 73 - 0
tests/test_client_regress/tests.py

@@ -17,7 +17,10 @@ from django.template.response import SimpleTemplateResponse
 from django.utils._os import upath
 from django.utils.translation import ugettext_lazy
 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
 
 @override_settings(
@@ -961,6 +964,76 @@ class SessionTests(TestCase):
         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):
     def test_get(self):
         "Request a view via request method GET"