test_forumthreads_view.py 18 KB

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