test_readtracker.py 8.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218
  1. from datetime import timedelta
  2. from django.contrib.auth import get_user_model
  3. from django.test import TestCase
  4. from django.utils import timezone
  5. from misago.acl import add_acl
  6. from misago.forums.models import Forum
  7. from misago.threads import testutils
  8. from misago.users.models import AnonymousUser
  9. from misago.readtracker import forumstracker, threadstracker
  10. class ReadTrackerTests(TestCase):
  11. def setUp(self):
  12. self.forums = [f for f in Forum.objects.filter(role="forum")[:1]]
  13. self.forum = self.forums[0]
  14. User = get_user_model()
  15. self.user = User.objects.create_user("Bob", "bob@test.com", "Pass.123")
  16. self.anon = AnonymousUser()
  17. def post_thread(self, datetime):
  18. return testutils.post_thread(forum=self.forum, started_on=datetime)
  19. class ForumsTrackerTests(ReadTrackerTests):
  20. def test_anon_empty_forum_read(self):
  21. """anon users content is always read"""
  22. forumstracker.make_read_aware(self.anon, self.forums)
  23. self.assertIsNone(self.forum.last_post_on)
  24. self.assertTrue(self.forum.is_read)
  25. def test_anon_forum_with_recent_reply_read(self):
  26. """anon users content is always read"""
  27. forumstracker.make_read_aware(self.anon, self.forums)
  28. self.forum.last_post_on = timezone.now()
  29. self.assertTrue(self.forum.is_read)
  30. def test_empty_forum_is_read(self):
  31. """empty forum is read for signed in user"""
  32. forumstracker.make_read_aware(self.user, self.forums)
  33. self.assertTrue(self.forum.is_read)
  34. def test_make_read_aware_sets_read_flag_for_empty_forum(self):
  35. """make_read_aware sets read flag on empty forum"""
  36. forumstracker.make_read_aware(self.anon, self.forums)
  37. self.assertTrue(self.forum.is_read)
  38. forumstracker.make_read_aware(self.user, self.forums)
  39. self.assertTrue(self.forum.is_read)
  40. def test_make_read_aware_sets_read_flag_for_forum_with_old_thread(self):
  41. """make_read_aware sets read flag on forum with old thread"""
  42. self.forum.last_post_on = self.user.reads_cutoff - timedelta(days=1)
  43. forumstracker.make_read_aware(self.user, self.forums)
  44. self.assertTrue(self.forum.is_read)
  45. def test_make_read_aware_sets_unread_flag_for_forum_with_new_thread(self):
  46. """make_read_aware sets unread flag on forum with new thread"""
  47. self.forum.last_post_on = self.user.reads_cutoff + timedelta(days=1)
  48. forumstracker.make_read_aware(self.user, self.forums)
  49. self.assertFalse(self.forum.is_read)
  50. def test_sync_record_for_empty_forum(self):
  51. """sync_record sets read flag on empty forum"""
  52. add_acl(self.user, self.forums)
  53. forumstracker.sync_record(self.user, self.forum)
  54. self.user.forumread_set.get(forum=self.forum)
  55. forumstracker.make_read_aware(self.user, self.forums)
  56. self.assertTrue(self.forum.is_read)
  57. def test_sync_record_for_forum_with_old_thread_and_reply(self):
  58. """
  59. sync_record sets read flag on forum with old thread,
  60. then changes flag to unread when new reply is posted
  61. """
  62. self.post_thread(self.user.reads_cutoff - timedelta(days=1))
  63. add_acl(self.user, self.forums)
  64. forumstracker.sync_record(self.user, self.forum)
  65. self.user.forumread_set.get(forum=self.forum)
  66. forumstracker.make_read_aware(self.user, self.forums)
  67. self.assertTrue(self.forum.is_read)
  68. thread = self.post_thread(self.user.reads_cutoff + timedelta(days=1))
  69. forumstracker.sync_record(self.user, self.forum)
  70. forumstracker.make_read_aware(self.user, self.forums)
  71. self.assertFalse(self.forum.is_read)
  72. def test_sync_record_for_forum_with_new_thread(self):
  73. """
  74. sync_record sets read flag on forum with old thread,
  75. then keeps flag to unread when new reply is posted
  76. """
  77. self.post_thread(self.user.reads_cutoff + timedelta(days=1))
  78. add_acl(self.user, self.forums)
  79. forumstracker.sync_record(self.user, self.forum)
  80. self.user.forumread_set.get(forum=self.forum)
  81. forumstracker.make_read_aware(self.user, self.forums)
  82. self.assertFalse(self.forum.is_read)
  83. self.post_thread(self.user.reads_cutoff + timedelta(days=1))
  84. forumstracker.sync_record(self.user, self.forum)
  85. forumstracker.make_read_aware(self.user, self.forums)
  86. self.assertFalse(self.forum.is_read)
  87. def test_sync_record_for_forum_with_deleted_threads(self):
  88. """unread forum reverts to read after its emptied"""
  89. self.post_thread(self.user.reads_cutoff + timedelta(days=1))
  90. self.post_thread(self.user.reads_cutoff + timedelta(days=1))
  91. self.post_thread(self.user.reads_cutoff + timedelta(days=1))
  92. add_acl(self.user, self.forums)
  93. forumstracker.sync_record(self.user, self.forum)
  94. forumstracker.make_read_aware(self.user, self.forums)
  95. self.assertFalse(self.forum.is_read)
  96. self.forum.thread_set.all().delete()
  97. self.forum.synchronize()
  98. self.forum.save()
  99. forumstracker.make_read_aware(self.user, self.forums)
  100. self.assertTrue(self.forum.is_read)
  101. def test_sync_record_for_forum_with_many_threads(self):
  102. """sync_record sets unread flag on forum with many threads"""
  103. self.post_thread(self.user.reads_cutoff + timedelta(days=1))
  104. self.post_thread(self.user.reads_cutoff - timedelta(days=1))
  105. self.post_thread(self.user.reads_cutoff + timedelta(days=1))
  106. self.post_thread(self.user.reads_cutoff - timedelta(days=1))
  107. add_acl(self.user, self.forums)
  108. forumstracker.sync_record(self.user, self.forum)
  109. self.user.forumread_set.get(forum=self.forum)
  110. forumstracker.make_read_aware(self.user, self.forums)
  111. self.assertFalse(self.forum.is_read)
  112. self.post_thread(self.user.reads_cutoff + timedelta(days=1))
  113. forumstracker.sync_record(self.user, self.forum)
  114. forumstracker.make_read_aware(self.user, self.forums)
  115. self.assertFalse(self.forum.is_read)
  116. class ThreadsTrackerTests(ReadTrackerTests):
  117. def setUp(self):
  118. super(ThreadsTrackerTests, self).setUp()
  119. self.thread = self.post_thread(timezone.now() - timedelta(days=10))
  120. def reply_thread(self, is_hidden=False, is_moderated=False):
  121. self.post = testutils.reply_thread(
  122. thread=self.thread,
  123. is_hidden=is_hidden,
  124. is_moderated=is_moderated,
  125. posted_on=timezone.now())
  126. return self.post
  127. def test_thread_read_for_guest(self):
  128. """threads are always read for guests"""
  129. threadstracker.make_read_aware(self.anon, self.thread)
  130. self.assertTrue(self.thread.is_read)
  131. self.reply_thread()
  132. threadstracker.make_read_aware(self.anon, [self.thread])
  133. self.assertTrue(self.thread.is_read)
  134. def test_thread_read_for_user(self):
  135. """thread is read for user"""
  136. threadstracker.make_read_aware(self.user, self.thread)
  137. self.assertTrue(self.thread.is_read)
  138. def test_thread_replied_unread_for_user(self):
  139. """replied thread is unread for user"""
  140. self.reply_thread(self.thread)
  141. threadstracker.make_read_aware(self.user, self.thread)
  142. self.assertFalse(self.thread.is_read)
  143. def _test_thread_read(self):
  144. """thread read flag is set for user, then its set as unread by reply"""
  145. self.reply_thread(self.thread)
  146. add_acl(self.user, self.forums)
  147. threadstracker.make_read_aware(self.user, self.thread)
  148. self.assertFalse(self.thread.is_read)
  149. threadstracker.read_thread(self.user, self.thread, self.post)
  150. threadstracker.make_read_aware(self.user, self.thread)
  151. self.assertTrue(self.thread.is_read)
  152. forumstracker.make_read_aware(self.user, self.forums)
  153. self.assertTrue(self.forum.is_read)
  154. self.thread.last_post_on = timezone.now()
  155. self.thread.save()
  156. self.forum.synchronize()
  157. self.forum.save()
  158. self.reply_thread()
  159. threadstracker.make_read_aware(self.user, self.thread)
  160. self.assertFalse(self.thread.is_read)
  161. forumstracker.make_read_aware(self.user, self.forums)
  162. self.assertFalse(self.forum.is_read)
  163. posts = [post for post in self.thread.post_set.order_by('id')]
  164. threadstracker.make_posts_read_aware(self.user, self.thread, posts)
  165. for post in posts[:-1]:
  166. self.assertTrue(post.is_read)
  167. self.assertFalse(posts[-1].is_read)