test_thread_model.py 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368
  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.categories.models import Category
  6. from misago.threads.models import Poll, Post, Thread, ThreadParticipant
  7. UserModel = get_user_model()
  8. class ThreadModelTests(TestCase):
  9. def setUp(self):
  10. datetime = timezone.now()
  11. self.category = Category.objects.all_categories()[:1][0]
  12. self.thread = Thread(
  13. category=self.category,
  14. started_on=datetime,
  15. starter_name='Tester',
  16. starter_slug='tester',
  17. last_post_on=datetime,
  18. last_poster_name='Tester',
  19. last_poster_slug='tester'
  20. )
  21. self.thread.set_title("Test thread")
  22. self.thread.save()
  23. post = Post.objects.create(
  24. category=self.category,
  25. thread=self.thread,
  26. poster_name='Tester',
  27. poster_ip='127.0.0.1',
  28. original="Hello! I am test message!",
  29. parsed="<p>Hello! I am test message!</p>",
  30. checksum="nope",
  31. posted_on=datetime,
  32. updated_on=datetime
  33. )
  34. self.thread.first_post = post
  35. self.thread.last_post = post
  36. self.thread.save()
  37. def test_synchronize(self):
  38. """synchronize method updates thread data to reflect its contents"""
  39. user = UserModel.objects.create_user(
  40. "Bob", "bob@boberson.com", "Pass.123")
  41. self.assertEqual(self.thread.replies, 0)
  42. datetime = timezone.now() + timedelta(5)
  43. post = Post.objects.create(
  44. category=self.category,
  45. thread=self.thread,
  46. poster=user,
  47. poster_name=user.username,
  48. poster_ip='127.0.0.1',
  49. original="Hello! I am test message!",
  50. parsed="<p>Hello! I am test message!</p>",
  51. checksum="nope",
  52. posted_on=datetime,
  53. updated_on=datetime
  54. )
  55. # first sync call, updates last thread
  56. self.thread.synchronize()
  57. self.assertEqual(self.thread.last_post, post)
  58. self.assertEqual(self.thread.last_post_on, post.posted_on)
  59. self.assertEqual(self.thread.last_poster, user)
  60. self.assertEqual(self.thread.last_poster_name, user.username)
  61. self.assertEqual(self.thread.last_poster_slug, user.slug)
  62. self.assertFalse(self.thread.has_reported_posts)
  63. self.assertFalse(self.thread.has_unapproved_posts)
  64. self.assertFalse(self.thread.has_hidden_posts)
  65. self.assertEqual(self.thread.replies, 1)
  66. # add unapproved post
  67. unapproved_post = Post.objects.create(
  68. category=self.category,
  69. thread=self.thread,
  70. poster=user,
  71. poster_name=user.username,
  72. poster_ip='127.0.0.1',
  73. original="Hello! I am test message!",
  74. parsed="<p>Hello! I am test message!</p>",
  75. checksum="nope",
  76. posted_on=datetime + timedelta(5),
  77. updated_on=datetime + timedelta(5),
  78. is_unapproved=True
  79. )
  80. self.thread.synchronize()
  81. self.assertEqual(self.thread.last_post, post)
  82. self.assertEqual(self.thread.last_post_on, post.posted_on)
  83. self.assertEqual(self.thread.last_poster, user)
  84. self.assertEqual(self.thread.last_poster_name, user.username)
  85. self.assertEqual(self.thread.last_poster_slug, user.slug)
  86. self.assertFalse(self.thread.has_reported_posts)
  87. self.assertTrue(self.thread.has_unapproved_posts)
  88. self.assertFalse(self.thread.has_hidden_posts)
  89. self.assertEqual(self.thread.replies, 1)
  90. # add hidden post
  91. hidden_post = Post.objects.create(
  92. category=self.category,
  93. thread=self.thread,
  94. poster=user,
  95. poster_name=user.username,
  96. poster_ip='127.0.0.1',
  97. original="Hello! I am test message!",
  98. parsed="<p>Hello! I am test message!</p>",
  99. checksum="nope",
  100. posted_on=datetime + timedelta(10),
  101. updated_on=datetime + timedelta(10),
  102. is_hidden=True
  103. )
  104. self.thread.synchronize()
  105. self.assertEqual(self.thread.last_post, hidden_post)
  106. self.assertEqual(self.thread.last_post_on, hidden_post.posted_on)
  107. self.assertEqual(self.thread.last_poster, user)
  108. self.assertEqual(self.thread.last_poster_name, user.username)
  109. self.assertEqual(self.thread.last_poster_slug, user.slug)
  110. self.assertFalse(self.thread.has_reported_posts)
  111. self.assertTrue(self.thread.has_unapproved_posts)
  112. self.assertTrue(self.thread.has_hidden_posts)
  113. self.assertEqual(self.thread.replies, 2)
  114. # unhide post
  115. hidden_post.is_hidden = False
  116. hidden_post.save()
  117. # last post changed to unhidden one
  118. self.thread.synchronize()
  119. self.assertEqual(self.thread.last_post, hidden_post)
  120. self.assertEqual(self.thread.last_post_on, hidden_post.posted_on)
  121. self.assertEqual(self.thread.last_poster, user)
  122. self.assertEqual(self.thread.last_poster_name, user.username)
  123. self.assertEqual(self.thread.last_poster_slug, user.slug)
  124. self.assertFalse(self.thread.has_reported_posts)
  125. self.assertTrue(self.thread.has_unapproved_posts)
  126. self.assertFalse(self.thread.has_hidden_posts)
  127. self.assertEqual(self.thread.replies, 2)
  128. # unmoderate post
  129. unapproved_post.is_unapproved = False
  130. unapproved_post.save()
  131. # last post not changed, but flags and count did
  132. self.thread.synchronize()
  133. self.assertEqual(self.thread.last_post, hidden_post)
  134. self.assertEqual(self.thread.last_post_on, hidden_post.posted_on)
  135. self.assertEqual(self.thread.last_poster, user)
  136. self.assertEqual(self.thread.last_poster_name, user.username)
  137. self.assertEqual(self.thread.last_poster_slug, user.slug)
  138. self.assertFalse(self.thread.has_reported_posts)
  139. self.assertFalse(self.thread.has_unapproved_posts)
  140. self.assertFalse(self.thread.has_hidden_posts)
  141. self.assertEqual(self.thread.replies, 3)
  142. # add event post
  143. event = Post.objects.create(
  144. category=self.category,
  145. thread=self.thread,
  146. poster=user,
  147. poster_name=user.username,
  148. poster_ip='127.0.0.1',
  149. original="-",
  150. parsed="-",
  151. checksum="nope",
  152. posted_on=datetime + timedelta(10),
  153. updated_on=datetime + timedelta(10),
  154. is_event=True
  155. )
  156. self.thread.synchronize()
  157. self.assertEqual(self.thread.last_post, event)
  158. self.assertEqual(self.thread.last_post_on, event.posted_on)
  159. self.assertEqual(self.thread.last_poster, user)
  160. self.assertEqual(self.thread.last_poster_name, user.username)
  161. self.assertEqual(self.thread.last_poster_slug, user.slug)
  162. self.assertTrue(self.thread.last_post_is_event)
  163. self.assertTrue(self.thread.has_events)
  164. self.assertFalse(self.thread.has_reported_posts)
  165. self.assertFalse(self.thread.has_unapproved_posts)
  166. self.assertFalse(self.thread.has_hidden_posts)
  167. # events don't count to reply count
  168. self.assertEqual(self.thread.replies, 3)
  169. # create another post to provoke other has_events resolution path
  170. Post.objects.create(
  171. category=self.category,
  172. thread=self.thread,
  173. poster=user,
  174. poster_name=user.username,
  175. poster_ip='127.0.0.1',
  176. original="Hello! I am test message!",
  177. parsed="<p>Hello! I am test message!</p>",
  178. checksum="nope",
  179. posted_on=datetime,
  180. updated_on=datetime
  181. )
  182. self.thread.synchronize()
  183. self.assertFalse(self.thread.last_post_is_event)
  184. self.assertTrue(self.thread.has_events)
  185. # remove event
  186. event.delete()
  187. self.thread.synchronize()
  188. self.assertFalse(self.thread.last_post_is_event)
  189. self.assertFalse(self.thread.has_events)
  190. # has poll flag
  191. self.assertFalse(self.thread.has_poll)
  192. Poll.objects.create(
  193. thread=self.thread,
  194. category=self.category,
  195. poster_name='test',
  196. poster_slug='test',
  197. poster_ip='127.0.0.1',
  198. choices=[]
  199. )
  200. self.thread.synchronize()
  201. self.assertTrue(self.thread.has_poll)
  202. def test_set_first_post(self):
  203. """set_first_post sets first post and poster data on thread"""
  204. user = UserModel.objects.create_user(
  205. "Bob", "bob@boberson.com", "Pass.123")
  206. datetime = timezone.now() + timedelta(5)
  207. post = Post.objects.create(
  208. category=self.category,
  209. thread=self.thread,
  210. poster=user,
  211. poster_name=user.username,
  212. poster_ip='127.0.0.1',
  213. original="Hello! I am test message!",
  214. parsed="<p>Hello! I am test message!</p>",
  215. checksum="nope",
  216. posted_on=datetime,
  217. updated_on=datetime
  218. )
  219. self.thread.set_first_post(post)
  220. self.assertEqual(self.thread.first_post, post)
  221. self.assertEqual(self.thread.started_on, post.posted_on)
  222. self.assertEqual(self.thread.starter, user)
  223. self.assertEqual(self.thread.starter_name, user.username)
  224. self.assertEqual(self.thread.starter_slug, user.slug)
  225. def test_set_last_post(self):
  226. """set_last_post sets first post and poster data on thread"""
  227. user = UserModel.objects.create_user(
  228. "Bob", "bob@boberson.com", "Pass.123")
  229. datetime = timezone.now() + timedelta(5)
  230. post = Post.objects.create(
  231. category=self.category,
  232. thread=self.thread,
  233. poster=user,
  234. poster_name=user.username,
  235. poster_ip='127.0.0.1',
  236. original="Hello! I am test message!",
  237. parsed="<p>Hello! I am test message!</p>",
  238. checksum="nope",
  239. posted_on=datetime,
  240. updated_on=datetime
  241. )
  242. self.thread.set_last_post(post)
  243. self.assertEqual(self.thread.last_post, post)
  244. self.assertEqual(self.thread.last_post_on, post.posted_on)
  245. self.assertEqual(self.thread.last_poster, user)
  246. self.assertEqual(self.thread.last_poster_name, user.username)
  247. self.assertEqual(self.thread.last_poster_slug, user.slug)
  248. def test_move(self):
  249. """move(new_category) moves thread to other category"""
  250. # pick category instead of category (so we don't have to create one)
  251. root_category = Category.objects.root_category()
  252. Category(
  253. name='New Category',
  254. slug='new-category',
  255. ).insert_at(root_category, position='last-child', save=True)
  256. new_category = Category.objects.get(slug='new-category')
  257. self.thread.move(new_category)
  258. self.assertEqual(self.thread.category, new_category)
  259. for post in self.thread.post_set.all():
  260. self.assertEqual(post.category_id, new_category.id)
  261. def test_merge(self):
  262. """merge(other_thread) moves other thread content to this thread"""
  263. with self.assertRaises(ValueError):
  264. self.thread.merge(self.thread)
  265. datetime = timezone.now() + timedelta(5)
  266. other_thread = Thread(
  267. category=self.category,
  268. started_on=datetime,
  269. starter_name='Tester',
  270. starter_slug='tester',
  271. last_post_on=datetime,
  272. last_poster_name='Tester',
  273. last_poster_slug='tester'
  274. )
  275. other_thread.set_title("Other thread")
  276. other_thread.save()
  277. post = Post.objects.create(
  278. category=self.category,
  279. thread=other_thread,
  280. poster_name='Admin',
  281. poster_ip='127.0.0.1',
  282. original="Hello! I am other message!",
  283. parsed="<p>Hello! I am other message!</p>",
  284. checksum="nope",
  285. posted_on=datetime,
  286. updated_on=datetime
  287. )
  288. other_thread.first_post = post
  289. other_thread.last_post = post
  290. other_thread.save()
  291. self.thread.merge(other_thread)
  292. self.thread.synchronize()
  293. self.assertEqual(self.thread.replies, 1)
  294. self.assertEqual(self.thread.last_post, post)
  295. self.assertEqual(self.thread.last_post_on, post.posted_on)
  296. self.assertEqual(self.thread.last_poster_name, "Admin")
  297. self.assertEqual(self.thread.last_poster_slug, "admin")
  298. def test_delete_private_thread(self):
  299. """
  300. private thread gets deleted automatically
  301. when there are no participants left in it
  302. """
  303. user_a = UserModel.objects.create_user(
  304. "Bob", "bob@boberson.com", "Pass.123")
  305. user_b = UserModel.objects.create_user(
  306. "Weebl", "weebl@weeblson.com", "Pass.123")
  307. ThreadParticipant.objects.add_participants(self.thread, [user_a, user_b])
  308. self.assertEqual(self.thread.participants.count(), 2)
  309. user_a.delete()
  310. Thread.objects.get(id=self.thread.id)
  311. user_b.delete()
  312. with self.assertRaises(Thread.DoesNotExist):
  313. Thread.objects.get(id=self.thread.id)