/lib/django-1.4/tests/regressiontests/comment_tests/tests/comment_view_tests.py
Python | 294 lines | 266 code | 22 blank | 6 comment | 3 complexity | 2745502aad237ee1843147e742d668c5 MD5 | raw file
1from __future__ import absolute_import
2
3import re
4
5from django.conf import settings
6from django.contrib.auth.models import User
7from django.contrib.comments import signals
8from django.contrib.comments.models import Comment
9
10from . import CommentTestCase
11from ..models import Article, Book
12
13
14post_redirect_re = re.compile(r'^http://testserver/posted/\?c=(?P<pk>\d+$)')
15
16class CommentViewTests(CommentTestCase):
17
18 def testPostCommentHTTPMethods(self):
19 a = Article.objects.get(pk=1)
20 data = self.getValidData(a)
21 response = self.client.get("/post/", data)
22 self.assertEqual(response.status_code, 405)
23 self.assertEqual(response["Allow"], "POST")
24
25 def testPostCommentMissingCtype(self):
26 a = Article.objects.get(pk=1)
27 data = self.getValidData(a)
28 del data["content_type"]
29 response = self.client.post("/post/", data)
30 self.assertEqual(response.status_code, 400)
31
32 def testPostCommentBadCtype(self):
33 a = Article.objects.get(pk=1)
34 data = self.getValidData(a)
35 data["content_type"] = "Nobody expects the Spanish Inquisition!"
36 response = self.client.post("/post/", data)
37 self.assertEqual(response.status_code, 400)
38
39 def testPostCommentMissingObjectPK(self):
40 a = Article.objects.get(pk=1)
41 data = self.getValidData(a)
42 del data["object_pk"]
43 response = self.client.post("/post/", data)
44 self.assertEqual(response.status_code, 400)
45
46 def testPostCommentBadObjectPK(self):
47 a = Article.objects.get(pk=1)
48 data = self.getValidData(a)
49 data["object_pk"] = "14"
50 response = self.client.post("/post/", data)
51 self.assertEqual(response.status_code, 400)
52
53 def testPostInvalidIntegerPK(self):
54 a = Article.objects.get(pk=1)
55 data = self.getValidData(a)
56 data["comment"] = "This is another comment"
57 data["object_pk"] = u'\ufffd'
58 response = self.client.post("/post/", data)
59 self.assertEqual(response.status_code, 400)
60
61 def testPostInvalidDecimalPK(self):
62 b = Book.objects.get(pk='12.34')
63 data = self.getValidData(b)
64 data["comment"] = "This is another comment"
65 data["object_pk"] = 'cookies'
66 response = self.client.post("/post/", data)
67 self.assertEqual(response.status_code, 400)
68
69 def testCommentPreview(self):
70 a = Article.objects.get(pk=1)
71 data = self.getValidData(a)
72 data["preview"] = "Preview"
73 response = self.client.post("/post/", data)
74 self.assertEqual(response.status_code, 200)
75 self.assertTemplateUsed(response, "comments/preview.html")
76
77 def testHashTampering(self):
78 a = Article.objects.get(pk=1)
79 data = self.getValidData(a)
80 data["security_hash"] = "Nobody expects the Spanish Inquisition!"
81 response = self.client.post("/post/", data)
82 self.assertEqual(response.status_code, 400)
83
84 def testDebugCommentErrors(self):
85 """The debug error template should be shown only if DEBUG is True"""
86 olddebug = settings.DEBUG
87
88 settings.DEBUG = True
89 a = Article.objects.get(pk=1)
90 data = self.getValidData(a)
91 data["security_hash"] = "Nobody expects the Spanish Inquisition!"
92 response = self.client.post("/post/", data)
93 self.assertEqual(response.status_code, 400)
94 self.assertTemplateUsed(response, "comments/400-debug.html")
95
96 settings.DEBUG = False
97 response = self.client.post("/post/", data)
98 self.assertEqual(response.status_code, 400)
99 self.assertTemplateNotUsed(response, "comments/400-debug.html")
100
101 settings.DEBUG = olddebug
102
103 def testCreateValidComment(self):
104 a = Article.objects.get(pk=1)
105 data = self.getValidData(a)
106 self.response = self.client.post("/post/", data, REMOTE_ADDR="1.2.3.4")
107 self.assertEqual(self.response.status_code, 302)
108 self.assertEqual(Comment.objects.count(), 1)
109 c = Comment.objects.all()[0]
110 self.assertEqual(c.ip_address, "1.2.3.4")
111 self.assertEqual(c.comment, "This is my comment")
112
113 def testPostAsAuthenticatedUser(self):
114 a = Article.objects.get(pk=1)
115 data = self.getValidData(a)
116 data['name'] = data['email'] = ''
117 self.client.login(username="normaluser", password="normaluser")
118 self.response = self.client.post("/post/", data, REMOTE_ADDR="1.2.3.4")
119 self.assertEqual(self.response.status_code, 302)
120 self.assertEqual(Comment.objects.count(), 1)
121 c = Comment.objects.all()[0]
122 self.assertEqual(c.ip_address, "1.2.3.4")
123 u = User.objects.get(username='normaluser')
124 self.assertEqual(c.user, u)
125 self.assertEqual(c.user_name, u.get_full_name())
126 self.assertEqual(c.user_email, u.email)
127
128 def testPostAsAuthenticatedUserWithoutFullname(self):
129 """
130 Check that the user's name in the comment is populated for
131 authenticated users without first_name and last_name.
132 """
133 user = User.objects.create_user(username='jane_other',
134 email='jane@example.com', password='jane_other')
135 a = Article.objects.get(pk=1)
136 data = self.getValidData(a)
137 data['name'] = data['email'] = ''
138 self.client.login(username="jane_other", password="jane_other")
139 self.response = self.client.post("/post/", data, REMOTE_ADDR="1.2.3.4")
140 c = Comment.objects.get(user=user)
141 self.assertEqual(c.ip_address, "1.2.3.4")
142 self.assertEqual(c.user_name, 'jane_other')
143 user.delete()
144
145 def testPreventDuplicateComments(self):
146 """Prevent posting the exact same comment twice"""
147 a = Article.objects.get(pk=1)
148 data = self.getValidData(a)
149 self.client.post("/post/", data)
150 self.client.post("/post/", data)
151 self.assertEqual(Comment.objects.count(), 1)
152
153 # This should not trigger the duplicate prevention
154 self.client.post("/post/", dict(data, comment="My second comment."))
155 self.assertEqual(Comment.objects.count(), 2)
156
157 def testCommentSignals(self):
158 """Test signals emitted by the comment posting view"""
159
160 # callback
161 def receive(sender, **kwargs):
162 self.assertEqual(kwargs['comment'].comment, "This is my comment")
163 self.assertTrue('request' in kwargs)
164 received_signals.append(kwargs.get('signal'))
165
166 # Connect signals and keep track of handled ones
167 received_signals = []
168 expected_signals = [
169 signals.comment_will_be_posted, signals.comment_was_posted
170 ]
171 for signal in expected_signals:
172 signal.connect(receive)
173
174 # Post a comment and check the signals
175 self.testCreateValidComment()
176 self.assertEqual(received_signals, expected_signals)
177
178 for signal in expected_signals:
179 signal.disconnect(receive)
180
181 def testWillBePostedSignal(self):
182 """
183 Test that the comment_will_be_posted signal can prevent the comment from
184 actually getting saved
185 """
186 def receive(sender, **kwargs): return False
187 signals.comment_will_be_posted.connect(receive, dispatch_uid="comment-test")
188 a = Article.objects.get(pk=1)
189 data = self.getValidData(a)
190 response = self.client.post("/post/", data)
191 self.assertEqual(response.status_code, 400)
192 self.assertEqual(Comment.objects.count(), 0)
193 signals.comment_will_be_posted.disconnect(dispatch_uid="comment-test")
194
195 def testWillBePostedSignalModifyComment(self):
196 """
197 Test that the comment_will_be_posted signal can modify a comment before
198 it gets posted
199 """
200 def receive(sender, **kwargs):
201 # a bad but effective spam filter :)...
202 kwargs['comment'].is_public = False
203
204 signals.comment_will_be_posted.connect(receive)
205 self.testCreateValidComment()
206 c = Comment.objects.all()[0]
207 self.assertFalse(c.is_public)
208
209 def testCommentNext(self):
210 """Test the different "next" actions the comment view can take"""
211 a = Article.objects.get(pk=1)
212 data = self.getValidData(a)
213 response = self.client.post("/post/", data)
214 location = response["Location"]
215 match = post_redirect_re.match(location)
216 self.assertTrue(match != None, "Unexpected redirect location: %s" % location)
217
218 data["next"] = "/somewhere/else/"
219 data["comment"] = "This is another comment"
220 response = self.client.post("/post/", data)
221 location = response["Location"]
222 match = re.search(r"^http://testserver/somewhere/else/\?c=\d+$", location)
223 self.assertTrue(match != None, "Unexpected redirect location: %s" % location)
224
225 data["next"] = "http://badserver/somewhere/else/"
226 data["comment"] = "This is another comment with an unsafe next url"
227 response = self.client.post("/post/", data)
228 location = response["Location"]
229 match = post_redirect_re.match(location)
230 self.assertTrue(match != None, "Unsafe redirection to: %s" % location)
231
232 def testCommentDoneView(self):
233 a = Article.objects.get(pk=1)
234 data = self.getValidData(a)
235 response = self.client.post("/post/", data)
236 location = response["Location"]
237 match = post_redirect_re.match(location)
238 self.assertTrue(match != None, "Unexpected redirect location: %s" % location)
239 pk = int(match.group('pk'))
240 response = self.client.get(location)
241 self.assertTemplateUsed(response, "comments/posted.html")
242 self.assertEqual(response.context[0]["comment"], Comment.objects.get(pk=pk))
243
244 def testCommentNextWithQueryString(self):
245 """
246 The `next` key needs to handle already having a query string (#10585)
247 """
248 a = Article.objects.get(pk=1)
249 data = self.getValidData(a)
250 data["next"] = "/somewhere/else/?foo=bar"
251 data["comment"] = "This is another comment"
252 response = self.client.post("/post/", data)
253 location = response["Location"]
254 match = re.search(r"^http://testserver/somewhere/else/\?foo=bar&c=\d+$", location)
255 self.assertTrue(match != None, "Unexpected redirect location: %s" % location)
256
257 def testCommentPostRedirectWithInvalidIntegerPK(self):
258 """
259 Tests that attempting to retrieve the location specified in the
260 post redirect, after adding some invalid data to the expected
261 querystring it ends with, doesn't cause a server error.
262 """
263 a = Article.objects.get(pk=1)
264 data = self.getValidData(a)
265 data["comment"] = "This is another comment"
266 response = self.client.post("/post/", data)
267 location = response["Location"]
268 broken_location = location + u"\ufffd"
269 response = self.client.get(broken_location)
270 self.assertEqual(response.status_code, 200)
271
272 def testCommentNextWithQueryStringAndAnchor(self):
273 """
274 The `next` key needs to handle already having an anchor. Refs #13411.
275 """
276 # With a query string also.
277 a = Article.objects.get(pk=1)
278 data = self.getValidData(a)
279 data["next"] = "/somewhere/else/?foo=bar#baz"
280 data["comment"] = "This is another comment"
281 response = self.client.post("/post/", data)
282 location = response["Location"]
283 match = re.search(r"^http://testserver/somewhere/else/\?foo=bar&c=\d+#baz$", location)
284 self.assertTrue(match != None, "Unexpected redirect location: %s" % location)
285
286 # Without a query string
287 a = Article.objects.get(pk=1)
288 data = self.getValidData(a)
289 data["next"] = "/somewhere/else/#baz"
290 data["comment"] = "This is another comment"
291 response = self.client.post("/post/", data)
292 location = response["Location"]
293 match = re.search(r"^http://testserver/somewhere/else/\?c=\d+#baz$", location)
294 self.assertTrue(match != None, "Unexpected redirect location: %s" % location)