test_forum_models.py 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570
  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.moderators = [moderator_user]
  88. forum.save()
  89. assert forum.title == "Test Forum"
  90. assert forum.moderators == [moderator_user]
  91. def test_forum_delete(forum):
  92. """Test the delete forum method."""
  93. forum.delete()
  94. forum = Forum.query.filter_by(id=forum.id).first()
  95. assert forum is None
  96. def test_forum_delete_with_user_and_topic(topic, user):
  97. """Now test the delete forum method with a topic inside."""
  98. assert user.post_count == 1
  99. topic.forum.delete([user])
  100. forum = Forum.query.filter_by(id=topic.forum_id).first()
  101. assert forum is None
  102. assert user.post_count == 0
  103. def test_forum_update_last_post(topic, user):
  104. """Test the update last post method."""
  105. post = Post(content="Test Content 2")
  106. post.save(topic=topic, user=user)
  107. assert topic.forum.last_post == post
  108. post.delete()
  109. topic.forum.update_last_post()
  110. assert topic.forum.last_post == topic.first_post
  111. def test_forum_update_read(database, user, topic):
  112. """Test the update read method."""
  113. forumsread = ForumsRead.query.\
  114. filter(ForumsRead.user_id == user.id,
  115. ForumsRead.forum_id == topic.forum_id).first()
  116. topicsread = TopicsRead.query.\
  117. filter(TopicsRead.user_id == user.id,
  118. TopicsRead.topic_id == topic.id).first()
  119. forum = topic.forum
  120. with current_app.test_request_context():
  121. # Test with logged in user
  122. login_user(user)
  123. # Should return False because topicsread is None
  124. assert not forum.update_read(current_user, forumsread, topicsread)
  125. # This is the first time the user visits the topic
  126. topicsread = TopicsRead()
  127. topicsread.user_id = user.id
  128. topicsread.topic_id = topic.id
  129. topicsread.forum_id = topic.forum_id
  130. topicsread.last_read = datetime.utcnow()
  131. topicsread.save()
  132. # hence, we also need to create a new forumsread entry
  133. assert forum.update_read(current_user, forumsread, topicsread)
  134. forumsread = ForumsRead.query.\
  135. filter(ForumsRead.user_id == user.id,
  136. ForumsRead.forum_id == topic.forum_id).first()
  137. # everything should be up-to-date now
  138. assert not forum.update_read(current_user, forumsread, topicsread)
  139. post = Post(content="Test Content")
  140. post.save(user=user, topic=topic)
  141. # Updating the topicsread tracker
  142. topicsread.last_read = datetime.utcnow()
  143. topicsread.save()
  144. # now the forumsread tracker should also need a update
  145. assert forum.update_read(current_user, forumsread, topicsread)
  146. logout_user()
  147. # should fail because the user is logged out
  148. assert not forum.update_read(current_user, forumsread, topicsread)
  149. def test_forum_update_read_two_topics(database, user, topic, topic_moderator):
  150. """Test if the ForumsRead tracker will be updated if there are two topics
  151. and where one is unread and the other is read.
  152. """
  153. forumsread = ForumsRead.query.\
  154. filter(ForumsRead.user_id == user.id,
  155. ForumsRead.forum_id == topic.forum_id).first()
  156. forum = topic.forum
  157. with current_app.test_request_context():
  158. # Test with logged in user
  159. login_user(user)
  160. # This is the first time the user visits the topic
  161. topicsread = TopicsRead()
  162. topicsread.user_id = user.id
  163. topicsread.topic_id = topic.id
  164. topicsread.forum_id = topic.forum_id
  165. topicsread.last_read = datetime.utcnow()
  166. topicsread.save()
  167. # will not create a entry because there is still one unread topic
  168. assert not forum.update_read(current_user, forumsread, topicsread)
  169. def test_forum_url(forum):
  170. assert forum.url == "http://localhost:5000/forum/1-test-forum"
  171. def test_forum_slugify(forum):
  172. assert forum.slug == "test-forum"
  173. def test_forum_get_forum(forum, user):
  174. with current_app.test_request_context():
  175. # Test with logged in user
  176. login_user(user)
  177. forum_with_forumsread = \
  178. Forum.get_forum(forum_id=forum.id, user=current_user)
  179. assert forum_with_forumsread == (forum, None)
  180. # Test with logged out user
  181. logout_user()
  182. forum_with_forumsread = \
  183. Forum.get_forum(forum_id=forum.id, user=current_user)
  184. assert forum_with_forumsread == (forum, None)
  185. def test_forum_get_topics(topic, user):
  186. forum = topic.forum
  187. with current_app.test_request_context():
  188. # Test with logged in user
  189. login_user(user)
  190. topics = Forum.get_topics(forum_id=forum.id, user=current_user)
  191. assert topics.items == [(topic, None)]
  192. # Test with logged out user
  193. logout_user()
  194. topics = Forum.get_topics(forum_id=forum.id, user=current_user)
  195. assert topics.items == [(topic, None)]
  196. def test_topic_save(forum, user):
  197. """Test the save topic method with creating and editing a topic."""
  198. post = Post(content="Test Content")
  199. topic = Topic(title="Test Title")
  200. assert forum.last_post_id is None
  201. assert forum.post_count == 0
  202. assert forum.topic_count == 0
  203. topic.save(forum=forum, post=post, user=user)
  204. assert topic.title == "Test Title"
  205. topic.title = "Test Edit Title"
  206. topic.save()
  207. assert topic.title == "Test Edit Title"
  208. # The first post in the topic is also the last post
  209. assert topic.first_post_id == post.id
  210. assert topic.last_post_id == post.id
  211. assert forum.last_post_id == post.id
  212. assert forum.post_count == 1
  213. assert forum.topic_count == 1
  214. def test_topic_delete(topic):
  215. """Test the delete topic method"""
  216. assert topic.user.post_count == 1
  217. assert topic.post_count == 1
  218. assert topic.forum.topic_count == 1
  219. assert topic.forum.post_count == 1
  220. topic.delete(users=[topic.user])
  221. forum = Forum.query.filter_by(id=topic.forum_id).first()
  222. user = User.query.filter_by(id=topic.user_id).first()
  223. topic = Topic.query.filter_by(id=topic.id).first()
  224. assert topic is None
  225. assert user.post_count == 0
  226. assert forum.topic_count == 0
  227. assert forum.post_count == 0
  228. assert forum.last_post_id is None
  229. def test_topic_move(topic):
  230. """Tests the topic move method."""
  231. forum_other = Forum(title="Test Forum 2", category_id=1)
  232. forum_other.save()
  233. forum_old = Forum.query.filter_by(id=topic.forum_id).first()
  234. assert topic.move(forum_other)
  235. assert forum_old.topics.all() == []
  236. assert forum_old.last_post_id is None
  237. assert forum_old.topic_count == 0
  238. assert forum_old.post_count == 0
  239. assert forum_other.last_post_id == topic.last_post_id
  240. assert forum_other.topic_count == 1
  241. assert forum_other.post_count == 1
  242. def test_topic_move_same_forum(topic):
  243. """You cannot move a topic within the same forum."""
  244. assert not topic.move(topic.forum)
  245. def test_topic_tracker_needs_update(database, user, topic):
  246. """Tests if the topicsread tracker needs an update if a new post has been
  247. submitted.
  248. """
  249. forumsread = ForumsRead.query.\
  250. filter(ForumsRead.user_id == user.id,
  251. ForumsRead.forum_id == topic.forum_id).first()
  252. topicsread = TopicsRead.query.\
  253. filter(TopicsRead.user_id == user.id,
  254. TopicsRead.topic_id == topic.id).first()
  255. with current_app.test_request_context():
  256. assert topic.tracker_needs_update(forumsread, topicsread)
  257. # Update the tracker
  258. topicsread = TopicsRead()
  259. topicsread.user_id = user.id
  260. topicsread.topic_id = topic.id
  261. topicsread.forum_id = topic.forum_id
  262. topicsread.last_read = datetime.utcnow()
  263. topicsread.save()
  264. forumsread = ForumsRead()
  265. forumsread.user_id = user.id
  266. forumsread.forum_id = topic.forum_id
  267. forumsread.last_read = datetime.utcnow()
  268. forumsread.save()
  269. # Now the topic should be read
  270. assert not topic.tracker_needs_update(forumsread, topicsread)
  271. post = Post(content="Test Content")
  272. post.save(topic=topic, user=user)
  273. assert topic.tracker_needs_update(forumsread, topicsread)
  274. def test_topic_tracker_needs_update_cleared(database, user, topic):
  275. """Tests if the topicsread needs an update if the forum has been marked
  276. as cleared.
  277. """
  278. forumsread = ForumsRead.query.\
  279. filter(ForumsRead.user_id == user.id,
  280. ForumsRead.forum_id == topic.forum_id).first()
  281. topicsread = TopicsRead.query.\
  282. filter(TopicsRead.user_id == user.id,
  283. TopicsRead.topic_id == topic.id).first()
  284. with current_app.test_request_context():
  285. assert topic.tracker_needs_update(forumsread, topicsread)
  286. # Update the tracker
  287. forumsread = ForumsRead()
  288. forumsread.user_id = user.id
  289. forumsread.forum_id = topic.forum_id
  290. forumsread.last_read = datetime.utcnow()
  291. forumsread.cleared = datetime.utcnow()
  292. forumsread.save()
  293. # Now the topic should be read
  294. assert not topic.tracker_needs_update(forumsread, topicsread)
  295. def test_topic_update_read(database, user, topic):
  296. """Tests the update read method if the topic is unread/read."""
  297. forumsread = ForumsRead.query.\
  298. filter(ForumsRead.user_id == user.id,
  299. ForumsRead.forum_id == topic.forum_id).first()
  300. with current_app.test_request_context():
  301. # Test with logged in user
  302. login_user(user)
  303. assert current_user.is_authenticated
  304. # Update the tracker
  305. assert topic.update_read(current_user, topic.forum, forumsread)
  306. # Because the tracker is already up-to-date, it shouldn't update it
  307. # again.
  308. assert not topic.update_read(current_user, topic.forum, forumsread)
  309. # Adding a new post - now the tracker shouldn't be up-to-date anymore.
  310. post = Post(content="Test Content")
  311. post.save(topic=topic, user=user)
  312. forumsread = ForumsRead.query.\
  313. filter(ForumsRead.user_id == user.id,
  314. ForumsRead.forum_id == topic.forum_id).first()
  315. # Test tracker length
  316. flaskbb_config["TRACKER_LENGTH"] = 0
  317. assert not topic.update_read(current_user, topic.forum, forumsread)
  318. flaskbb_config["TRACKER_LENGTH"] = 1
  319. assert topic.update_read(current_user, topic.forum, forumsread)
  320. # Test with logged out user
  321. logout_user()
  322. assert not current_user.is_authenticated
  323. assert not topic.update_read(current_user, topic.forum, forumsread)
  324. def test_topic_url(topic):
  325. assert topic.url == "http://localhost:5000/topic/1-test-topic-normal"
  326. def test_topic_slug(topic):
  327. assert topic.slug == "test-topic-normal"
  328. def test_post_save(topic, user):
  329. """Tests the save post method."""
  330. post = Post(content="Test Content")
  331. post.save(topic=topic, user=user)
  332. assert post.content == "Test Content"
  333. post.content = "Test Edit Content"
  334. post.save()
  335. assert post.content == "Test Edit Content"
  336. assert topic.user.post_count == 2
  337. assert topic.post_count == 2
  338. assert topic.last_post == post
  339. assert topic.forum.post_count == 2
  340. def test_post_delete(topic):
  341. """Tests the delete post method with three different post types.
  342. The three types are:
  343. * First Post
  344. * A post between the first and last post (middle)
  345. * Last Post
  346. """
  347. post_middle = Post(content="Test Content Middle")
  348. post_middle.save(topic=topic, user=topic.user)
  349. post_last = Post(content="Test Content Last")
  350. post_last.save(topic=topic, user=topic.user)
  351. assert topic.post_count == 3
  352. assert topic.forum.post_count == 3
  353. assert topic.user.post_count == 3
  354. post_middle.delete()
  355. # Check the last posts
  356. assert topic.last_post == post_last
  357. assert topic.forum.last_post == post_last
  358. post_last.delete()
  359. # That was a bit trickier..
  360. assert topic.post_count == 1
  361. assert topic.forum.post_count == 1
  362. assert topic.user.post_count == 1
  363. assert topic.first_post_id == topic.last_post_id
  364. assert topic.forum.last_post_id == topic.last_post_id
  365. def test_report(topic, user):
  366. """Tests if the reports can be saved/edited and deleted with the
  367. implemented save and delete methods."""
  368. report = Report(reason="Test Report")
  369. report.save(user=user, post=topic.first_post)
  370. assert report.reason == "Test Report"
  371. report.reason = "Test Report Edited"
  372. report.save()
  373. assert report.reason == "Test Report Edited"
  374. report.delete()
  375. report = Report.query.filter_by(id=report.id).first()
  376. assert report is None
  377. def test_forumsread(topic, user):
  378. """Tests if the forumsread tracker can be saved/edited and deleted with the
  379. implemented save and delete methods."""
  380. forumsread = ForumsRead()
  381. forumsread.user_id = user.id
  382. forumsread.forum_id = topic.forum_id
  383. forumsread.last_read = datetime.utcnow()
  384. forumsread.save()
  385. assert forumsread is not None
  386. forumsread.delete()
  387. forumsread = ForumsRead.query.filter_by(forum_id=forumsread.forum_id).first()
  388. assert forumsread is None
  389. def test_topicsread(topic, user):
  390. """Tests if the topicsread trakcer can be saved/edited and deleted with the
  391. implemented save and delete methods."""
  392. topicsread = TopicsRead()
  393. topicsread.user_id = user.id
  394. topicsread.topic_id = topic.id
  395. topicsread.forum_id = topic.forum_id
  396. topicsread.last_read = datetime.utcnow()
  397. topicsread.save()
  398. assert topicsread is not None
  399. topicsread.delete()
  400. topicsread = TopicsRead.query.filter_by(topic_id=topicsread.topic_id).first()
  401. assert topicsread is None