فهرست منبع

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 سال پیش
والد
کامیت
a35ed20241
5فایلهای تغییر یافته به همراه102 افزوده شده و 7 حذف شده
  1. 12 6
      django/test/client.py
  2. 4 0
      docs/releases/1.6.txt
  3. 1 1
      docs/topics/testing/overview.txt
  4. 12 0
      tests/test_client_regress/models.py
  5. 73 0
      tests/test_client_regress/tests.py

+ 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"