test_forum_threads_view.py 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512
  1. from django.contrib.auth import get_user_model
  2. from django.core.urlresolvers import reverse
  3. from django.test import TestCase
  4. from django.utils.translation import ugettext as _
  5. from misago.acl import add_acl
  6. from misago.acl.testutils import override_acl
  7. from misago.forums.models import Forum
  8. from misago.users.testutils import AuthenticatedUserTestCase
  9. from misago.threads import testutils
  10. from misago.threads.models import Label
  11. from misago.threads.views.generic.forum import ForumFiltering, ForumThreads
  12. class ForumViewHelperTestCase(AuthenticatedUserTestCase):
  13. def setUp(self):
  14. super(ForumViewHelperTestCase, self).setUp()
  15. self.forum = Forum.objects.all_forums().filter(role="forum")[:1][0]
  16. self.forum.labels = []
  17. def override_acl(self, new_acl):
  18. new_acl.update({'can_browse': True})
  19. forums_acl = self.user.acl
  20. forums_acl['visible_forums'].append(self.forum.pk)
  21. forums_acl['forums'][self.forum.pk] = new_acl
  22. override_acl(self.user, forums_acl)
  23. add_acl(self.user, self.forum)
  24. class ForumFilteringTests(ForumViewHelperTestCase):
  25. def test_get_available_filters(self):
  26. """get_available_filters returns filters varying on forum acl"""
  27. default_acl = {
  28. 'can_see_all_threads': False,
  29. 'can_see_reports': False,
  30. 'can_review_moderated_content': False,
  31. }
  32. cases = (
  33. ('can_see_all_threads', 'my-threads'),
  34. ('can_see_reports', 'reported'),
  35. ('can_review_moderated_content', 'moderated-threads'),
  36. )
  37. for permission, filter_type in cases:
  38. self.override_acl(default_acl)
  39. filtering = ForumFiltering(self.forum, 'misago:forum', {
  40. 'forum_id': self.forum.id,
  41. 'forum_slug': self.forum.slug,
  42. })
  43. available_filters = filtering.get_available_filters()
  44. available_filters = [f['type'] for f in available_filters]
  45. self.assertNotIn(filter_type, available_filters)
  46. acl = default_acl.copy()
  47. acl[permission] = True
  48. self.override_acl(acl)
  49. filtering = ForumFiltering(self.forum, 'misago:forum', {
  50. 'forum_id': self.forum.id,
  51. 'forum_slug': self.forum.slug,
  52. })
  53. available_filters = filtering.get_available_filters()
  54. available_filters = [f['type'] for f in available_filters]
  55. self.assertIn(filter_type, available_filters)
  56. self.forum.labels = [
  57. Label(name='Label A', slug='label-a'),
  58. Label(name='Label B', slug='label-b'),
  59. Label(name='Label C', slug='label-c'),
  60. Label(name='Label D', slug='label-d'),
  61. ]
  62. self.override_acl(default_acl)
  63. ForumFiltering(self.forum, 'misago:forum', {
  64. 'forum_id': self.forum.id,
  65. 'forum_slug': self.forum.slug,
  66. })
  67. available_filters = filtering.get_available_filters()
  68. available_filters = [f['type'] for f in available_filters]
  69. self.assertEqual(len(available_filters), len(self.forum.labels))
  70. for label in self.forum.labels:
  71. self.assertIn(label.slug, available_filters)
  72. def test_clean_kwargs(self):
  73. """clean_kwargs cleans kwargs"""
  74. self.override_acl({
  75. 'can_see_all_threads': True,
  76. 'can_see_reports': True,
  77. 'can_review_moderated_content': True,
  78. })
  79. filtering = ForumFiltering(self.forum, 'misago:forum', {
  80. 'forum_id': self.forum.id,
  81. 'forum_slug': self.forum.slug,
  82. })
  83. available_filters = filtering.get_available_filters()
  84. available_filters = [f['type'] for f in available_filters]
  85. clean_kwargs = filtering.clean_kwargs({'test': 'kwarg'})
  86. self.assertEqual(clean_kwargs, {'test': 'kwarg'})
  87. clean_kwargs = filtering.clean_kwargs({
  88. 'test': 'kwarg',
  89. 'show': 'everything-hue-hue',
  90. })
  91. self.assertEqual(clean_kwargs, {'test': 'kwarg'})
  92. self.assertFalse(filtering.is_active)
  93. self.assertIsNone(filtering.show)
  94. for filter_type in available_filters:
  95. clean_kwargs = filtering.clean_kwargs({
  96. 'test': 'kwarg',
  97. 'show': filter_type,
  98. })
  99. self.assertEqual(clean_kwargs, {
  100. 'test': 'kwarg',
  101. 'show': filter_type,
  102. })
  103. self.assertTrue(filtering.is_active)
  104. self.assertEqual(filtering.show, filter_type)
  105. def test_current(self):
  106. """current returns dict with current filter"""
  107. self.override_acl({
  108. 'can_see_all_threads': True,
  109. 'can_see_reports': True,
  110. 'can_review_moderated_content': True,
  111. })
  112. test_cases = (
  113. ('my-threads', _("My threads")),
  114. ('reported', _("With reported posts")),
  115. ('moderated-threads', _("Moderated threads")),
  116. ('moderated-posts', _("With moderated posts")),
  117. )
  118. for filter_type, name in test_cases:
  119. filtering = ForumFiltering(self.forum, 'misago:forum', {
  120. 'forum_id': self.forum.id,
  121. 'forum_slug': self.forum.slug,
  122. })
  123. filtering.clean_kwargs({'show': filter_type})
  124. self.assertEqual(filtering.current['name'], name)
  125. def test_choices(self):
  126. """choices returns list of dicts with available filters"""
  127. self.override_acl({
  128. 'can_see_all_threads': True,
  129. 'can_see_reports': True,
  130. 'can_review_moderated_content': True,
  131. })
  132. test_cases = (
  133. 'my-threads',
  134. 'reported',
  135. 'moderated-threads',
  136. 'moderated-posts',
  137. )
  138. for filter_type in test_cases:
  139. filtering = ForumFiltering(self.forum, 'misago:forum', {
  140. 'forum_id': self.forum.id,
  141. 'forum_slug': self.forum.slug,
  142. })
  143. filtering.clean_kwargs({'show': filter_type})
  144. choices = [choice['type'] for choice in filtering.choices()]
  145. self.assertNotIn(filter_type, choices)
  146. class ForumThreadsTests(ForumViewHelperTestCase):
  147. def test_empty_list(self):
  148. """list returns empty list of items"""
  149. self.override_acl({
  150. 'can_see_all_threads': True,
  151. 'can_review_moderated_content': False
  152. })
  153. threads = ForumThreads(self.user, self.forum)
  154. threads_list = threads.list()
  155. self.assertEqual(threads_list, [])
  156. def test_list_exception(self):
  157. """
  158. uninitialized list raises exceptions when
  159. page and paginator attributes are accessed
  160. """
  161. self.override_acl({
  162. 'can_see_all_threads': False,
  163. 'can_review_moderated_content': False
  164. })
  165. threads = ForumThreads(self.user, self.forum)
  166. with self.assertRaises(AttributeError):
  167. threads.page
  168. with self.assertRaises(AttributeError):
  169. threads.paginator
  170. def test_list_with_threads(self):
  171. """list returns list of visible threads"""
  172. test_threads = [
  173. testutils.post_thread(
  174. forum=self.forum,
  175. title="Hello, I am thread",
  176. is_moderated=False,
  177. poster=self.user),
  178. testutils.post_thread(
  179. forum=self.forum,
  180. title="Hello, I am moderated thread",
  181. is_moderated=True,
  182. poster=self.user),
  183. testutils.post_thread(
  184. forum=self.forum,
  185. title="Hello, I am other user thread",
  186. is_moderated=False,
  187. poster="Bob"),
  188. testutils.post_thread(
  189. forum=self.forum,
  190. title="Hello, I am other user moderated thread",
  191. is_moderated=True,
  192. poster="Bob"),
  193. ]
  194. self.override_acl({
  195. 'can_see_all_threads': False,
  196. 'can_review_moderated_content': False
  197. })
  198. threads = ForumThreads(self.user, self.forum)
  199. self.assertEqual(threads.list(), [test_threads[1], test_threads[0]])
  200. self.override_acl({
  201. 'can_see_all_threads': True,
  202. 'can_review_moderated_content': False
  203. })
  204. threads = ForumThreads(self.user, self.forum)
  205. self.assertEqual(threads.list(),
  206. [test_threads[2], test_threads[1], test_threads[0]])
  207. self.override_acl({
  208. 'can_see_all_threads': True,
  209. 'can_review_moderated_content': True
  210. })
  211. threads = ForumThreads(self.user, self.forum)
  212. test_threads.reverse()
  213. self.assertEqual(threads.list(), test_threads)
  214. self.assertTrue(threads.page)
  215. self.assertTrue(threads.paginator)
  216. class ForumThreadsAuthenticatedTests(AuthenticatedUserTestCase):
  217. def setUp(self):
  218. super(ForumThreadsAuthenticatedTests, self).setUp()
  219. self.forum = Forum.objects.all_forums().filter(role="forum")[:1][0]
  220. self.link = self.forum.get_absolute_url()
  221. self.forum.delete_content()
  222. def override_acl(self, new_acl):
  223. forums_acl = self.user.acl
  224. if new_acl['can_see']:
  225. forums_acl['visible_forums'].append(self.forum.pk)
  226. else:
  227. forums_acl['visible_forums'].remove(self.forum.pk)
  228. forums_acl['forums'][self.forum.pk] = new_acl
  229. override_acl(self.user, forums_acl)
  230. def test_cant_see(self):
  231. """has no permission to see forum"""
  232. self.override_acl({
  233. 'can_see': 0,
  234. 'can_browse': 0,
  235. })
  236. response = self.client.get(self.link)
  237. self.assertEqual(response.status_code, 404)
  238. def test_cant_browse(self):
  239. """has no permission to browse forum"""
  240. self.override_acl({
  241. 'can_see': 1,
  242. 'can_browse': 0,
  243. })
  244. response = self.client.get(self.link)
  245. self.assertEqual(response.status_code, 403)
  246. def test_can_browse_empty(self):
  247. """has permission to browse forum, sees empty list"""
  248. self.override_acl({
  249. 'can_see': 1,
  250. 'can_browse': 1,
  251. })
  252. response = self.client.get(self.link)
  253. self.assertEqual(response.status_code, 200)
  254. self.assertIn("No threads", response.content)
  255. def test_owned_threads_visibility(self):
  256. """
  257. can_see_all_threads=0 displays only owned threads to authenticated user
  258. """
  259. test_acl = {
  260. 'can_see': 1,
  261. 'can_browse': 1,
  262. 'can_see_all_threads': 0,
  263. 'can_review_moderated_content': 0,
  264. }
  265. other_moderated_title = "Test other user moderated thread"
  266. testutils.post_thread(
  267. forum=self.forum, title=other_moderated_title, is_moderated=True)
  268. other_title = "Test other user thread"
  269. testutils.post_thread(forum=self.forum, title=other_title)
  270. owned_title = "Test authenticated user thread"
  271. testutils.post_thread(
  272. forum=self.forum,
  273. title=owned_title,
  274. poster=self.user)
  275. owned_moderated_title = "Test authenticated user moderated thread"
  276. testutils.post_thread(
  277. forum=self.forum,
  278. title=owned_moderated_title,
  279. poster=self.user,
  280. is_moderated=True)
  281. self.override_acl(test_acl)
  282. response = self.client.get(self.link)
  283. self.assertEqual(response.status_code, 200)
  284. self.assertNotIn(other_title, response.content)
  285. self.assertNotIn(other_moderated_title, response.content)
  286. self.assertIn(owned_title, response.content)
  287. self.assertIn(owned_moderated_title, response.content)
  288. self.assertNotIn('show-my-threads', response.content)
  289. def test_moderated_threads_visibility(self):
  290. """moderated threads are not rendered to non-moderator, except owned"""
  291. test_acl = {
  292. 'can_see': 1,
  293. 'can_browse': 1,
  294. 'can_see_all_threads': 1,
  295. 'can_review_moderated_content': 0,
  296. }
  297. test_title = "Test moderated thread"
  298. thread = testutils.post_thread(
  299. forum=self.forum, title=test_title, is_moderated=True)
  300. self.override_acl(test_acl)
  301. response = self.client.get(self.link)
  302. self.assertEqual(response.status_code, 200)
  303. self.assertNotIn(test_title, response.content)
  304. test_title = "Test owned moderated thread"
  305. thread = testutils.post_thread(
  306. forum=self.forum,
  307. title=test_title,
  308. is_moderated=True,
  309. poster=self.user)
  310. self.override_acl(test_acl)
  311. response = self.client.get(self.link)
  312. self.assertEqual(response.status_code, 200)
  313. self.assertIn(test_title, response.content)
  314. def test_owned_threads_filter(self):
  315. """owned threads filter is available to authenticated user"""
  316. test_acl = {
  317. 'can_see': 1,
  318. 'can_browse': 1,
  319. 'can_see_all_threads': 1,
  320. 'can_review_moderated_content': 0,
  321. }
  322. other_moderated_title = "Test other user moderated thread"
  323. testutils.post_thread(
  324. forum=self.forum, title=other_moderated_title, is_moderated=True)
  325. other_title = "Test other user thread"
  326. testutils.post_thread(forum=self.forum, title=other_title)
  327. owned_title = "Test authenticated user thread"
  328. testutils.post_thread(
  329. forum=self.forum,
  330. title=owned_title,
  331. poster=self.user)
  332. owned_moderated_title = "Test authenticated user moderated thread"
  333. testutils.post_thread(
  334. forum=self.forum,
  335. title=owned_moderated_title,
  336. poster=self.user,
  337. is_moderated=True)
  338. self.override_acl(test_acl)
  339. response = self.client.get(self.link)
  340. self.assertEqual(response.status_code, 200)
  341. self.assertIn(other_title, response.content)
  342. self.assertNotIn(other_moderated_title, response.content)
  343. self.assertIn(owned_title, response.content)
  344. self.assertIn(owned_moderated_title, response.content)
  345. self.assertIn('show-my-threads', response.content)
  346. self.override_acl(test_acl)
  347. response = self.client.get(reverse('misago:forum', kwargs={
  348. 'forum_id': self.forum.id,
  349. 'forum_slug': self.forum.slug,
  350. 'show': 'my-threads',
  351. }))
  352. self.assertEqual(response.status_code, 200)
  353. self.assertNotIn(other_title, response.content)
  354. self.assertNotIn(other_moderated_title, response.content)
  355. self.assertIn(owned_title, response.content)
  356. self.assertIn(owned_moderated_title, response.content)
  357. def test_moderated_threads_filter(self):
  358. """moderated threads filter is available to moderator"""
  359. test_acl = {
  360. 'can_see': 1,
  361. 'can_browse': 1,
  362. 'can_see_all_threads': 1,
  363. 'can_review_moderated_content': 0,
  364. }
  365. not_moderated_title = "Not moderated thread"
  366. testutils.post_thread(forum=self.forum, title=not_moderated_title)
  367. hidden_title = "Test moderated thread"
  368. testutils.post_thread(
  369. forum=self.forum, title=hidden_title, is_moderated=True)
  370. visible_title = "Test owned moderated thread"
  371. testutils.post_thread(
  372. forum=self.forum,
  373. title=visible_title,
  374. is_moderated=True,
  375. poster=self.user)
  376. self.override_acl(test_acl)
  377. response = self.client.get(self.link)
  378. self.assertEqual(response.status_code, 200)
  379. self.assertIn(not_moderated_title, response.content)
  380. self.assertNotIn(hidden_title, response.content)
  381. self.assertIn(visible_title, response.content)
  382. self.assertNotIn('show-moderated-threads', response.content)
  383. self.assertNotIn('show-moderated-posts', response.content)
  384. self.override_acl(test_acl)
  385. response = self.client.get(reverse('misago:forum', kwargs={
  386. 'forum_id': self.forum.id,
  387. 'forum_slug': self.forum.slug,
  388. 'show': 'moderated-threads',
  389. }))
  390. self.assertEqual(response.status_code, 302)
  391. self.override_acl(test_acl)
  392. response = self.client.get(reverse('misago:forum', kwargs={
  393. 'forum_id': self.forum.id,
  394. 'forum_slug': self.forum.slug,
  395. 'show': 'moderated-posts',
  396. }))
  397. self.assertEqual(response.status_code, 302)
  398. test_acl = {
  399. 'can_see': 1,
  400. 'can_browse': 1,
  401. 'can_see_all_threads': 1,
  402. 'can_review_moderated_content': 1,
  403. }
  404. self.override_acl(test_acl)
  405. response = self.client.get(self.link)
  406. self.assertEqual(response.status_code, 200)
  407. self.assertIn(not_moderated_title, response.content)
  408. self.assertIn(hidden_title, response.content)
  409. self.assertIn(visible_title, response.content)
  410. self.assertIn('show-moderated-threads', response.content)
  411. self.assertIn('show-moderated-posts', response.content)
  412. self.override_acl(test_acl)
  413. response = self.client.get(reverse('misago:forum', kwargs={
  414. 'forum_id': self.forum.id,
  415. 'forum_slug': self.forum.slug,
  416. 'show': 'moderated-threads',
  417. }))
  418. self.assertEqual(response.status_code, 200)
  419. self.assertNotIn(not_moderated_title, response.content)
  420. self.assertIn(hidden_title, response.content)
  421. self.assertIn(visible_title, response.content)
  422. self.assertIn('show-moderated-threads', response.content)
  423. self.assertIn('show-moderated-posts', response.content)