PageRenderTime 50ms CodeModel.GetById 20ms RepoModel.GetById 0ms app.codeStats 0ms

/apps/kbforums/tests/test_notifications.py

https://github.com/pcraciunoiu/kitsune
Python | 312 lines | 305 code | 4 blank | 3 comment | 0 complexity | f238f386d23f5618746f36ef2f536276 MD5 | raw file
  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 kbforums.events import NewPostEvent, NewThreadEvent
  7. from kbforums.models import Thread, Post
  8. from kbforums.tests import KBForumTestCase
  9. from sumo.tests import post, attrs_eq, starts_with
  10. from wiki.models import Document
  11. # Some of these contain a locale prefix on included links, while others don't.
  12. # This depends on whether the tests use them inside or outside the scope of a
  13. # request. See the long explanation in questions.tests.test_notifications.
  14. REPLY_EMAIL = u"""Reply to thread: Sticky Thread
  15. User jsocol has replied to a thread you're watching. Here
  16. is their reply:
  17. ========
  18. a post
  19. ========
  20. To view this post on the site, click the following link, or
  21. paste it into your browser's location bar:
  22. https://testserver/en-US/kb/article-title/discuss/2#post-%s
  23. --
  24. Unsubscribe from these emails:
  25. https://testserver/en-US/unsubscribe/"""
  26. NEW_THREAD_EMAIL = u"""New thread: a title
  27. User jsocol has posted a new thread in a forum you're watching.
  28. Here is the thread:
  29. ========
  30. a post
  31. ========
  32. To view this post on the site, click the following link, or
  33. paste it into your browser's location bar:
  34. https://testserver/en-US/kb/article-title/discuss/%s
  35. --
  36. Unsubscribe from these emails:
  37. https://testserver/en-US/unsubscribe/"""
  38. class NotificationsTests(KBForumTestCase):
  39. """Test that notifications get sent."""
  40. @mock.patch.object(NewPostEvent, 'fire')
  41. def test_fire_on_reply(self, fire):
  42. """The event fires when there is a reply."""
  43. t = Thread.objects.get(pk=2)
  44. self.client.login(username='jsocol', password='testpass')
  45. post(self.client, 'wiki.discuss.reply', {'content': 'a post'},
  46. args=[t.document.slug, t.id])
  47. # NewPostEvent.fire() is called.
  48. assert fire.called
  49. @mock.patch.object(NewThreadEvent, 'fire')
  50. def test_fire_on_new_thread(self, fire):
  51. """The event fires when there is a new thread."""
  52. d = Document.objects.get(pk=1)
  53. self.client.login(username='jsocol', password='testpass')
  54. post(self.client, 'wiki.discuss.new_thread',
  55. {'title': 'a title', 'content': 'a post'},
  56. args=[d.slug])
  57. # NewThreadEvent.fire() is called.
  58. assert fire.called
  59. def _toggle_watch_thread_as(self, username, turn_on=True, thread_id=2):
  60. """Watch a thread and return it."""
  61. thread = Thread.objects.get(pk=thread_id)
  62. self.client.login(username=username, password='testpass')
  63. user = User.objects.get(username=username)
  64. watch = 'yes' if turn_on else 'no'
  65. post(self.client, 'wiki.discuss.watch_thread', {'watch': watch},
  66. args=[thread.document.slug, thread.id])
  67. # Watch exists or not, depending on watch.
  68. if turn_on:
  69. assert NewPostEvent.is_notifying(user, thread), (
  70. 'NewPostEvent should be notifying.')
  71. else:
  72. assert not NewPostEvent.is_notifying(user, thread), (
  73. 'NewPostEvent should not be notifying.')
  74. return thread
  75. def _toggle_watch_kbforum_as(self, username, turn_on=True, document_id=1):
  76. """Watch a discussion forum and return it."""
  77. document = Document.objects.get(pk=document_id)
  78. self.client.login(username=username, password='testpass')
  79. user = User.objects.get(username=username)
  80. watch = 'yes' if turn_on else 'no'
  81. post(self.client, 'wiki.discuss.watch_forum', {'watch': watch},
  82. args=[document.slug])
  83. # Watch exists or not, depending on watch.
  84. if turn_on:
  85. assert NewThreadEvent.is_notifying(user, document), (
  86. 'NewThreadEvent should be notifying.')
  87. else:
  88. assert not NewPostEvent.is_notifying(user, document), (
  89. 'NewThreadEvent should not be notifying.')
  90. return document
  91. @mock.patch.object(Site.objects, 'get_current')
  92. def test_watch_thread_then_reply(self, get_current):
  93. """The event fires and sends emails when watching a thread."""
  94. get_current.return_value.domain = 'testserver'
  95. t = self._toggle_watch_thread_as('pcraciunoiu', turn_on=True)
  96. self.client.login(username='jsocol', password='testpass')
  97. post(self.client, 'wiki.discuss.reply', {'content': 'a post'},
  98. args=[t.document.slug, t.id])
  99. p = Post.objects.all().order_by('-id')[0]
  100. attrs_eq(mail.outbox[0], to=['user47963@nowhere'],
  101. subject='Reply to: Sticky Thread')
  102. starts_with(mail.outbox[0].body, REPLY_EMAIL % p.id)
  103. self._toggle_watch_thread_as('pcraciunoiu', turn_on=False)
  104. def test_watch_other_thread_then_reply(self):
  105. """Watching a different thread than the one we're replying to shouldn't
  106. notify."""
  107. t = self._toggle_watch_thread_as('pcraciunoiu', turn_on=True)
  108. t2 = Thread.objects.exclude(pk=t.pk)[0]
  109. self.client.login(username='jsocol', password='testpass')
  110. post(self.client, 'wiki.discuss.reply', {'content': 'a post'},
  111. args=[t2.document.slug, t2.id])
  112. assert not mail.outbox
  113. @mock.patch.object(Site.objects, 'get_current')
  114. def test_watch_forum_then_new_thread(self, get_current):
  115. """Watching a forum and creating a new thread should send email."""
  116. get_current.return_value.domain = 'testserver'
  117. f = self._toggle_watch_kbforum_as('pcraciunoiu', turn_on=True)
  118. self.client.login(username='jsocol', password='testpass')
  119. post(self.client, 'wiki.discuss.new_thread',
  120. {'title': 'a title', 'content': 'a post'}, args=[f.slug])
  121. t = Thread.objects.all().order_by('-id')[0]
  122. attrs_eq(mail.outbox[0], to=['user47963@nowhere'],
  123. subject=u'New thread in an article title: a title')
  124. starts_with(mail.outbox[0].body, NEW_THREAD_EMAIL % t.id)
  125. self._toggle_watch_kbforum_as('pcraciunoiu', turn_on=False)
  126. @mock.patch.object(Site.objects, 'get_current')
  127. def test_watch_forum_then_new_thread_as_self(self, get_current):
  128. """Watching a forum and creating a new thread as myself should not
  129. send email."""
  130. get_current.return_value.domain = 'testserver'
  131. f = self._toggle_watch_kbforum_as('pcraciunoiu', turn_on=True)
  132. self.client.login(username='pcraciunoiu', password='testpass')
  133. post(self.client, 'wiki.discuss.new_thread',
  134. {'title': 'a title', 'content': 'a post'}, args=[f.slug])
  135. # Assert no email is sent.
  136. assert not mail.outbox
  137. @mock.patch.object(Site.objects, 'get_current')
  138. def test_watch_forum_then_new_post(self, get_current):
  139. """Watching a forum and replying to a thread should send email."""
  140. get_current.return_value.domain = 'testserver'
  141. f = self._toggle_watch_kbforum_as('pcraciunoiu', turn_on=True)
  142. t = f.thread_set.all()[0]
  143. self.client.login(username='jsocol', password='testpass')
  144. post(self.client, 'wiki.discuss.reply', {'content': 'a post'},
  145. args=[f.slug, t.id])
  146. p = Post.objects.all().order_by('-id')[0]
  147. attrs_eq(mail.outbox[0], to=['user47963@nowhere'],
  148. subject='Reply to: Sticky Thread')
  149. starts_with(mail.outbox[0].body, REPLY_EMAIL % p.id)
  150. @mock.patch.object(Site.objects, 'get_current')
  151. def test_watch_forum_then_new_post_as_self(self, get_current):
  152. """Watching a forum and replying as myself should not send email."""
  153. get_current.return_value.domain = 'testserver'
  154. f = self._toggle_watch_kbforum_as('pcraciunoiu', turn_on=True)
  155. t = f.thread_set.all()[0]
  156. self.client.login(username='pcraciunoiu', password='testpass')
  157. post(self.client, 'wiki.discuss.reply', {'content': 'a post'},
  158. args=[f.slug, t.id])
  159. # Assert no email is sent.
  160. assert not mail.outbox
  161. @mock.patch.object(Site.objects, 'get_current')
  162. def test_watch_both_then_new_post(self, get_current):
  163. """Watching both and replying to a thread should send ONE email."""
  164. get_current.return_value.domain = 'testserver'
  165. f = self._toggle_watch_kbforum_as('pcraciunoiu', turn_on=True)
  166. t = f.thread_set.all()[0]
  167. self._toggle_watch_thread_as('pcraciunoiu', turn_on=True,
  168. thread_id=t.id)
  169. self.client.login(username='jsocol', password='testpass')
  170. post(self.client, 'wiki.discuss.reply', {'content': 'a post'},
  171. args=[f.slug, t.id])
  172. eq_(1, len(mail.outbox))
  173. p = Post.objects.all().order_by('-id')[0]
  174. attrs_eq(mail.outbox[0], to=['user47963@nowhere'],
  175. subject='Reply to: Sticky Thread')
  176. starts_with(mail.outbox[0].body, REPLY_EMAIL % p.id)
  177. self._toggle_watch_kbforum_as('pcraciunoiu', turn_on=False)
  178. self._toggle_watch_thread_as('pcraciunoiu', turn_on=False)
  179. @mock.patch.object(Site.objects, 'get_current')
  180. def test_watch_locale_then_new_post(self, get_current):
  181. """Watching locale and reply to a thread."""
  182. get_current.return_value.domain = 'testserver'
  183. d = Document.objects.filter(locale='en-US')[0]
  184. t = d.thread_set.all()[0]
  185. # Log in as pcraciunoiu.
  186. self.client.login(username='pcraciunoiu', password='testpass')
  187. post(self.client, 'wiki.discuss.watch_locale', {'watch': 'yes'})
  188. # Reply as jsocol to document d.
  189. self.client.login(username='jsocol', password='testpass')
  190. post(self.client, 'wiki.discuss.reply', {'content': 'a post'},
  191. args=[d.slug, t.id])
  192. # Email was sent as expected.
  193. eq_(1, len(mail.outbox))
  194. p = Post.objects.all().order_by('-id')[0]
  195. attrs_eq(mail.outbox[0], to=['user47963@nowhere'],
  196. subject='Reply to: Sticky Thread')
  197. starts_with(mail.outbox[0].body, REPLY_EMAIL % p.id)
  198. @mock.patch.object(Site.objects, 'get_current')
  199. def test_watch_all_then_new_post(self, get_current):
  200. """Watching document + thread + locale and reply to thread."""
  201. get_current.return_value.domain = 'testserver'
  202. d = self._toggle_watch_kbforum_as('pcraciunoiu', turn_on=True)
  203. t = d.thread_set.all()[0]
  204. self._toggle_watch_thread_as('pcraciunoiu', turn_on=True,
  205. thread_id=t.id)
  206. # Log in as pcraciunoiu.
  207. self.client.login(username='pcraciunoiu', password='testpass')
  208. post(self.client, 'wiki.discuss.watch_locale', {'watch': 'yes'})
  209. # Reply as jsocol to document d.
  210. self.client.login(username='jsocol', password='testpass')
  211. post(self.client, 'wiki.discuss.reply', {'content': 'a post'},
  212. args=[d.slug, t.id])
  213. # Only ONE email was sent. As expected.
  214. eq_(1, len(mail.outbox))
  215. p = Post.objects.all().order_by('-id')[0]
  216. attrs_eq(mail.outbox[0], to=['user47963@nowhere'],
  217. subject='Reply to: Sticky Thread')
  218. starts_with(mail.outbox[0].body, REPLY_EMAIL % p.id)
  219. @mock.patch.object(Site.objects, 'get_current')
  220. def test_watch_other_locale_then_new_thread(self, get_current):
  221. """Watching a different locale and createing a thread does not
  222. notify."""
  223. get_current.return_value.domain = 'testserver'
  224. d = Document.objects.filter(locale='en-US')[0]
  225. # Log in as pcraciunoiu.
  226. self.client.login(username='pcraciunoiu', password='testpass')
  227. post(self.client, 'wiki.discuss.watch_locale', {'watch': 'yes'},
  228. locale='ja')
  229. # Create new thread as jsocol for document d.
  230. self.client.login(username='jsocol', password='testpass')
  231. post(self.client, 'wiki.discuss.new_thread',
  232. {'title': 'a title', 'content': 'a post'}, args=[d.slug])
  233. # Email was not sent.
  234. eq_(0, len(mail.outbox))
  235. @mock.patch.object(Site.objects, 'get_current')
  236. def test_watch_locale_then_new_thread(self, get_current):
  237. """Watching locale and create a thread."""
  238. get_current.return_value.domain = 'testserver'
  239. d = Document.objects.filter(locale='en-US')[0]
  240. # Log in as pcraciunoiu.
  241. self.client.login(username='pcraciunoiu', password='testpass')
  242. post(self.client, 'wiki.discuss.watch_locale', {'watch': 'yes'})
  243. # Create new thread as jsocol for document d.
  244. self.client.login(username='jsocol', password='testpass')
  245. post(self.client, 'wiki.discuss.new_thread',
  246. {'title': 'a title', 'content': 'a post'}, args=[d.slug])
  247. # Email was sent as expected.
  248. t = Thread.objects.all().order_by('-id')[0]
  249. attrs_eq(mail.outbox[0], to=['user47963@nowhere'],
  250. subject=u'New thread in an article title: a title')
  251. starts_with(mail.outbox[0].body, NEW_THREAD_EMAIL % t.id)