test_forum_models.py 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573
  1. from datetime import datetime
  2. from flask import current_app
  3. from flask_login import login_user, current_user, logout_user
  4. from flaskbb.forum.models import Category, Forum, Topic, Post, ForumsRead, \
  5. TopicsRead, Report
  6. from flaskbb.user.models import User
  7. from flaskbb.utils.settings import flaskbb_config
  8. def test_category_save(database):
  9. """Test the save category method."""
  10. category = Category(title="Test Category")
  11. category.save()
  12. assert category.title == "Test Category"
  13. def test_category_delete(category):
  14. """Test the delete category method."""
  15. category.delete()
  16. category = Category.query.filter_by(id=category.id).first()
  17. assert category is None
  18. def test_category_delete_with_user(topic):
  19. """Test the delete category method with recounting the users post counts."""
  20. user = topic.user
  21. forum = topic.forum
  22. category = topic.forum.category
  23. assert user.post_count == 1
  24. assert forum.post_count == 1
  25. assert forum.topic_count == 1
  26. category.delete([user])
  27. assert user.post_count == 0
  28. category = Category.query.filter_by(id=category.id).first()
  29. topic = Topic.query.filter_by(id=topic.id).first()
  30. assert category is None
  31. # The topic should also be deleted
  32. assert topic is None
  33. def test_category_delete_with_forum(forum):
  34. """When deleting a category, all of his forums should also be deleted."""
  35. forum.category.delete()
  36. assert forum is not None
  37. assert forum.category is not None
  38. category = Category.query.filter_by(id=forum.category.id).first()
  39. forum = Forum.query.filter_by(id=forum.id).first()
  40. assert forum is None
  41. assert category is None
  42. def test_category_get_forums(forum, user):
  43. category = forum.category
  44. with current_app.test_request_context():
  45. # Test with logged in user
  46. login_user(user)
  47. assert current_user.is_authenticated()
  48. cat, forums = Category.get_forums(category.id, current_user)
  49. # Check if it is a list because in a category there are normally more
  50. # than one forum in it (not in these tests)
  51. assert isinstance(forums, list) is True
  52. assert forums == [(forum, None)]
  53. assert cat == category
  54. # Test the same thing with a logged out user
  55. logout_user()
  56. assert not current_user.is_authenticated()
  57. cat, forums = Category.get_forums(category.id, current_user)
  58. # Check if it is a list because in a category there are normally more
  59. # than one forum in it (not in these tests)
  60. assert isinstance(forums, list) is True
  61. assert forums == [(forum, None)]
  62. assert cat == category
  63. def test_category_get_all(forum, user):
  64. category = forum.category
  65. with current_app.test_request_context():
  66. # Test with logged in user
  67. login_user(user)
  68. assert current_user.is_authenticated()
  69. categories = Category.get_all(current_user)
  70. # All categories are stored in a list
  71. assert isinstance(categories, list)
  72. # The forums for a category are also stored in a list
  73. assert isinstance(categories[0][1], list)
  74. assert categories == [(category, [(forum, None)])]
  75. # Test with logged out user
  76. logout_user()
  77. assert not current_user.is_authenticated()
  78. categories = Category.get_all(current_user)
  79. # All categories are stored in a list
  80. assert isinstance(categories, list)
  81. # The forums for a category are also stored in a list
  82. assert isinstance(categories[0][1], list)
  83. assert categories == [(category, [(forum, None)])]
  84. def test_forum_save(category, moderator_user):
  85. """Test the save forum method"""
  86. forum = Forum(title="Test Forum", category_id=category.id)
  87. forum.save()
  88. assert forum.title == "Test Forum"
  89. # Test with adding a moderator
  90. forum.save([moderator_user])
  91. assert forum.moderators == [moderator_user]
  92. def test_forum_delete(forum):
  93. """Test the delete forum method."""
  94. forum.delete()
  95. forum = Forum.query.filter_by(id=forum.id).first()
  96. assert forum is None
  97. def test_forum_delete_with_user_and_topic(topic, user):
  98. """Now test the delete forum method with a topic inside."""
  99. assert user.post_count == 1
  100. topic.forum.delete([user])
  101. forum = Forum.query.filter_by(id=topic.forum_id).first()
  102. assert forum is None
  103. assert user.post_count == 0
  104. def test_forum_update_last_post(topic, user):
  105. """Test the update last post method."""
  106. post = Post(content="Test Content 2")
  107. post.save(topic=topic, user=user)
  108. assert topic.forum.last_post == post
  109. post.delete()
  110. topic.forum.update_last_post()
  111. assert topic.forum.last_post == topic.first_post
  112. def test_forum_update_read(database, user, topic):
  113. """Test the update read method."""
  114. forumsread = ForumsRead.query.\
  115. filter(ForumsRead.user_id == user.id,
  116. ForumsRead.forum_id == topic.forum_id).first()
  117. topicsread = TopicsRead.query.\
  118. filter(TopicsRead.user_id == user.id,
  119. TopicsRead.topic_id == topic.id).first()
  120. forum = topic.forum
  121. with current_app.test_request_context():
  122. # Test with logged in user
  123. login_user(user)
  124. # Should return False because topicsread is None
  125. assert not forum.update_read(current_user, forumsread, topicsread)
  126. # This is the first time the user visits the topic
  127. topicsread = TopicsRead()
  128. topicsread.user_id = user.id
  129. topicsread.topic_id = topic.id
  130. topicsread.forum_id = topic.forum_id
  131. topicsread.last_read = datetime.utcnow()
  132. topicsread.save()
  133. # hence, we also need to create a new forumsread entry
  134. assert forum.update_read(current_user, forumsread, topicsread)
  135. forumsread = ForumsRead.query.\
  136. filter(ForumsRead.user_id == user.id,
  137. ForumsRead.forum_id == topic.forum_id).first()
  138. # everything should be up-to-date now
  139. assert not forum.update_read(current_user, forumsread, topicsread)
  140. post = Post(content="Test Content")
  141. post.save(user=user, topic=topic)
  142. # Updating the topicsread tracker
  143. topicsread.last_read = datetime.utcnow()
  144. topicsread.save()
  145. # now the forumsread tracker should also need a update
  146. assert forum.update_read(current_user, forumsread, topicsread)
  147. logout_user()
  148. # should fail because the user is logged out
  149. assert not forum.update_read(current_user, forumsread, topicsread)
  150. def test_forum_update_read_two_topics(database, user, topic, topic_moderator):
  151. """Test if the ForumsRead tracker will be updated if there are two topics
  152. and where one is unread and the other is read.
  153. """
  154. forumsread = ForumsRead.query.\
  155. filter(ForumsRead.user_id == user.id,
  156. ForumsRead.forum_id == topic.forum_id).first()
  157. forum = topic.forum
  158. with current_app.test_request_context():
  159. # Test with logged in user
  160. login_user(user)
  161. # This is the first time the user visits the topic
  162. topicsread = TopicsRead()
  163. topicsread.user_id = user.id
  164. topicsread.topic_id = topic.id
  165. topicsread.forum_id = topic.forum_id
  166. topicsread.last_read = datetime.utcnow()
  167. topicsread.save()
  168. # will not create a entry because there is still one unread topic
  169. assert not forum.update_read(current_user, forumsread, topicsread)
  170. def test_forum_url(forum):
  171. assert forum.url == "http://localhost:5000/forum/1-test-forum"
  172. def test_forum_slugify(forum):
  173. assert forum.slug == "test-forum"
  174. def test_forum_get_forum(forum, user):
  175. with current_app.test_request_context():
  176. # Test with logged in user
  177. login_user(user)
  178. forum_with_forumsread = \
  179. Forum.get_forum(forum_id=forum.id, user=current_user)
  180. assert forum_with_forumsread == (forum, None)
  181. # Test with logged out user
  182. logout_user()
  183. forum_with_forumsread = \
  184. Forum.get_forum(forum_id=forum.id, user=current_user)
  185. assert forum_with_forumsread == (forum, None)
  186. def test_forum_get_topics(topic, user):
  187. forum = topic.forum
  188. with current_app.test_request_context():
  189. # Test with logged in user
  190. login_user(user)
  191. topics = Forum.get_topics(forum_id=forum.id, user=current_user)
  192. assert topics.items == [(topic, None)]
  193. # Test with logged out user
  194. logout_user()
  195. topics = Forum.get_topics(forum_id=forum.id, user=current_user)
  196. assert topics.items == [(topic, None)]
  197. def test_topic_save(forum, user):
  198. """Test the save topic method with creating and editing a topic."""
  199. post = Post(content="Test Content")
  200. topic = Topic(title="Test Title")
  201. assert forum.last_post_id is None
  202. assert forum.post_count == 0
  203. assert forum.topic_count == 0
  204. topic.save(forum=forum, post=post, user=user)
  205. assert topic.title == "Test Title"
  206. topic.title = "Test Edit Title"
  207. topic.save()
  208. assert topic.title == "Test Edit Title"
  209. # The first post in the topic is also the last post
  210. assert topic.first_post_id == post.id
  211. assert topic.last_post_id == post.id
  212. assert forum.last_post_id == post.id
  213. assert forum.post_count == 1
  214. assert forum.topic_count == 1
  215. def test_topic_delete(topic):
  216. """Test the delete topic method"""
  217. assert topic.user.post_count == 1
  218. assert topic.post_count == 1
  219. assert topic.forum.topic_count == 1
  220. assert topic.forum.post_count == 1
  221. topic.delete(users=[topic.user])
  222. forum = Forum.query.filter_by(id=topic.forum_id).first()
  223. user = User.query.filter_by(id=topic.user_id).first()
  224. topic = Topic.query.filter_by(id=topic.id).first()
  225. assert topic is None
  226. assert user.post_count == 0
  227. assert forum.topic_count == 0
  228. assert forum.post_count == 0
  229. assert forum.last_post_id is None
  230. def test_topic_move(topic):
  231. """Tests the topic move method."""
  232. forum_other = Forum(title="Test Forum 2", category_id=1)
  233. forum_other.save()
  234. forum_old = Forum.query.filter_by(id=topic.forum_id).first()
  235. assert topic.move(forum_other)
  236. assert forum_old.topics.all() == []
  237. assert forum_old.last_post_id is None
  238. assert forum_old.topic_count == 0
  239. assert forum_old.post_count == 0
  240. assert forum_other.last_post_id == topic.last_post_id
  241. assert forum_other.topic_count == 1
  242. assert forum_other.post_count == 1
  243. def test_topic_move_same_forum(topic):
  244. """You cannot move a topic within the same forum."""
  245. assert not topic.move(topic.forum)
  246. def test_topic_tracker_needs_update(database, user, topic):
  247. """Tests if the topicsread tracker needs an update if a new post has been
  248. submitted.
  249. """
  250. forumsread = ForumsRead.query.\
  251. filter(ForumsRead.user_id == user.id,
  252. ForumsRead.forum_id == topic.forum_id).first()
  253. topicsread = TopicsRead.query.\
  254. filter(TopicsRead.user_id == user.id,
  255. TopicsRead.topic_id == topic.id).first()
  256. with current_app.test_request_context():
  257. assert topic.tracker_needs_update(forumsread, topicsread)
  258. # Update the tracker
  259. topicsread = TopicsRead()
  260. topicsread.user_id = user.id
  261. topicsread.topic_id = topic.id
  262. topicsread.forum_id = topic.forum_id
  263. topicsread.last_read = datetime.utcnow()
  264. topicsread.save()
  265. forumsread = ForumsRead()
  266. forumsread.user_id = user.id
  267. forumsread.forum_id = topic.forum_id
  268. forumsread.last_read = datetime.utcnow()
  269. forumsread.save()
  270. # Now the topic should be read
  271. assert not topic.tracker_needs_update(forumsread, topicsread)
  272. post = Post(content="Test Content")
  273. post.save(topic=topic, user=user)
  274. assert topic.tracker_needs_update(forumsread, topicsread)
  275. def test_topic_tracker_needs_update_cleared(database, user, topic):
  276. """Tests if the topicsread needs an update if the forum has been marked
  277. as cleared.
  278. """
  279. forumsread = ForumsRead.query.\
  280. filter(ForumsRead.user_id == user.id,
  281. ForumsRead.forum_id == topic.forum_id).first()
  282. topicsread = TopicsRead.query.\
  283. filter(TopicsRead.user_id == user.id,
  284. TopicsRead.topic_id == topic.id).first()
  285. with current_app.test_request_context():
  286. assert topic.tracker_needs_update(forumsread, topicsread)
  287. # Update the tracker
  288. forumsread = ForumsRead()
  289. forumsread.user_id = user.id
  290. forumsread.forum_id = topic.forum_id
  291. forumsread.last_read = datetime.utcnow()
  292. forumsread.cleared = datetime.utcnow()
  293. forumsread.save()
  294. # Now the topic should be read
  295. assert not topic.tracker_needs_update(forumsread, topicsread)
  296. def test_topic_update_read(database, user, topic):
  297. """Tests the update read method if the topic is unread/read."""
  298. forumsread = ForumsRead.query.\
  299. filter(ForumsRead.user_id == user.id,
  300. ForumsRead.forum_id == topic.forum_id).first()
  301. with current_app.test_request_context():
  302. # Test with logged in user
  303. login_user(user)
  304. assert current_user.is_authenticated()
  305. # Update the tracker
  306. assert topic.update_read(current_user, topic.forum, forumsread)
  307. # Because the tracker is already up-to-date, it shouldn't update it
  308. # again.
  309. assert not topic.update_read(current_user, topic.forum, forumsread)
  310. # Adding a new post - now the tracker shouldn't be up-to-date anymore.
  311. post = Post(content="Test Content")
  312. post.save(topic=topic, user=user)
  313. forumsread = ForumsRead.query.\
  314. filter(ForumsRead.user_id == user.id,
  315. ForumsRead.forum_id == topic.forum_id).first()
  316. # Test tracker length
  317. flaskbb_config["TRACKER_LENGTH"] = 0
  318. assert not topic.update_read(current_user, topic.forum, forumsread)
  319. flaskbb_config["TRACKER_LENGTH"] = 1
  320. assert topic.update_read(current_user, topic.forum, forumsread)
  321. # Test with logged out user
  322. logout_user()
  323. assert not current_user.is_authenticated()
  324. assert not topic.update_read(current_user, topic.forum, forumsread)
  325. def test_topic_url(topic):
  326. assert topic.url == "http://localhost:5000/topic/1-test-topic-normal"
  327. def test_topic_slug(topic):
  328. assert topic.slug == "test-topic-normal"
  329. def test_post_save(topic, user):
  330. """Tests the save post method."""
  331. post = Post(content="Test Content")
  332. post.save(topic=topic, user=user)
  333. assert post.content == "Test Content"
  334. post.content = "Test Edit Content"
  335. post.save()
  336. assert post.content == "Test Edit Content"
  337. assert topic.user.post_count == 2
  338. assert topic.post_count == 2
  339. assert topic.last_post == post
  340. assert topic.forum.post_count == 2
  341. def test_post_delete(topic):
  342. """Tests the delete post method with three different post types.
  343. The three types are:
  344. * First Post
  345. * A post between the first and last post (middle)
  346. * Last Post
  347. """
  348. post_middle = Post(content="Test Content Middle")
  349. post_middle.save(topic=topic, user=topic.user)
  350. post_last = Post(content="Test Content Last")
  351. post_last.save(topic=topic, user=topic.user)
  352. assert topic.post_count == 3
  353. assert topic.forum.post_count == 3
  354. assert topic.user.post_count == 3
  355. post_middle.delete()
  356. # Check the last posts
  357. assert topic.last_post == post_last
  358. assert topic.forum.last_post == post_last
  359. post_last.delete()
  360. # That was a bit trickier..
  361. assert topic.post_count == 1
  362. assert topic.forum.post_count == 1
  363. assert topic.user.post_count == 1
  364. assert topic.first_post_id == topic.last_post_id
  365. assert topic.forum.last_post_id == topic.last_post_id
  366. def test_report(topic, user):
  367. """Tests if the reports can be saved/edited and deleted with the
  368. implemented save and delete methods."""
  369. report = Report(reason="Test Report")
  370. report.save(user=user, post=topic.first_post)
  371. assert report.reason == "Test Report"
  372. report.reason = "Test Report Edited"
  373. report.save()
  374. assert report.reason == "Test Report Edited"
  375. report.delete()
  376. report = Report.query.filter_by(id=report.id).first()
  377. assert report is None
  378. def test_forumsread(topic, user):
  379. """Tests if the forumsread tracker can be saved/edited and deleted with the
  380. implemented save and delete methods."""
  381. forumsread = ForumsRead()
  382. forumsread.user_id = user.id
  383. forumsread.forum_id = topic.forum_id
  384. forumsread.last_read = datetime.utcnow()
  385. forumsread.save()
  386. assert forumsread is not None
  387. forumsread.delete()
  388. forumsread = ForumsRead.query.filter_by(forum_id=forumsread.forum_id).first()
  389. assert forumsread is None
  390. def test_topicsread(topic, user):
  391. """Tests if the topicsread trakcer can be saved/edited and deleted with the
  392. implemented save and delete methods."""
  393. topicsread = TopicsRead()
  394. topicsread.user_id = user.id
  395. topicsread.topic_id = topic.id
  396. topicsread.forum_id = topic.forum_id
  397. topicsread.last_read = datetime.utcnow()
  398. topicsread.save()
  399. assert topicsread is not None
  400. topicsread.delete()
  401. topicsread = TopicsRead.query.filter_by(topic_id=topicsread.topic_id).first()
  402. assert topicsread is None