PageRenderTime 61ms CodeModel.GetById 32ms RepoModel.GetById 1ms app.codeStats 0ms

/kitsune/kbforums/tests/test_notifications.py

https://github.com/dbbhattacharya/kitsune
Python | 385 lines | 378 code | 4 blank | 3 comment | 0 complexity | d189f1cdc18d773b376d28fdb97308df MD5 | raw file
Possible License(s): LGPL-2.1, Apache-2.0, GPL-2.0, BSD-3-Clause
  1. from django.contrib.auth.models import User
  2. from django.contrib.sites.models import Site
  3. from django.core import mail
  4. import mock
  5. from nose.tools import eq_
  6. from kitsune.kbforums.events import NewPostEvent, NewThreadEvent
  7. from kitsune.kbforums.models import Thread, Post
  8. from kitsune.kbforums.tests import KBForumTestCase, thread
  9. from kitsune.sumo.tests import post, attrs_eq, starts_with
  10. from kitsune.users.models import Setting
  11. from kitsune.users.tests import user
  12. from kitsune.wiki.tests import document
  13. # Some of these contain a locale prefix on included links, while others don't.
  14. # This depends on whether the tests use them inside or outside the scope of a
  15. # request. See the long explanation in questions.tests.test_notifications.
  16. REPLY_EMAIL = u"""Reply to thread: Sticky Thread
  17. jsocol has replied to a thread you're watching. Here is their reply:
  18. ========
  19. a post
  20. ========
  21. To view this post on the site, click the following link, or paste it into \
  22. your browser's location bar:
  23. https://testserver/en-US/kb/%s/discuss/%s?utm_campaign=kbforums-post&\
  24. utm_medium=email&utm_source=notification#post-%s
  25. --
  26. Unsubscribe from these emails:
  27. https://testserver/en-US/unsubscribe/"""
  28. NEW_THREAD_EMAIL = u"""New thread: a title
  29. jsocol has posted a new thread in a forum you're watching. Here is the \
  30. thread:
  31. ========
  32. a post
  33. ========
  34. To view this post on the site, click the following link, or paste it into \
  35. your browser's location bar:
  36. https://testserver/en-US/kb/%s/discuss/%s?utm_campaign=kbforums-thread&\
  37. utm_medium=email&utm_source=notification
  38. --
  39. Unsubscribe from these emails:
  40. https://testserver/en-US/unsubscribe/"""
  41. class NotificationsTests(KBForumTestCase):
  42. """Test that notifications get sent."""
  43. @mock.patch.object(NewPostEvent, 'fire')
  44. def test_fire_on_reply(self, fire):
  45. """The event fires when there is a reply."""
  46. t = thread(save=True)
  47. u = user(save=True)
  48. self.client.login(username=u.username, password='testpass')
  49. post(self.client, 'wiki.discuss.reply', {'content': 'a post'},
  50. args=[t.document.slug, t.id])
  51. # NewPostEvent.fire() is called.
  52. assert fire.called
  53. @mock.patch.object(NewThreadEvent, 'fire')
  54. def test_fire_on_new_thread(self, fire):
  55. """The event fires when there is a new thread."""
  56. d = document(save=True)
  57. u = user(save=True)
  58. self.client.login(username=u.username, password='testpass')
  59. post(self.client, 'wiki.discuss.new_thread',
  60. {'title': 'a title', 'content': 'a post'},
  61. args=[d.slug])
  62. # NewThreadEvent.fire() is called.
  63. assert fire.called
  64. def _toggle_watch_thread_as(self, username, thread, turn_on=True):
  65. """Watch a thread and return it."""
  66. self.client.login(username=username, password='testpass')
  67. user = User.objects.get(username=username)
  68. watch = 'yes' if turn_on else 'no'
  69. post(self.client, 'wiki.discuss.watch_thread', {'watch': watch},
  70. args=[thread.document.slug, thread.id])
  71. # Watch exists or not, depending on watch.
  72. if turn_on:
  73. assert NewPostEvent.is_notifying(user, thread), (
  74. 'NewPostEvent should be notifying.')
  75. else:
  76. assert not NewPostEvent.is_notifying(user, thread), (
  77. 'NewPostEvent should not be notifying.')
  78. return thread
  79. def _toggle_watch_kbforum_as(self, username, document, turn_on=True):
  80. """Watch a discussion forum and return it."""
  81. self.client.login(username=username, password='testpass')
  82. user = User.objects.get(username=username)
  83. watch = 'yes' if turn_on else 'no'
  84. post(self.client, 'wiki.discuss.watch_forum', {'watch': watch},
  85. args=[document.slug])
  86. # Watch exists or not, depending on watch.
  87. if turn_on:
  88. assert NewThreadEvent.is_notifying(user, document), (
  89. 'NewThreadEvent should be notifying.')
  90. else:
  91. assert not NewThreadEvent.is_notifying(user, document), (
  92. 'NewThreadEvent should not be notifying.')
  93. return document
  94. @mock.patch.object(Site.objects, 'get_current')
  95. def test_watch_thread_then_reply(self, get_current):
  96. """The event fires and sends emails when watching a thread."""
  97. get_current.return_value.domain = 'testserver'
  98. u = user(username='jsocol', save=True)
  99. u_b = user(username='berkerpeksag', save=True)
  100. d = document(title='an article title', save=True)
  101. _t = thread(title='Sticky Thread', document=d, is_sticky=True,
  102. save=True)
  103. t = self._toggle_watch_thread_as(u_b.username, _t, turn_on=True)
  104. self.client.login(username=u.username, password='testpass')
  105. post(self.client, 'wiki.discuss.reply', {'content': 'a post'},
  106. args=[t.document.slug, t.id])
  107. p = Post.objects.all().order_by('-id')[0]
  108. attrs_eq(mail.outbox[0], to=[u_b.email],
  109. subject='Re: an article title - Sticky Thread')
  110. starts_with(mail.outbox[0].body, REPLY_EMAIL % (d.slug, t.id, p.id))
  111. self._toggle_watch_thread_as(u_b.username, _t, turn_on=False)
  112. def test_watch_other_thread_then_reply(self):
  113. """Watching a different thread than the one we're replying to shouldn't
  114. notify."""
  115. u_b = user(username='berkerpeksag', save=True)
  116. _t = thread(save=True)
  117. self._toggle_watch_thread_as(u_b.username, _t, turn_on=True)
  118. u = user(save=True)
  119. t2 = thread(save=True)
  120. self.client.login(username=u.username, password='testpass')
  121. post(self.client, 'wiki.discuss.reply', {'content': 'a post'},
  122. args=[t2.document.slug, t2.id])
  123. assert not mail.outbox
  124. @mock.patch.object(Site.objects, 'get_current')
  125. def test_watch_forum_then_new_thread(self, get_current):
  126. """Watching a forum and creating a new thread should send email."""
  127. get_current.return_value.domain = 'testserver'
  128. u = user(save=True)
  129. d = document(title='an article title', save=True)
  130. f = self._toggle_watch_kbforum_as(u.username, d, turn_on=True)
  131. u2 = user(username='jsocol', save=True)
  132. self.client.login(username=u2.username, password='testpass')
  133. post(self.client, 'wiki.discuss.new_thread',
  134. {'title': 'a title', 'content': 'a post'}, args=[f.slug])
  135. t = Thread.objects.all().order_by('-id')[0]
  136. attrs_eq(mail.outbox[0], to=[u.email],
  137. subject=u'an article title - a title')
  138. starts_with(mail.outbox[0].body, NEW_THREAD_EMAIL % (d.slug, t.id))
  139. self._toggle_watch_kbforum_as(u.username, d, turn_on=False)
  140. @mock.patch.object(Site.objects, 'get_current')
  141. def test_watch_forum_then_new_thread_as_self(self, get_current):
  142. """Watching a forum and creating a new thread as myself should not
  143. send email."""
  144. get_current.return_value.domain = 'testserver'
  145. u = user(save=True)
  146. d = document(save=True)
  147. f = self._toggle_watch_kbforum_as(u.username, d, turn_on=True)
  148. self.client.login(username=u.username, password='testpass')
  149. post(self.client, 'wiki.discuss.new_thread',
  150. {'title': 'a title', 'content': 'a post'}, args=[f.slug])
  151. # Assert no email is sent.
  152. assert not mail.outbox
  153. @mock.patch.object(Site.objects, 'get_current')
  154. def test_watch_forum_then_new_post(self, get_current):
  155. """Watching a forum and replying to a thread should send email."""
  156. get_current.return_value.domain = 'testserver'
  157. u = user(save=True)
  158. d = document(title='an article title', save=True)
  159. f = self._toggle_watch_kbforum_as(u.username, d, turn_on=True)
  160. t = thread(title='Sticky Thread', document=d, save=True)
  161. u2 = user(username='jsocol', save=True)
  162. self.client.login(username=u2.username, password='testpass')
  163. post(self.client, 'wiki.discuss.reply', {'content': 'a post'},
  164. args=[f.slug, t.id])
  165. p = Post.objects.all().order_by('-id')[0]
  166. attrs_eq(mail.outbox[0], to=[u.email],
  167. subject='Re: an article title - Sticky Thread')
  168. starts_with(mail.outbox[0].body, REPLY_EMAIL % (d.slug, t.id, p.id))
  169. @mock.patch.object(Site.objects, 'get_current')
  170. def test_watch_forum_then_new_post_as_self(self, get_current):
  171. """Watching a forum and replying as myself should not send email."""
  172. get_current.return_value.domain = 'testserver'
  173. u = user(save=True)
  174. d = document(title='an article title', save=True)
  175. f = self._toggle_watch_kbforum_as(u.username, d, turn_on=True)
  176. t = thread(document=d, save=True)
  177. self.client.login(username=u.username, password='testpass')
  178. post(self.client, 'wiki.discuss.reply', {'content': 'a post'},
  179. args=[f.slug, t.id])
  180. # Assert no email is sent.
  181. assert not mail.outbox
  182. @mock.patch.object(Site.objects, 'get_current')
  183. def test_watch_both_then_new_post(self, get_current):
  184. """Watching both and replying to a thread should send ONE email."""
  185. get_current.return_value.domain = 'testserver'
  186. u = user(save=True)
  187. d = document(title='an article title', save=True)
  188. f = self._toggle_watch_kbforum_as(u.username, d, turn_on=True)
  189. t = thread(title='Sticky Thread', document=d, save=True)
  190. self._toggle_watch_thread_as(u.username, t, turn_on=True)
  191. u2 = user(username='jsocol', save=True)
  192. self.client.login(username=u2.username, password='testpass')
  193. post(self.client, 'wiki.discuss.reply', {'content': 'a post'},
  194. args=[f.slug, t.id])
  195. eq_(1, len(mail.outbox))
  196. p = Post.objects.all().order_by('-id')[0]
  197. attrs_eq(mail.outbox[0], to=[u.email],
  198. subject='Re: an article title - Sticky Thread')
  199. starts_with(mail.outbox[0].body, REPLY_EMAIL % (d.slug, t.id, p.id))
  200. self._toggle_watch_kbforum_as(u.username, d, turn_on=False)
  201. self._toggle_watch_thread_as(u.username, t, turn_on=False)
  202. @mock.patch.object(Site.objects, 'get_current')
  203. def test_watch_locale_then_new_post(self, get_current):
  204. """Watching locale and reply to a thread."""
  205. get_current.return_value.domain = 'testserver'
  206. d = document(title='an article title', locale='en-US', save=True)
  207. t = thread(document=d, title='Sticky Thread', save=True)
  208. u = user(save=True)
  209. self.client.login(username=u.username, password='testpass')
  210. post(self.client, 'wiki.discuss.watch_locale', {'watch': 'yes'})
  211. # Reply as jsocol to document d.
  212. u2 = user(username='jsocol', save=True)
  213. self.client.login(username=u2.username, password='testpass')
  214. post(self.client, 'wiki.discuss.reply', {'content': 'a post'},
  215. args=[d.slug, t.id])
  216. # Email was sent as expected.
  217. eq_(1, len(mail.outbox))
  218. p = Post.objects.all().order_by('-id')[0]
  219. attrs_eq(mail.outbox[0], to=[u.email],
  220. subject='Re: an article title - Sticky Thread')
  221. starts_with(mail.outbox[0].body, REPLY_EMAIL % (d.slug, t.id, p.id))
  222. @mock.patch.object(Site.objects, 'get_current')
  223. def test_watch_all_then_new_post(self, get_current):
  224. """Watching document + thread + locale and reply to thread."""
  225. get_current.return_value.domain = 'testserver'
  226. u = user(save=True)
  227. _d = document(title='an article title', save=True)
  228. d = self._toggle_watch_kbforum_as(u.username, _d, turn_on=True)
  229. t = thread(title='Sticky Thread', document=d, save=True)
  230. self._toggle_watch_thread_as(u.username, t, turn_on=True)
  231. self.client.login(username=u.username, password='testpass')
  232. post(self.client, 'wiki.discuss.watch_locale', {'watch': 'yes'})
  233. # Reply as jsocol to document d.
  234. u2 = user(username='jsocol', save=True)
  235. self.client.login(username=u2.username, password='testpass')
  236. post(self.client, 'wiki.discuss.reply', {'content': 'a post'},
  237. args=[d.slug, t.id])
  238. # Only ONE email was sent. As expected.
  239. eq_(1, len(mail.outbox))
  240. p = Post.objects.all().order_by('-id')[0]
  241. attrs_eq(mail.outbox[0], to=[u.email],
  242. subject='Re: an article title - Sticky Thread')
  243. starts_with(mail.outbox[0].body, REPLY_EMAIL % (d.slug, t.id, p.id))
  244. @mock.patch.object(Site.objects, 'get_current')
  245. def test_watch_other_locale_then_new_thread(self, get_current):
  246. """Watching a different locale and createing a thread does not
  247. notify."""
  248. get_current.return_value.domain = 'testserver'
  249. d = document(locale='en-US', save=True)
  250. u = user(username='berkerpeksag', save=True)
  251. self.client.login(username=u.username, password='testpass')
  252. post(self.client, 'wiki.discuss.watch_locale', {'watch': 'yes'},
  253. locale='ja')
  254. u2 = user(save=True)
  255. self.client.login(username=u2.username, password='testpass')
  256. post(self.client, 'wiki.discuss.new_thread',
  257. {'title': 'a title', 'content': 'a post'}, args=[d.slug])
  258. # Email was not sent.
  259. eq_(0, len(mail.outbox))
  260. @mock.patch.object(Site.objects, 'get_current')
  261. def test_watch_locale_then_new_thread(self, get_current):
  262. """Watching locale and create a thread."""
  263. get_current.return_value.domain = 'testserver'
  264. d = document(title='an article title', locale='en-US', save=True)
  265. u = user(username='berkerpeksag', save=True)
  266. self.client.login(username=u.username, password='testpass')
  267. post(self.client, 'wiki.discuss.watch_locale', {'watch': 'yes'})
  268. u2 = user(username='jsocol', save=True)
  269. self.client.login(username=u2.username, password='testpass')
  270. post(self.client, 'wiki.discuss.new_thread',
  271. {'title': 'a title', 'content': 'a post'}, args=[d.slug])
  272. # Email was sent as expected.
  273. t = Thread.objects.all().order_by('-id')[0]
  274. attrs_eq(mail.outbox[0], to=[u.email],
  275. subject=u'an article title - a title')
  276. starts_with(mail.outbox[0].body, NEW_THREAD_EMAIL % (d.slug, t.id))
  277. @mock.patch.object(Site.objects, 'get_current')
  278. def test_autowatch_new_thread(self, get_current):
  279. """Creating a new thread should email responses"""
  280. get_current.return_value.domain = 'testserver'
  281. d = document(save=True)
  282. u = user(save=True)
  283. self.client.login(username=u.username, password='testpass')
  284. s = Setting.objects.create(user=u, name='kbforums_watch_new_thread',
  285. value='False')
  286. data = {'title': 'a title', 'content': 'a post'}
  287. post(self.client, 'wiki.discuss.new_thread', data, args=[d.slug])
  288. t1 = thread(document=d, save=True)
  289. assert not NewPostEvent.is_notifying(u, t1), (
  290. 'NewPostEvent should not be notifying.')
  291. s.value = 'True'
  292. s.save()
  293. post(self.client, 'wiki.discuss.new_thread', data, args=[d.slug])
  294. t2 = Thread.uncached.all().order_by('-id')[0]
  295. assert NewPostEvent.is_notifying(u, t2), (
  296. 'NewPostEvent should be notifying')
  297. @mock.patch.object(Site.objects, 'get_current')
  298. def test_autowatch_reply(self, get_current):
  299. get_current.return_value.domain = 'testserver'
  300. u = user(save=True)
  301. t1 = thread(is_locked=False, save=True)
  302. t2 = thread(is_locked=False, save=True)
  303. assert not NewPostEvent.is_notifying(u, t1)
  304. assert not NewPostEvent.is_notifying(u, t2)
  305. self.client.login(username=u.username, password='testpass')
  306. s = Setting.objects.create(user=u,
  307. name='kbforums_watch_after_reply',
  308. value='True')
  309. data = {'content': 'some content'}
  310. post(self.client, 'wiki.discuss.reply', data,
  311. args=[t1.document.slug, t1.pk])
  312. assert NewPostEvent.is_notifying(u, t1)
  313. s.value = 'False'
  314. s.save()
  315. post(self.client, 'wiki.discuss.reply', data,
  316. args=[t2.document.slug, t2.pk])
  317. assert not NewPostEvent.is_notifying(u, t2)