test_threadslists_views.py 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386
  1. from misago.acl.testutils import override_acl
  2. from misago.categories.models import Category
  3. from misago.core import threadstore
  4. from misago.core.cache import cache
  5. from misago.users.testutils import AuthenticatedUserTestCase
  6. from misago.threads import testutils
  7. LISTS_URLS = (
  8. '',
  9. 'my/',
  10. 'new/',
  11. 'unread/',
  12. 'subscribed/'
  13. )
  14. class ThreadsListTestCase(AuthenticatedUserTestCase):
  15. def setUp(self):
  16. super(ThreadsListTestCase, self).setUp()
  17. cache.clear()
  18. threadstore.clear()
  19. self.root = Category.objects.root_category()
  20. self.first_category = Category.objects.get(slug='first-category')
  21. """
  22. Create categories tree for test cases:
  23. First category (created by migration)
  24. Category A
  25. + Category B
  26. + Subcategory C
  27. + Subcategory D
  28. Category E
  29. + Subcategory F
  30. """
  31. Category(
  32. name='Category A',
  33. slug='category-a',
  34. ).insert_at(self.root, position='last-child', save=True)
  35. Category(
  36. name='Category E',
  37. slug='category-e',
  38. ).insert_at(self.root, position='last-child', save=True)
  39. self.root = Category.objects.root_category()
  40. self.category_a = Category.objects.get(slug='category-a')
  41. Category(
  42. name='Category B',
  43. slug='category-b',
  44. ).insert_at(self.category_a, position='last-child', save=True)
  45. self.category_b = Category.objects.get(slug='category-b')
  46. Category(
  47. name='Category C',
  48. slug='category-c',
  49. ).insert_at(self.category_b, position='last-child', save=True)
  50. Category(
  51. name='Category D',
  52. slug='category-d',
  53. ).insert_at(self.category_b, position='last-child', save=True)
  54. self.category_c = Category.objects.get(slug='category-c')
  55. self.category_d = Category.objects.get(slug='category-d')
  56. self.category_e = Category.objects.get(slug='category-e')
  57. Category(
  58. name='Category F',
  59. slug='category-f',
  60. ).insert_at(self.category_e, position='last-child', save=True)
  61. self.category_f = Category.objects.get(slug='category-f')
  62. self.access_all_categories()
  63. def access_all_categories(self, extra=None):
  64. cache.clear()
  65. threadstore.clear()
  66. categories_acl = {'categories': {}, 'visible_categories': []}
  67. for category in Category.objects.all_categories():
  68. categories_acl['visible_categories'].append(category.pk)
  69. categories_acl['categories'][category.pk] = {
  70. 'can_see': 1,
  71. 'can_browse': 1,
  72. 'can_see_all_threads': 1,
  73. 'can_see_own_threads': 0,
  74. 'can_hide_threads': 0,
  75. 'can_review_moderated_content': 0,
  76. }
  77. if extra:
  78. categories_acl['categories'][category.pk].update(extra)
  79. override_acl(self.user, categories_acl)
  80. return categories_acl
  81. class ListsTests(ThreadsListTestCase):
  82. def test_list_renders_empty(self):
  83. """empty threads list renders"""
  84. for url in LISTS_URLS:
  85. self.access_all_categories()
  86. response = self.client.get('/' + url)
  87. self.assertEqual(response.status_code, 200)
  88. self.assertIn("empty-message", response.content)
  89. self.access_all_categories()
  90. response = self.client.get(self.category_b.get_absolute_url() + url)
  91. self.assertEqual(response.status_code, 200)
  92. self.assertIn(self.category_b.name, response.content)
  93. self.assertIn("empty-message", response.content)
  94. def test_list_authenticated_only_views(self):
  95. """authenticated only views return 403 for guests"""
  96. for url in LISTS_URLS:
  97. self.access_all_categories()
  98. response = self.client.get('/' + url)
  99. self.assertEqual(response.status_code, 200)
  100. self.access_all_categories()
  101. response = self.client.get(self.category_b.get_absolute_url() + url)
  102. self.assertEqual(response.status_code, 200)
  103. self.assertIn(self.category_b.name, response.content)
  104. self.logout_user()
  105. self.user = self.get_anonymous_user()
  106. for url in LISTS_URLS[1:]:
  107. self.access_all_categories()
  108. response = self.client.get('/' + url)
  109. self.assertEqual(response.status_code, 403)
  110. self.access_all_categories()
  111. response = self.client.get(self.category_b.get_absolute_url() + url)
  112. self.assertEqual(response.status_code, 403)
  113. def test_empty_list_hides_categories_picker(self):
  114. """categories picker is hidden on empty list"""
  115. Category(
  116. name='Hidden Category',
  117. slug='hidden-category',
  118. ).insert_at(self.root, position='last-child', save=True)
  119. test_category = Category.objects.get(slug='hidden-category')
  120. self.access_all_categories()
  121. response = self.client.get('/')
  122. self.assertEqual(response.status_code, 200)
  123. self.assertNotIn(self.category_a.get_absolute_url(), response.content)
  124. self.assertNotIn(self.category_e.get_absolute_url(), response.content)
  125. self.access_all_categories()
  126. response = self.client.get(self.category_a.get_absolute_url())
  127. self.assertEqual(response.status_code, 200)
  128. self.assertNotIn(self.category_b.get_absolute_url(), response.content)
  129. def test_list_renders_categories_picker(self):
  130. """categories picker renders valid categories"""
  131. Category(
  132. name='Hidden Category',
  133. slug='hidden-category',
  134. ).insert_at(self.root, position='last-child', save=True)
  135. test_category = Category.objects.get(slug='hidden-category')
  136. testutils.post_thread(
  137. category=self.category_b,
  138. )
  139. response = self.client.get('/')
  140. self.assertEqual(response.status_code, 200)
  141. self.assertIn(self.category_a.get_absolute_url(), response.content)
  142. # readable categories, but non-accessible directly
  143. self.assertNotIn(self.category_b.get_absolute_url(), response.content)
  144. self.assertNotIn(self.category_c.get_absolute_url(), response.content)
  145. self.assertNotIn(self.category_d.get_absolute_url(), response.content)
  146. self.assertNotIn(self.category_f.get_absolute_url(), response.content)
  147. # hidden category
  148. self.assertNotIn(test_category.get_absolute_url(), response.content)
  149. # test category view
  150. self.access_all_categories()
  151. response = self.client.get(self.category_a.get_absolute_url())
  152. self.assertEqual(response.status_code, 200)
  153. self.assertIn(self.category_b.get_absolute_url(), response.content)
  154. # readable categories, but non-accessible directly
  155. self.assertNotIn(self.category_c.get_absolute_url(), response.content)
  156. self.assertNotIn(self.category_d.get_absolute_url(), response.content)
  157. self.assertNotIn(self.category_f.get_absolute_url(), response.content)
  158. class CategoryThreadsListTests(ThreadsListTestCase):
  159. def test_access_hidden_category(self):
  160. """hidden category returns 404"""
  161. Category(
  162. name='Hidden Category',
  163. slug='hidden-category',
  164. ).insert_at(self.root, position='last-child', save=True)
  165. test_category = Category.objects.get(slug='hidden-category')
  166. for url in LISTS_URLS:
  167. response = self.client.get(test_category.get_absolute_url() + url)
  168. self.assertEqual(response.status_code, 404)
  169. def test_access_protected_category(self):
  170. """protected category returns 403"""
  171. Category(
  172. name='Hidden Category',
  173. slug='hidden-category',
  174. ).insert_at(self.root, position='last-child', save=True)
  175. test_category = Category.objects.get(slug='hidden-category')
  176. for url in LISTS_URLS:
  177. override_acl(self.user, {
  178. 'visible_categories': [test_category.pk],
  179. 'categories': {
  180. test_category.pk: {
  181. 'can_see': 1,
  182. 'can_browse': 0,
  183. }
  184. }
  185. });
  186. response = self.client.get(test_category.get_absolute_url() + url)
  187. self.assertEqual(response.status_code, 403)
  188. class ThreadsVisibilityTests(ThreadsListTestCase):
  189. def test_list_renders_test_thread(self):
  190. """list renders test thread with valid top category"""
  191. test_thread = testutils.post_thread(
  192. category=self.category_c,
  193. )
  194. response = self.client.get('/')
  195. self.assertEqual(response.status_code, 200)
  196. self.assertIn(test_thread.get_absolute_url(), response.content)
  197. self.assertIn(self.category_a.get_absolute_url(), response.content)
  198. # other top category is hidden from user
  199. self.assertNotIn(self.category_e.get_absolute_url(), response.content)
  200. # real thread's category is hidden away from user
  201. self.assertNotIn(self.category_c.get_absolute_url(), response.content)
  202. # test category view
  203. self.access_all_categories()
  204. response = self.client.get(self.category_b.get_absolute_url())
  205. self.assertEqual(response.status_code, 200)
  206. # thread displays
  207. self.assertIn(test_thread.get_absolute_url(), response.content)
  208. self.assertIn(self.category_c.get_absolute_url(), response.content)
  209. self.assertNotIn(self.category_d.get_absolute_url(), response.content)
  210. def test_list_renders_hidden_thread(self):
  211. """list renders empty due to no permission to see thread"""
  212. Category(
  213. name='Hidden Category',
  214. slug='hidden-category',
  215. ).insert_at(self.root, position='last-child', save=True)
  216. test_category = Category.objects.get(slug='hidden-category')
  217. test_thread = testutils.post_thread(
  218. category=test_category,
  219. )
  220. response = self.client.get('/')
  221. self.assertEqual(response.status_code, 200)
  222. self.assertIn("empty-message", response.content)
  223. def test_list_user_see_own_moderated_thread(self):
  224. """list renders moderated thread that belongs to viewer"""
  225. test_thread = testutils.post_thread(
  226. category=self.category_a,
  227. poster=self.user,
  228. is_moderated=True,
  229. )
  230. response = self.client.get('/')
  231. self.assertEqual(response.status_code, 200)
  232. self.assertIn(test_thread.get_absolute_url(), response.content)
  233. def test_list_user_cant_see_moderated_thread(self):
  234. """list hides moderated thread that belongs to other user"""
  235. test_thread = testutils.post_thread(
  236. category=self.category_a,
  237. is_moderated=True,
  238. )
  239. response = self.client.get('/')
  240. self.assertEqual(response.status_code, 200)
  241. self.assertNotIn(test_thread.get_absolute_url(), response.content)
  242. def test_list_user_cant_see_hidden_thread(self):
  243. """list hides hidden thread that belongs to other user"""
  244. test_thread = testutils.post_thread(
  245. category=self.category_a,
  246. is_hidden=True,
  247. )
  248. response = self.client.get('/')
  249. self.assertEqual(response.status_code, 200)
  250. self.assertNotIn(test_thread.get_absolute_url(), response.content)
  251. def test_list_user_cant_see_own_hidden_thread(self):
  252. """list hides hidden thread that belongs to viewer"""
  253. test_thread = testutils.post_thread(
  254. category=self.category_a,
  255. poster=self.user,
  256. is_hidden=True,
  257. )
  258. response = self.client.get('/')
  259. self.assertEqual(response.status_code, 200)
  260. self.assertNotIn(test_thread.get_absolute_url(), response.content)
  261. def test_list_user_can_see_own_hidden_thread(self):
  262. """list shows hidden thread that belongs to viewer due to permission"""
  263. test_thread = testutils.post_thread(
  264. category=self.category_a,
  265. poster=self.user,
  266. is_hidden=True,
  267. )
  268. self.access_all_categories({
  269. 'can_hide_threads': 1
  270. })
  271. response = self.client.get('/')
  272. self.assertEqual(response.status_code, 200)
  273. self.assertIn(test_thread.get_absolute_url(), response.content)
  274. def test_list_user_can_see_hidden_thread(self):
  275. """
  276. list shows hidden thread that belongs to other user due to permission
  277. """
  278. test_thread = testutils.post_thread(
  279. category=self.category_a,
  280. is_hidden=True,
  281. )
  282. self.access_all_categories({
  283. 'can_hide_threads': 1
  284. })
  285. response = self.client.get('/')
  286. self.assertEqual(response.status_code, 200)
  287. self.assertIn(test_thread.get_absolute_url(), response.content)
  288. def test_list_user_can_see_moderated_thread(self):
  289. """
  290. list shows hidden thread that belongs to other user due to permission
  291. """
  292. test_thread = testutils.post_thread(
  293. category=self.category_a,
  294. is_moderated=True,
  295. )
  296. self.access_all_categories({
  297. 'can_review_moderated_content': 1
  298. })
  299. response = self.client.get('/')
  300. self.assertEqual(response.status_code, 200)
  301. self.assertIn(test_thread.get_absolute_url(), response.content)