Code

Ticket #10899: 10899_at_r16086.diff

File 10899_at_r16086.diff, 6.0 KB (added by prestontimmons, 3 years ago)

Updated patch against r16086

Line 
1diff --git a/django/test/client.py b/django/test/client.py
2index 5cbc0ca..ea4d9ff 100644
3--- a/django/test/client.py
4+++ b/django/test/client.py
5@@ -345,6 +345,7 @@ class Client(RequestFactory):
6         super(Client, self).__init__(**defaults)
7         self.handler = ClientHandler(enforce_csrf_checks)
8         self.exc_info = None
9+        self._session_store = None
10 
11     def store_exc_info(self, **kwargs):
12         """
13@@ -356,15 +357,25 @@ class Client(RequestFactory):
14         """
15         Obtains the current session variables.
16         """
17+        if self._session_store:
18+            return self._session_store
19+
20         if 'django.contrib.sessions' in settings.INSTALLED_APPS:
21             engine = import_module(settings.SESSION_ENGINE)
22-            cookie = self.cookies.get(settings.SESSION_COOKIE_NAME, None)
23+            cookie = self.cookies.get(settings.SESSION_COOKIE_NAME)
24             if cookie:
25-                return engine.SessionStore(cookie.value)
26-        return {}
27+                session_store = engine.SessionStore(cookie.value)
28+            else:
29+                session_store = engine.SessionStore()
30+                session_store.save()
31+                self.cookies[settings.SESSION_COOKIE_NAME] = \
32+                     session_store.session_key
33+            self._session_store = session_store
34+            return session_store
35+        else:
36+            return {}
37     session = property(_session)
38 
39-
40     def request(self, **request):
41         """
42         The master request method. Composes the environment dictionary
43@@ -374,6 +385,15 @@ class Client(RequestFactory):
44         """
45         environ = self._base_environ(**request)
46 
47+        if hasattr(self.session, "save"):
48+            # Save session modifications and update the session cookie since
49+            # the session key may change over login or logout. Also, force
50+            # the session to be reloaded on next access.
51+            self.session.save()
52+            self.cookies[settings.SESSION_COOKIE_NAME] = \
53+                self.session.session_key
54+            self._session_store = None
55+
56         # Curry a data dictionary into an instance of the template renderer
57         # callback function.
58         data = {}
59@@ -505,14 +525,10 @@ class Client(RequestFactory):
60         user = authenticate(**credentials)
61         if user and user.is_active \
62                 and 'django.contrib.sessions' in settings.INSTALLED_APPS:
63-            engine = import_module(settings.SESSION_ENGINE)
64 
65             # Create a fake request to store login details.
66             request = HttpRequest()
67-            if self.session:
68-                request.session = self.session
69-            else:
70-                request.session = engine.SessionStore()
71+            request.session = self.session
72             login(request, user)
73 
74             # Save the session values.
75@@ -545,6 +561,7 @@ class Client(RequestFactory):
76         if session_cookie:
77             session.delete(session_key=session_cookie.value)
78         self.cookies = SimpleCookie()
79+        self._session_store = None
80 
81     def _handle_redirects(self, response, **extra):
82         "Follows any redirects by requesting responses from the server using GET."
83diff --git a/docs/topics/testing.txt b/docs/topics/testing.txt
84index fb9f6e5..005a336 100644
85--- a/docs/topics/testing.txt
86+++ b/docs/topics/testing.txt
87@@ -1009,6 +1009,15 @@ can access these properties as part of a test condition.
88             session['somekey'] = 'test'
89             session.save()
90 
91+.. versionadded:: Development
92+
93+    Similar to normal Django sessions, you can manipulate sessions directly.
94+    The modified values will be saved on subsequent requests.
95+
96+        def test_something(self):
97+            self.client.session['somekey'] = value
98+            self.client.session['anotherkey'] = value
99+
100 .. _Cookie module documentation: http://docs.python.org/library/cookie.html
101 
102 Example
103diff --git a/tests/regressiontests/test_client_regress/models.py b/tests/regressiontests/test_client_regress/models.py
104index 6757695..40848a1 100644
105--- a/tests/regressiontests/test_client_regress/models.py
106+++ b/tests/regressiontests/test_client_regress/models.py
107@@ -691,6 +691,39 @@ class SessionTests(TestCase):
108         self.assertEqual(response.status_code, 200)
109         self.assertEqual(response.content, 'YES')
110 
111+    def test_session_manipulation(self):
112+        # Check that the session can be edited as documented before #10899.
113+        session = self.client.session
114+        session["session_var"] = "foo"
115+        session.save()
116+
117+        response = self.client.get('/test_client_regress/check_session/')
118+        self.assertEqual(response.status_code, 200)
119+        self.assertEqual(response.content, 'foo')
120+
121+    def test_direct_session_manipulation(self):
122+        # Add a value to the session
123+        self.client.session['session_var'] = 'bar'
124+        self.assertEqual(self.client.session['session_var'], 'bar')
125+
126+        # Check that the session has been modified
127+        response = self.client.get('/test_client_regress/check_session/')
128+        self.assertEqual(response.status_code, 200)
129+        self.assertEqual(response.content, 'bar')
130+
131+        # Check that the session variable persists over login
132+        # when cycle_key() is called
133+        self.client.login(username='testclient', password='password')
134+        self.assertEqual(self.client.session['session_var'], 'bar')
135+
136+        response = self.client.get('/test_client_regress/check_session/')
137+        self.assertEqual(response.status_code, 200)
138+        self.assertEqual(response.content, 'bar')
139+
140+        # Check that new session is started after logout
141+        self.client.logout()
142+        self.assertEqual(self.client.session.get('session_var'), None)
143+
144     def test_logout(self):
145         """Logout should work whether the user is logged in or not (#9978)."""
146         self.client.logout()
147@@ -699,6 +732,7 @@ class SessionTests(TestCase):
148         self.client.logout()
149         self.client.logout()
150 
151+
152 class RequestMethodTests(TestCase):
153     def test_get(self):
154         "Request a view via request method GET"