/wakawaka/tests/test_page.py

http://github.com/bartTC/django-wakawaka · Python · 335 lines · 293 code · 17 blank · 25 comment · 3 complexity · c303705215069db96c479f2d24ac1b81 MD5 · raw file

  1. from django.contrib.auth.models import Permission
  2. from django.urls import reverse
  3. from wakawaka.forms import WikiPageForm
  4. from wakawaka.models import Revision, WikiPage
  5. from wakawaka.tests.base import BaseTestCase
  6. class PageTestCase(BaseTestCase):
  7. """
  8. Wiki Page display, editing and deleting.
  9. """
  10. def test_if_user_not_logged_in_404(self):
  11. """
  12. Pages which don't exist, and the user is not logged in, display 404.
  13. """
  14. response = self.client.get(reverse('wakawaka_index'), follow=True)
  15. self.assertEqual(response.status_code, 404)
  16. def test_if_user_logged_in_page_form_is_displayed(self):
  17. """
  18. If a user is logged in, and the page does not exist yet, we redirect
  19. to a Create Page form.
  20. """
  21. self.login_superuser()
  22. # Calling /WikiIndex/ will result in a redirect to /edit/
  23. response = self.client.get(reverse('wakawaka_index'), follow=True)
  24. self.assertEqual(response.status_code, 200)
  25. self.assertTrue('form' in response.context)
  26. self.assertTrue(isinstance(response.context['form'], WikiPageForm))
  27. def test_model_str_methods(self):
  28. """
  29. Models __str__ methods are fine.
  30. """
  31. page = self.create_wikipage(
  32. 'WikiIndex', 'This is the first revision', 'This is the second revision',
  33. )
  34. self.assertTrue(isinstance(page.__str__(), str))
  35. self.assertTrue(isinstance(page.current.__str__(), str))
  36. # --------------------------------------------------------------------------
  37. # Page form creation and permissions
  38. # --------------------------------------------------------------------------
  39. def test_page_form_invalid(self):
  40. """
  41. At a bare minimum, the PageForm needs a 'content' field. Otherwise
  42. the form is displayed again, having errors.
  43. """
  44. self.login_superuser()
  45. data = {}
  46. edit_url = reverse('wakawaka_edit', kwargs={'slug': 'WikiIndex'})
  47. response = self.client.post(edit_url, data, follow=True)
  48. self.assertTrue('form' in response.context)
  49. self.assertTrue(isinstance(response.context['form'], WikiPageForm))
  50. def test_page_form_valid(self):
  51. """
  52. Having a valid 'content' POST object will create that page.
  53. """
  54. content = 'This is the content of the new WikiIndex page'
  55. formatted = '<p>This is the content of the new <a href="/WikiIndex/">WikiIndex</a> page</p>'
  56. self.login_superuser()
  57. data = {'content': content}
  58. edit_url = reverse('wakawaka_edit', kwargs={'slug': 'WikiIndex'})
  59. response = self.client.post(edit_url, data, follow=True)
  60. # The Response is our page, and it has the content formatted in it.
  61. # Since WikiIndex is a valid Page index word, it's linked automatically.
  62. self.assertContains(response, formatted)
  63. # One Page with one revision was created
  64. self.assertEqual(WikiPage.objects.count(), 1)
  65. self.assertEqual(WikiPage.objects.all()[0].revisions.count(), 1)
  66. def test_page_add_only_if_perm(self):
  67. """
  68. The user needs 'add_wikipage' and 'add_revision' permission to add
  69. add a page.
  70. """
  71. user = self.login_staffuser_noperm()
  72. # No permission
  73. data = {'content': 'This is the content of the new WikiIndex page'}
  74. edit_url = reverse('wakawaka_edit', kwargs={'slug': 'WikiIndex'})
  75. response = self.client.post(edit_url, data, follow=True)
  76. self.assertEqual(response.status_code, 403)
  77. page_perm = Permission.objects.get(codename='add_wikipage')
  78. rev_perm = Permission.objects.get(codename='add_revision')
  79. # Just the page perm is not enough
  80. user.user_permissions.add(page_perm)
  81. response = self.client.post(edit_url, data, follow=True)
  82. self.assertEqual(response.status_code, 403)
  83. # Page perm and rev perm is ok
  84. user.user_permissions.add(rev_perm)
  85. response = self.client.post(edit_url, data, follow=True)
  86. self.assertEqual(response.status_code, 200)
  87. def test_page_edit_only_if_perm(self):
  88. """
  89. Users need at least 'wakawaka.change_wikipage' and
  90. 'wakawaka.change_revision' permission to edit a page.
  91. """
  92. # Create page upfront
  93. self.create_wikipage('WikiIndex', 'Some content')
  94. data = {'content': 'This is updated content.'}
  95. edit_url = reverse('wakawaka_edit', kwargs={'slug': 'WikiIndex'})
  96. page_perm = Permission.objects.get(codename='change_wikipage')
  97. rev_perm = Permission.objects.get(codename='change_revision')
  98. # Login a user with no permissions
  99. user = self.login_staffuser_noperm()
  100. # User with no perm can't edit
  101. response = self.client.post(edit_url, data, follow=True)
  102. self.assertEqual(response.status_code, 403)
  103. # Just the page perm is not enough
  104. user.user_permissions.add(page_perm)
  105. response = self.client.post(edit_url, data, follow=True)
  106. self.assertEqual(response.status_code, 403)
  107. # Page perm and rev perm is ok
  108. user.user_permissions.add(rev_perm)
  109. response = self.client.post(edit_url, data, follow=True)
  110. self.assertEqual(response.status_code, 200)
  111. # --------------------------------------------------------------------------
  112. # Page revisions
  113. # --------------------------------------------------------------------------
  114. def test_editing_again_creates_revision(self):
  115. """
  116. Submitting a page edit form multiple times creates a separate revision
  117. automatically.
  118. """
  119. self.login_superuser()
  120. data1 = {'content': 'First Content'}
  121. edit_url = reverse('wakawaka_edit', kwargs={'slug': 'WikiIndex'})
  122. self.client.post(edit_url, data1, follow=True)
  123. data2 = {'content': 'Updated Content'}
  124. edit_url = reverse('wakawaka_edit', kwargs={'slug': 'WikiIndex'})
  125. self.client.post(edit_url, data2, follow=True)
  126. # One Page with one revision was created
  127. self.assertEqual(WikiPage.objects.count(), 1)
  128. self.assertEqual(WikiPage.objects.all()[0].revisions.count(), 2)
  129. # We can call each revision individually. The last change is displayed
  130. # when calling without a revision
  131. page_url = reverse('wakawaka_page', kwargs={'slug': 'WikiIndex'})
  132. response = self.client.get(page_url, follow=True)
  133. self.assertContains(response, data2['content'])
  134. page_url = reverse('wakawaka_page', kwargs={'slug': 'WikiIndex', 'rev_id': 2})
  135. response = self.client.get(page_url, follow=True)
  136. self.assertContains(response, data2['content'])
  137. page_url = reverse('wakawaka_page', kwargs={'slug': 'WikiIndex', 'rev_id': 1})
  138. response = self.client.get(page_url, follow=True)
  139. self.assertContains(response, data1['content'])
  140. def test_edit_page_with_same_content_does_not_work(self):
  141. """
  142. Saving a page revision with the same content as before, won't create a
  143. new revision.
  144. """
  145. self.login_superuser()
  146. data1 = {'content': 'First Content'}
  147. edit_url = reverse('wakawaka_edit', kwargs={'slug': 'WikiIndex'})
  148. self.client.post(edit_url, data1, follow=True)
  149. data2 = {'content': 'First Content'}
  150. edit_url = reverse('wakawaka_edit', kwargs={'slug': 'WikiIndex'})
  151. self.client.post(edit_url, data2, follow=True)
  152. self.assertEqual(WikiPage.objects.count(), 1)
  153. self.assertEqual(WikiPage.objects.all()[0].revisions.count(), 1)
  154. self.assertEqual(Revision.objects.count(), 1)
  155. def test_edit_revision_reverts_content(self):
  156. """
  157. If the user calls the revision edit page form, and submits it, it
  158. will automatically revert the content to this revision.
  159. """
  160. # Create a WikiIndex page with two revisions:
  161. rev1 = 'First Content'
  162. rev2 = 'Updated Content'
  163. self.create_wikipage('WikiIndex', rev1, rev2)
  164. # Need to be logged in to edit a Page
  165. self.login_superuser()
  166. # Calling edit form with older revision will have that content in form
  167. page_url = reverse('wakawaka_edit', kwargs={'slug': 'WikiIndex', 'rev_id': 1})
  168. response = self.client.get(page_url, follow=True)
  169. self.assertContains(response, rev1)
  170. self.assertContains(response, 'Reverted')
  171. # @OPTIMIZE: should not test for "Reverted" in text, too vague
  172. # Calling the edit form of the current revision, will display the regular
  173. # edit form.
  174. page_url = reverse('wakawaka_edit', kwargs={'slug': 'WikiIndex', 'rev_id': 2})
  175. response = self.client.get(page_url, follow=True)
  176. self.assertContains(response, rev2)
  177. self.assertNotContains(response, 'Reverted')
  178. # @OPTIMIZE: should not test for "Reverted" in text, too vague
  179. # --------------------------------------------------------------------------
  180. # Page deletion
  181. # --------------------------------------------------------------------------
  182. def test_user_needs_delete_perm_for_page(self):
  183. """
  184. Deleting an entire page needs both 'delete_revision' and 'delete_wikipage'
  185. permission.
  186. The delete form is integrated into the edit page. It's a choicefield
  187. holding either or both of 'rev' and 'page' depending on the users
  188. permission.
  189. """
  190. # Create one page with two revisions upfront
  191. self.create_wikipage('WikiIndex', 'Some content', 'Other content')
  192. self.assertEqual(WikiPage.objects.count(), 1)
  193. self.assertEqual(Revision.objects.count(), 2)
  194. # Need to be logged in to edit a Page. The user also needs edit
  195. # permission to see the edit page
  196. user = self.login_staffuser_noperm()
  197. user.user_permissions.add(Permission.objects.get(codename='change_wikipage'))
  198. user.user_permissions.add(Permission.objects.get(codename='change_revision'))
  199. # The user has no permission at all so this will fail. The delete
  200. # form is not even displayed then. So this is silently ignored,
  201. data = {'delete': 'rev'}
  202. page_url = reverse('wakawaka_edit', kwargs={'slug': 'WikiIndex', 'rev_id': 2})
  203. self.client.post(page_url, data, follow=False)
  204. self.assertEqual(WikiPage.objects.count(), 1)
  205. self.assertEqual(Revision.objects.count(), 2)
  206. # Give the user delete_revision permission so they can delete it.
  207. user.user_permissions.add(Permission.objects.get(codename='delete_revision'))
  208. data = {'delete': 'rev'}
  209. page_url = reverse('wakawaka_edit', kwargs={'slug': 'WikiIndex', 'rev_id': 2})
  210. self.client.post(page_url, data, follow=True)
  211. self.assertEqual(WikiPage.objects.count(), 1)
  212. self.assertEqual(Revision.objects.count(), 1)
  213. # If a page has only one Revision set, and the user tries to delete
  214. # this revision, it will also delete the page - but only if the user
  215. # has aside 'delete_revision' permission also 'delete_wikipage' permission.
  216. data = {'delete': 'rev'}
  217. page_url = reverse('wakawaka_edit', kwargs={'slug': 'WikiIndex', 'rev_id': 1})
  218. self.client.post(page_url, data, follow=True)
  219. self.assertEqual(WikiPage.objects.count(), 1)
  220. self.assertEqual(Revision.objects.count(), 1)
  221. # Give the user delete_wikipage permission so they can delete the
  222. # entire page, by deleting the last revision of it
  223. user.user_permissions.add(Permission.objects.get(codename='delete_wikipage'))
  224. data = {'delete': 'rev'}
  225. page_url = reverse('wakawaka_edit', kwargs={'slug': 'WikiIndex', 'rev_id': 1})
  226. self.client.post(page_url, data, follow=True)
  227. # Since the page does not exist anymore, the user is redirected to
  228. # the index page.
  229. self.assertEqual(WikiPage.objects.count(), 0)
  230. self.assertEqual(Revision.objects.count(), 0)
  231. def test_delete_page(self):
  232. """
  233. If the user has all permissions they can delete the page right away.
  234. """
  235. user = self.login_staffuser_noperm()
  236. user.user_permissions.add(Permission.objects.get(codename='change_wikipage'))
  237. user.user_permissions.add(Permission.objects.get(codename='change_revision'))
  238. user.user_permissions.add(Permission.objects.get(codename='delete_wikipage'))
  239. user.user_permissions.add(Permission.objects.get(codename='delete_revision'))
  240. # Create one page with two revisions upfront
  241. self.create_wikipage('WikiIndex', 'Some content', 'Other content')
  242. self.assertEqual(WikiPage.objects.count(), 1)
  243. self.assertEqual(Revision.objects.count(), 2)
  244. data = {'delete': 'page'}
  245. page_url = reverse('wakawaka_edit', kwargs={'slug': 'WikiIndex'})
  246. self.client.post(page_url, data, follow=False)
  247. self.assertEqual(WikiPage.objects.count(), 0)
  248. self.assertEqual(Revision.objects.count(), 0)
  249. def test_delete_bad_value(self):
  250. """
  251. Deleting a page or revision still needs to be set. If the delete form
  252. passes no or an invalid value, nothing happens.
  253. """
  254. user = self.login_staffuser_noperm()
  255. user.user_permissions.add(Permission.objects.get(codename='change_wikipage'))
  256. user.user_permissions.add(Permission.objects.get(codename='change_revision'))
  257. user.user_permissions.add(Permission.objects.get(codename='delete_wikipage'))
  258. user.user_permissions.add(Permission.objects.get(codename='delete_revision'))
  259. # Create one page with two revisions upfront
  260. self.create_wikipage('WikiIndex', 'Some content', 'Other content')
  261. self.assertEqual(WikiPage.objects.count(), 1)
  262. self.assertEqual(Revision.objects.count(), 2)
  263. # No value
  264. data = {'delete': ''}
  265. page_url = reverse('wakawaka_edit', kwargs={'slug': 'WikiIndex'})
  266. self.client.post(page_url, data, follow=False)
  267. self.assertEqual(WikiPage.objects.count(), 1)
  268. self.assertEqual(Revision.objects.count(), 2)
  269. # Invalid value
  270. data = {'delete': 'foobar'}
  271. page_url = reverse('wakawaka_edit', kwargs={'slug': 'WikiIndex'})
  272. self.client.post(page_url, data, follow=False)
  273. self.assertEqual(WikiPage.objects.count(), 1)
  274. self.assertEqual(Revision.objects.count(), 2)