コード例 #1
0
 def test_report_post(self):
     thr = Thread(category=self.cat, name='test_thread')
     thr.save()
     p = Post(
         thread=thr,
         content='This post will be reported.',
         author=self.user,
         add_date=timezone.now(),
     )
     p.save()
     self.assertTrue(self.client.login(username='******'))
     url = reverse(
         'forum_post_report',
         kwargs={
             'contest_id': self.contest.id,
             'category_id': self.cat.id,
             'thread_id': thr.id,
             'post_id': p.id,
         },
     )
     response = self.client.post(url, follow=True)
     self.assertEqual(403, response.status_code)
     self.ban.delete()
     response = self.client.post(url, follow=True)
     self.assertEqual(200, response.status_code)
コード例 #2
0
    def test_paging(self):
        self.assertTrue(self.client.login(username='******'))

        response = self.client.get(self.url, follow=True)
        self.assertEqual(200, response.status_code)
        self.assertContains(response, 'No posts to show.')

        time_offset_0h = timezone.now()

        p = Post(
            thread=self.thread,
            content='t',
            author=self.user,
            add_date=time_offset_0h,
        )
        p.save()

        response = self.client.get(self.url, follow=True)
        self.assertEqual(200, response.status_code)
        self.assertContains(response,
                            'Thread {} #{}'.format(p.thread.name, p.id))

        for i in range(43):
            Post(
                thread=self.thread,
                content='t' * i,
                author=self.user,
                add_date=time_offset_0h + timedelta(hours=i),
            ).save()

        response = self.client.get(self.url, follow=True)
        self.assertEqual(200, response.status_code)
        self.assertEqual(
            len(
                re.findall(r'Thread .*? #\d+',
                           response.content.decode('utf-8'))),
            settings.FORUM_PAGE_SIZE,
        )

        last_page = int(Post.objects.count() / settings.FORUM_PAGE_SIZE) + 1
        posts_on_last_page = Post.objects.count() % settings.FORUM_PAGE_SIZE

        response = self.client.get(self.url + '?page={}'.format(last_page),
                                   follow=True)
        self.assertEqual(200, response.status_code)
        self.assertEqual(
            len(
                re.findall(r'Thread .*? #\d+',
                           response.content.decode('utf-8'))),
            posts_on_last_page,
        )
コード例 #3
0
ファイル: tests.py プロジェクト: sio2project/oioioi
 def test_edit_post(self):
     thr = Thread(category=self.cat, name='test_thread')
     thr.save()
     p = Post(thread=thr, content='This post will be reported.',
              author=self.user, add_date=timezone.now())
     p.save()
     self.assertTrue(self.client.login(username='******'))
     edit_url = reverse('forum_post_edit', kwargs={'contest_id': self.contest.id,
                                                  'category_id': self.cat.id,
                                                  'thread_id': thr.id,
                                                  'post_id': p.id})
     self.assertEqual(403, self.client.get(edit_url).status_code)
     self.ban.delete()
     self.assertEqual(200, self.client.get(edit_url).status_code)
コード例 #4
0
 def test_report_post(self):
     p = Post(thread=self.thr, content='This post will be reported.',
              author=self.user, add_date=self.past)
     p.save()
     self.client.login(username='******')
     url = reverse('forum_post_report', kwargs={'contest_id': self.cont.id,
                                                'category_id': self.cat.id,
                                                'thread_id': self.thr.id,
                                                'post_id': p.id})
     name = self.user.first_name
     surname = self.user.last_name
     response = self.client.post(url, follow=True)
     self.assertIn('This post was reported', response.content)
     self.client.login(username='******')
     url = reverse('forum_thread', kwargs={'category_id': self.cat.id,
                                           'thread_id': self.thr.id})
     response = self.client.post(url, follow=True)
     regexp = r".* was reported.+?by.+?<a.+?>%s %s</a>.*" % (name, surname)
     pattern = re.compile(regexp, re.MULTILINE | re.DOTALL)
     self.assertTrue(pattern.match(response.content))
コード例 #5
0
ファイル: tests.py プロジェクト: sio2project/oioioi
    def test_remove_posts(self):
        p0 = Post(thread=self.thr, content='test0', author=self.user,
                  add_date=self.past)
        p0.save()
        p1 = Post(thread=self.thr, content='test1', author=self.user)
        p1.save()
        p2 = Post(thread=self.thr, content='test2', author=self.user)
        p2.save()

        self.assertTrue(self.client.login(username='******'))
        # user tries to remove post p1 but cannot (it is not last post)
        response = self.try_to_remove_post(p1)
        self.assertEqual(403, response.status_code)

        # user can remove p2 (last post, added by user)
        response = self.try_to_remove_post(p2)
        self.assertEqual(200, response.status_code)
        self.assertContains(response, 'Delete confirmation')
        p2.delete()

        # user tries to remove post p1 (and he can!)
        response = self.try_to_remove_post(p1)
        self.assertEqual(200, response.status_code)
        self.assertContains(response, 'Delete confirmation')
        p1.delete()

        # user tries to remove post p0 but can't (added earlier than 15min ago)
        response = self.try_to_remove_post(p0)
        self.assertEqual(403, response.status_code)
コード例 #6
0
ファイル: tests.py プロジェクト: sio2project/oioioi
    def test_ban_view_without_removing_reports(self):
        self.ban.delete()
        thr = Thread(category=self.cat, name='test_thread')
        thr.save()
        p0 = Post(thread=thr, content='test0', author=self.user2,
                  reported=True, reported_by=self.user)
        p0.save()
        p1 = Post(thread=thr, content='test1', author=self.user2,
                  reported=True, reported_by=self.user)
        p1.save()
        p2 = Post(thread=thr, content='test2', author=self.user2)
        p2.save()
        p3 = Post(thread=thr, content='test2', author=self.user,
                  reported=True, reported_by=self.user2)
        p3.save()

        def check_reports():
            p0.refresh_from_db()
            p1.refresh_from_db()
            p2.refresh_from_db()
            p3.refresh_from_db()
            return [p0.reported, p1.reported, p2.reported, p3.reported]

        self.assertEqual([True, True, False, True], check_reports())

        self.assertTrue(self.client.login(username='******'))
        self.assertFalse(Ban.objects.exists())

        ban_url = reverse('forum_user_ban', kwargs={'contest_id': self.contest.id,
                                                    'user_id': self.user.id})

        self.client.post(ban_url, {'reason': 'Abuse'})
        self.assertEqual(1, Ban.objects.count())
        ban = Ban.objects.all()[0]
        self.assertEqual(self.user, ban.user)
        self.assertEqual('test_admin', ban.admin.username)
        self.assertEqual('Abuse', ban.reason)
        self.assertEqual(self.contest.forum, ban.forum)
        self.assertEqual([True, True, False, True], check_reports())
        ban.delete()

        self.client.post(ban_url, {'reason': 'Abuse', 'delete_reports': True})
        self.assertEqual(1, Ban.objects.count())
        ban = Ban.objects.all()[0]
        self.assertEqual(self.user, ban.user)
        self.assertEqual('test_admin', ban.admin.username)
        self.assertEqual('Abuse', ban.reason)
        self.assertEqual(self.contest.forum, ban.forum)
        self.assertEqual([False, False, False, True], check_reports())
コード例 #7
0
ファイル: tests.py プロジェクト: sio2project/oioioi
class TestPost(TestCase):
    fixtures = ['test_users', 'test_contest']

    def setUp(self):
        delta = timedelta(days=3)
        self.past = timezone.now() - delta
        self.contest = get_contest_with_forum()
        self.user = User.objects.get(username='******')
        self.forum = self.contest.forum
        self.cat = Category(forum=self.forum, name='test_category')
        self.cat.save()
        self.thr = Thread(category=self.cat, name='test_thread')
        self.thr.save()
        self.p = Post(thread=self.thr, content='Test post!',
                      author=self.user, add_date=self.past)
        self.p.save()

    def assertContainsReportOption(self, response):
        self.assertNotContains(response, 'This post was reported')
        self.assertContains(response, 'report')

    def assertContainsApproveOption(self, response):
        self.assertNotContains(response,
                               'This post was approved.')
        self.assertContains(response, 'approve')

    def test_report(self):
        self.assertTrue(self.client.login(username='******'))
        url = reverse('forum_post_report',
                      kwargs={'contest_id': self.contest.id,
                              'category_id': self.cat.id,
                              'thread_id': self.thr.id,
                              'post_id': self.p.id})
        name = self.user.first_name
        surname = self.user.last_name
        response = self.client.post(url, follow=True)
        self.assertContains(response, 'This post was reported')
        self.assertTrue(self.client.login(username='******'))
        url = reverse('forum_thread', kwargs={'category_id': self.cat.id,
                                              'thread_id': self.thr.id})
        response = self.client.post(url, follow=True)

        reported_pattern = r"was reported\s*by\s*<a[^>]*>\s*%s %s\s*<\/a>" \
                           % (name, surname)
        self.assertTrue(re.search(reported_pattern, response.content.decode('utf-8')))

    def test_approve_after_report(self):
        self.assertTrue(self.client.login(username='******'))
        url = reverse('forum_thread', kwargs={'contest_id': self.contest.id,
                                              'category_id': self.cat.id,
                                              'thread_id': self.thr.id})
        response = self.client.get(url, follow=True)
        self.assertContainsReportOption(response)
        self.assertContainsApproveOption(response)

        self.assertTrue(self.client.login(username='******'))
        url = reverse('forum_thread', kwargs={'contest_id': self.contest.id,
                                              'category_id': self.cat.id,
                                              'thread_id': self.thr.id})
        response = self.client.get(url, follow=True)
        self.assertContainsReportOption(response)
        self.assertNotContains(response, 'approve')

        url = reverse('forum_post_report',
                      kwargs={'contest_id': self.contest.id,
                              'category_id': self.cat.id,
                              'thread_id': self.thr.id,
                              'post_id': self.p.id})
        response = self.client.post(url, follow=True)
        self.assertContains(response, 'This post was reported')

        self.assertTrue(self.client.login(username='******'))
        url = reverse('forum_post_approve',
                      kwargs={'contest_id': self.contest.id,
                              'category_id': self.cat.id,
                              'thread_id': self.thr.id,
                              'post_id': self.p.id})
        response = self.client.post(url, follow=True)
        self.assertContains(response, 'revoke approval')

        self.assertTrue(self.client.login(username='******'))
        url = reverse('forum_thread', kwargs={'contest_id': self.contest.id,
                                              'category_id': self.cat.id,
                                              'thread_id': self.thr.id})
        response = self.client.get(url, follow=True)
        self.assertNotContains(response, 'report')
        self.assertContains(response,
                            'This post was approved.')
        self.assertNotContains(response, 'revoke approval')

        self.p.refresh_from_db()
        self.assertTrue(self.p.approved)
        self.assertFalse(self.p.reported)

    def test_approve_without_report(self):
        self.assertTrue(self.client.login(username='******'))
        url = reverse('forum_thread', kwargs={'contest_id': self.contest.id,
                                              'category_id': self.cat.id,
                                              'thread_id': self.thr.id})
        response = self.client.get(url, follow=True)
        self.assertContainsReportOption(response)
        self.assertContainsApproveOption(response)

        url = reverse('forum_post_approve',
                      kwargs={'contest_id': self.contest.id,
                              'category_id': self.cat.id,
                              'thread_id': self.thr.id,
                              'post_id': self.p.id})
        self.client.post(url, follow=True)

        self.assertTrue(self.client.login(username='******'))
        url = reverse('forum_thread', kwargs={'contest_id': self.contest.id,
                                              'category_id': self.cat.id,
                                              'thread_id': self.thr.id})
        response = self.client.get(url, follow=True)
        self.assertNotContains(response, 'report')
        self.assertContains(response,
                            'This post was approved.')

        self.p.refresh_from_db()
        self.assertTrue(self.p.approved)
        self.assertFalse(self.p.reported)

    def test_report_after_approve(self):
        self.p.approved = True
        self.p.save()

        self.assertTrue(self.client.login(username='******'))
        url = reverse('forum_post_report',
                      kwargs={'contest_id': self.contest.id,
                              'category_id': self.cat.id,
                              'thread_id': self.thr.id,
                              'post_id': self.p.id})
        self.client.post(url)

        self.p.refresh_from_db()
        self.assertTrue(self.p.approved)
        self.assertFalse(self.p.reported)

        self.assertTrue(self.client.login(username='******'))
        url = reverse('forum_thread', kwargs={'contest_id': self.contest.id,
                                              'category_id': self.cat.id,
                                              'thread_id': self.thr.id})
        response = self.client.get(url, follow=True)
        self.assertNotContains(response, 'report')
        self.assertContains(response,
                            'This post was approved.')

    def test_revoking_approval_after_edit(self):
        self.p.approved = True
        self.p.save()

        self.assertTrue(self.client.login(username='******'))
        url = reverse('forum_post_edit',
                      kwargs={'contest_id': self.contest.id,
                              'category_id': self.cat.id,
                              'thread_id': self.thr.id,
                              'post_id': self.p.id})
        self.client.get(url, follow=True)

        self.p.refresh_from_db()
        self.assertTrue(self.p.approved)

        url = reverse('forum_post_edit',
                      kwargs={'contest_id': self.contest.id,
                              'category_id': self.cat.id,
                              'thread_id': self.thr.id,
                              'post_id': self.p.id})
        self.client.post(url, {'content': 'Test content'})

        self.p.refresh_from_db()
        self.assertFalse(self.p.approved)

    def test_admin_approval_edit(self):
        self.p.reported = True
        self.p.save()

        data = {
            'content': self.p.content,
            'thread': self.thr.id,
            'reported': self.p.reported,
            'approved': True
        }

        self.assertTrue(self.client.login(username='******'))
        self.client.get('/c/c/')  # 'c' becomes the current contest
        url = reverse('oioioiadmin:forum_post_change', args=(self.p.id,))
        self.client.post(url, data)

        self.p.refresh_from_db()
        self.assertTrue(self.p.approved)
        self.assertFalse(self.p.reported)

        data['reported'] = True
        self.client.post(url, data)

        self.p.refresh_from_db()
        self.assertTrue(self.p.approved)
        self.assertFalse(self.p.reported)

    def test_admin_approve_action(self):
        self.p.reported = True
        self.p.save()

        data = {'_selected_action': (self.p.id, ),
                'action': 'approve_action'}

        self.assertTrue(self.client.login(username='******'))
        self.client.get('/c/c/')  # 'c' becomes the current contest
        url = reverse('oioioiadmin:forum_post_changelist')
        self.client.post(url, data, follow=True)

        self.p.refresh_from_db()
        self.assertTrue(self.p.approved)
        self.assertFalse(self.p.reported)

    def test_admin_revoke_approval_action(self):
        self.p.approved = True
        self.p.save()

        data = {'_selected_action': (self.p.id, ),
                'action': 'revoke_approval_action'}

        self.assertTrue(self.client.login(username='******'))
        self.client.get('/c/c/')  # 'c' becomes the current contest
        url = reverse('oioioiadmin:forum_post_changelist')
        self.client.post(url, data, follow=True)

        self.p.refresh_from_db()
        self.assertFalse(self.p.approved)
        self.assertFalse(self.p.reported)

    def test_revoke_approval(self):
        self.p.approved = True
        self.p.save()

        self.assertTrue(self.client.login(username='******'))
        url = reverse('forum_thread', kwargs={'contest_id': self.contest.id,
                                              'category_id': self.cat.id,
                                              'thread_id': self.thr.id})
        response = self.client.get(url, follow=True)
        self.assertNotContains(response, 'revoke approval')

        self.assertTrue(self.client.login(username='******'))
        url = reverse('forum_thread', kwargs={'contest_id': self.contest.id,
                                              'category_id': self.cat.id,
                                              'thread_id': self.thr.id})
        response = self.client.get(url, follow=True)
        self.assertContains(response, 'revoke approval')

        url = reverse('forum_post_revoke_approval',
                      kwargs={'contest_id': self.contest.id,
                              'category_id': self.cat.id,
                              'thread_id': self.thr.id,
                              'post_id': self.p.id})
        response = self.client.post(url, follow=True)
        self.assertNotContains(response, 'revoke approval')

        self.p.refresh_from_db()
        self.assertFalse(self.p.approved)
        self.assertFalse(self.p.reported)
コード例 #8
0
class TestPost(TestCase):
    fixtures = ['test_users', 'test_contest']

    def setUp(self):
        delta = timedelta(days=3)
        self.past = timezone.now() - delta
        self.contest = get_contest_with_forum()
        self.user = User.objects.get(username='******')
        self.forum = self.contest.forum
        self.cat = Category(forum=self.forum, name='test_category')
        self.cat.save()
        self.thr = Thread(category=self.cat, name='test_thread')
        self.thr.save()
        self.p = Post(thread=self.thr,
                      content='Test post!',
                      author=self.user,
                      add_date=self.past)
        self.p.save()
        self.thread_url = reverse(
            'forum_thread',
            kwargs={
                'contest_id': self.contest.id,
                'category_id': self.cat.id,
                'thread_id': self.thr.id,
            },
        )

    def reverse_post(self, view_name):
        return reverse(
            view_name,
            kwargs={
                'contest_id': self.contest.id,
                'category_id': self.cat.id,
                'thread_id': self.thr.id,
                'post_id': self.p.id,
            },
        )

    def assertContainsReportOption(self, response):
        self.assertNotContains(response, 'This post was reported')
        self.assertContains(response, 'report')

    def assertContainsApproveOption(self, response):
        self.assertNotContains(response, 'This post was approved.')
        self.assertContains(response, 'approve')

    def report_post(self):
        self.p.reported = True
        self.p.reported_by = self.user
        self.p.save()

    def test_report(self):
        self.assertTrue(self.client.login(username='******'))
        url = self.reverse_post('forum_post_report')
        name = self.user.first_name
        surname = self.user.last_name
        response = self.client.get(url, follow=True)
        self.assertContains(response, 'Report confirmation')
        self.report_post()
        self.assertTrue(self.client.login(username='******'))
        url = reverse(
            'forum_thread',
            kwargs={
                'category_id': self.cat.id,
                'thread_id': self.thr.id
            },
        )
        response = self.client.post(url, follow=True)

        reported_pattern = r"was reported\s*by\s*<a[^>]*>\s*%s %s\s*<\/a>" % (
            name,
            surname,
        )
        self.assertTrue(
            re.search(reported_pattern, response.content.decode('utf-8')))

    def test_approve_after_report(self):
        self.assertTrue(self.client.login(username='******'))

        response = self.client.get(self.thread_url, follow=True)
        self.assertContainsReportOption(response)
        self.assertContainsApproveOption(response)

        self.assertTrue(self.client.login(username='******'))

        response = self.client.get(self.thread_url, follow=True)
        self.assertContainsReportOption(response)
        self.assertNotContains(response, 'approve')

        self.report_post()
        response = self.client.post(self.thread_url, follow=True)
        self.assertContains(response, 'This post was reported')

        self.assertTrue(self.client.login(username='******'))
        url = self.reverse_post('forum_post_approve')
        response = self.client.post(url, follow=True)
        self.assertContains(response, 'revoke approval')
        self.assertContains(response, 'This post was approved.')

        self.assertTrue(self.client.login(username='******'))

        response = self.client.get(self.thread_url, follow=True)
        self.assertNotContains(response, 'report')
        self.assertNotContains(response, 'revoke approval')

        self.p.refresh_from_db()
        self.assertTrue(self.p.approved)
        self.assertFalse(self.p.reported)

    def test_approve_without_report(self):
        self.assertTrue(self.client.login(username='******'))

        response = self.client.get(self.thread_url, follow=True)
        self.assertContainsReportOption(response)
        self.assertContainsApproveOption(response)

        url = self.reverse_post('forum_post_approve')
        self.client.post(url, follow=True)

        self.assertTrue(self.client.login(username='******'))
        response = self.client.get(self.thread_url, follow=True)
        self.assertNotContains(response, 'report')

        self.p.refresh_from_db()
        self.assertTrue(self.p.approved)
        self.assertFalse(self.p.reported)

    def test_report_after_approve(self):
        self.p.approved = True
        self.p.save()

        self.assertTrue(self.client.login(username='******'))
        url = self.reverse_post('forum_post_report')
        self.client.post(url)

        self.p.refresh_from_db()
        self.assertTrue(self.p.approved)
        self.assertFalse(self.p.reported)

        self.assertTrue(self.client.login(username='******'))
        response = self.client.get(self.thread_url, follow=True)
        self.assertNotContains(response, 'report')

    def test_revoking_approval_after_edit(self):
        self.p.approved = True
        self.p.save()

        self.assertTrue(self.client.login(username='******'))
        url = self.reverse_post('forum_post_edit')
        self.client.get(url, follow=True)

        self.p.refresh_from_db()
        self.assertTrue(self.p.approved)

        self.client.post(url, {'content': 'Test content'})

        self.p.refresh_from_db()
        self.assertFalse(self.p.approved)

    def test_admin_approval_edit(self):
        self.p.reported = True
        self.p.save()

        data = {
            'content': self.p.content,
            'thread': self.thr.id,
            'reported': self.p.reported,
            'approved': True,
        }

        self.assertTrue(self.client.login(username='******'))
        self.client.get('/c/c/')  # 'c' becomes the current contest
        url = reverse('oioioiadmin:forum_post_change', args=(self.p.id, ))
        self.client.post(url, data)

        self.p.refresh_from_db()
        self.assertTrue(self.p.approved)
        self.assertFalse(self.p.reported)

        data['reported'] = True
        self.client.post(url, data)

        self.p.refresh_from_db()
        self.assertTrue(self.p.approved)
        self.assertFalse(self.p.reported)

    def test_admin_approve_action(self):
        self.p.reported = True
        self.p.save()

        data = {'_selected_action': (self.p.id, ), 'action': 'approve_action'}

        self.assertTrue(self.client.login(username='******'))
        self.client.get('/c/c/')  # 'c' becomes the current contest
        url = reverse('oioioiadmin:forum_post_changelist')
        self.client.post(url, data, follow=True)

        self.p.refresh_from_db()
        self.assertTrue(self.p.approved)
        self.assertFalse(self.p.reported)

    def test_admin_revoke_approval_action(self):
        self.p.approved = True
        self.p.save()

        data = {
            '_selected_action': (self.p.id, ),
            'action': 'revoke_approval_action'
        }

        self.assertTrue(self.client.login(username='******'))
        self.client.get('/c/c/')  # 'c' becomes the current contest
        url = reverse('oioioiadmin:forum_post_changelist')
        self.client.post(url, data, follow=True)

        self.p.refresh_from_db()
        self.assertFalse(self.p.approved)
        self.assertFalse(self.p.reported)

    def test_revoke_approval(self):
        self.p.approved = True
        self.p.save()

        self.assertTrue(self.client.login(username='******'))
        response = self.client.get(self.thread_url, follow=True)
        self.assertNotContains(response, 'revoke approval')

        self.assertTrue(self.client.login(username='******'))
        response = self.client.get(self.thread_url, follow=True)
        self.assertContains(response, 'revoke approval')

        url = self.reverse_post('forum_post_revoke_approval')
        response = self.client.post(url, follow=True)
        self.assertNotContains(response, 'revoke approval')

        self.p.refresh_from_db()
        self.assertFalse(self.p.approved)
        self.assertFalse(self.p.reported)

    def test_reactions_visible_only_if_enabled(self):
        self.cat.reactions_enabled = False
        self.cat.save()
        response = self.client.get(self.thread_url, follow=True)
        self.assertNotContains(response, 'post_reactions')

        self.cat.reactions_enabled = True
        self.cat.save()
        response = self.client.get(self.thread_url, follow=True)
        self.assertContains(response, 'post_reactions')

    def test_reactions_not_clickable_for_anon(self):
        react_url = self.reverse_post('forum_post_toggle_reaction')
        downvote_url = react_url + '?reaction=downvote'

        self.cat.reactions_enabled = True
        self.cat.save()

        response = self.client.get(self.thread_url, follow=True)
        self.assertEqual(200, response.status_code)
        self.assertNotContains(response, downvote_url)
        self.assertTrue(self.client.login(username='******'))
        response = self.client.get(self.thread_url, follow=True)
        self.assertEqual(200, response.status_code)
        self.assertContains(response, downvote_url)

    def test_reactions_from_multiple_users(self):
        react_url = self.reverse_post('forum_post_toggle_reaction')
        downvote_url = react_url + '?reaction=downvote'

        self.cat.reactions_enabled = True
        self.cat.save()

        self.assertTrue(self.client.login(username='******'))
        response = self.client.post(downvote_url, follow=True)
        self.assertEqual(200, response.status_code)
        self.assertTrue(self.client.login(username='******'))
        response = self.client.post(downvote_url, follow=True)
        self.assertEqual(200, response.status_code)

        self.assertEqual(
            2,
            self.p.reactions.filter(type_of_reaction='DOWNVOTE').count())
        self.assertEqual(2, self.p.reactions.count())

    def test_remove_reaction(self):
        react_url = self.reverse_post('forum_post_toggle_reaction')
        downvote_url = react_url + '?reaction=downvote'
        self.cat.reactions_enabled = True
        self.cat.save()
        self.assertTrue(self.client.login(username='******'))

        def count_reactions(r):
            return self.p.reactions.filter(type_of_reaction=r).count()

        self.assertEqual(0, count_reactions('DOWNVOTE'))
        self.assertEqual(0, self.p.reactions.count())

        self.client.post(downvote_url, follow=True)
        self.assertEqual(1, count_reactions('DOWNVOTE'))
        self.assertEqual(1, self.p.reactions.count())

        self.client.post(downvote_url, follow=True)
        self.assertEqual(0, count_reactions('DOWNVOTE'))
        self.assertEqual(0, self.p.reactions.count())

    def test_switch_reaction(self):
        react_url = self.reverse_post('forum_post_toggle_reaction')
        downvote_url = react_url + '?reaction=downvote'
        upvote_url = react_url + '?reaction=upvote'
        self.cat.reactions_enabled = True
        self.cat.save()
        self.assertTrue(self.client.login(username='******'))

        def count_reactions(r):
            return self.p.reactions.filter(type_of_reaction=r).count()

        self.assertEqual(0, self.p.reactions.count())

        self.client.post(upvote_url, follow=True)
        self.assertEqual(1, count_reactions('UPVOTE'))
        self.assertEqual(0, count_reactions('DOWNVOTE'))
        self.assertEqual(1, self.p.reactions.count())

        self.client.post(downvote_url, follow=True)
        self.assertEqual(0, count_reactions('UPVOTE'))
        self.assertEqual(1, count_reactions('DOWNVOTE'))
        self.assertEqual(1, self.p.reactions.count())