Exemple #1
0
 def setUp(self):
     self.user1 = ProfileFactory().user
     self.user2 = ProfileFactory().user
     self.to_be_changed_staff = StaffProfileFactory().user
     self.staff = StaffProfileFactory().user
     self.assertTrue(self.staff.has_perm('forum.change_topic'))
     self.category1 = CategoryFactory(position=1)
     self.forum11 = ForumFactory(category=self.category1, position_in_category=1)
     self.forum12 = ForumFactory(category=self.category1, position_in_category=2)
     for group in self.staff.groups.all():
         self.forum12.groups.add(group)
     self.forum12.save()
Exemple #2
0
    def setUp(self):
        self.user1 = ProfileFactory()
        self.staff = StaffProfileFactory()

        # Create a forum for later test
        self.forumcat = CategoryFactory()
        self.forum = ForumFactory(category=self.forumcat)
        self.forumtopic = TopicFactory(forum=self.forum, author=self.staff.user)
Exemple #3
0
    def setUp(self):

        settings.EMAIL_BACKEND = 'django.core.mail.backends.locmem.EmailBackend'
        self.mas = ProfileFactory().user
        settings.ZDS_APP['member']['bot_account'] = self.mas.username

        self.category, self.forum = create_category_and_forum()

        self.user = ProfileFactory().user
        self.staff = StaffProfileFactory().user

        self.index_manager = ESIndexManager(**settings.ES_SEARCH_INDEX)
Exemple #4
0
    def setUp(self):

        self.staff = StaffProfileFactory().user

        settings.EMAIL_BACKEND = 'django.core.mail.backends.locmem.EmailBackend'
        self.mas = ProfileFactory().user
        self.overridden_zds_app['member']['bot_account'] = self.mas.username

        self.licence = LicenceFactory()
        self.subcategory = SubCategoryFactory()

        self.user_author = ProfileFactory().user
        self.user_staff = StaffProfileFactory().user
        self.user_guest = ProfileFactory().user

        self.tuto = PublishableContentFactory(type='TUTORIAL')
        self.tuto.authors.add(self.user_author)
        UserGalleryFactory(gallery=self.tuto.gallery,
                           user=self.user_author,
                           mode='W')
        self.tuto.licence = self.licence
        self.tuto.subcategory.add(self.subcategory)
        self.tuto.save()

        self.beta_forum = ForumFactory(
            pk=self.overridden_zds_app['forum']['beta_forum_id'],
            category=ForumCategoryFactory(position=1),
            position_in_category=1
        )  # ensure that the forum, for the beta versions, is created

        self.tuto_draft = self.tuto.load_version()
        self.part1 = ContainerFactory(parent=self.tuto_draft,
                                      db_object=self.tuto)
        self.chapter1 = ContainerFactory(parent=self.part1,
                                         db_object=self.tuto)

        self.extract1 = ExtractFactory(container=self.chapter1,
                                       db_object=self.tuto)
        bot = Group(name=self.overridden_zds_app['member']['bot_group'])
        bot.save()
Exemple #5
0
    def test_request_content_exports_generation(self):
        author = ProfileFactory()
        not_author = ProfileFactory()
        staff = StaffProfileFactory()

        content = PublishedContentFactory(
            author_list=[author.user]).public_version

        self.assertEqual(
            0,
            PublicationEvent.objects.filter(published_object=content).count())

        # Anonymous sender should not be able to ask for exports generation
        response = self.client.post(
            reverse("api:content:generate_export", args=[content.content.pk]))
        self.assertEqual(response.status_code, status.HTTP_401_UNAUTHORIZED)
        self.assertEqual(
            0,
            PublicationEvent.objects.filter(published_object=content).count())

        # An authenticated author but not an author should not either
        self.client.force_login(not_author.user)
        response = self.client.post(
            reverse("api:content:generate_export", args=[content.content.pk]))
        self.assertEqual(response.status_code, status.HTTP_403_FORBIDDEN)
        self.assertEqual(
            0,
            PublicationEvent.objects.filter(published_object=content).count())

        # But if the user is staff, it should
        self.client.force_login(staff.user)
        response = self.client.post(
            reverse("api:content:generate_export", args=[content.content.pk]))
        self.assertEqual(response.status_code, status.HTTP_201_CREATED)

        requests_count = PublicationEvent.objects.filter(
            published_object=content).count()
        self.assertGreater(requests_count, 0)

        # And if the user is an author, it should too
        self.client.force_login(author.user)
        response = self.client.post(
            reverse("api:content:generate_export", args=[content.content.pk]))
        self.assertEqual(response.status_code, status.HTTP_201_CREATED)

        # And it should be greater than the previous one as we added new requets
        self.assertGreater(
            PublicationEvent.objects.filter(published_object=content).count(),
            requests_count)

        self.client.logout()
Exemple #6
0
 def test_forbidden_email_provider_register_form(self):
     moderator = StaffProfileFactory().user
     if not BannedEmailProvider.objects.filter(
             provider='yopmail.com').exists():
         BannedEmailProvider.objects.create(provider='yopmail.com',
                                            moderator=moderator)
     data = {
         'email': '*****@*****.**',
         'username': '******',
         'password': '******',
         'password_confirm': 'ZePassword'
     }
     form = RegisterForm(data=data)
     self.assertFalse(form.is_valid())
Exemple #7
0
    def test_success_list_create_message(self):
        staff = StaffProfileFactory()
        login_check = self.client.login(username=staff.user.username,
                                        password='******')
        self.assertTrue(login_check)

        response = self.client.post(reverse('featured-message-create'), {
            'message': 'message',
            'url': 'http://test.com',
        },
                                    follow=True)

        self.assertEqual(200, response.status_code)
        self.assertEqual(1, FeaturedMessage.objects.count())
Exemple #8
0
 def test_forbidden_email_provider_register_form(self):
     moderator = StaffProfileFactory().user
     if not BannedEmailProvider.objects.filter(
             provider="yopmail.com").exists():
         BannedEmailProvider.objects.create(provider="yopmail.com",
                                            moderator=moderator)
     data = {
         "email": "*****@*****.**",
         "username": "******",
         "password": "******",
         "password_confirm": "ZePassword",
     }
     form = RegisterForm(data=data)
     self.assertFalse(form.is_valid())
Exemple #9
0
    def test_success_list_delete_featured(self):
        staff = StaffProfileFactory()
        self.client.force_login(staff.user)

        news = FeaturedResourceFactory()
        news2 = FeaturedResourceFactory()
        self.assertEqual(2, FeaturedResource.objects.all().count())
        response = self.client.post(
            reverse("featured-resource-list-delete"), {"items": [news.pk, news2.pk]}, follow=True
        )

        self.assertEqual(200, response.status_code)
        self.assertEqual(0, FeaturedResource.objects.filter(pk=news.pk).count())
        self.assertEqual(0, FeaturedResource.objects.filter(pk=news2.pk).count())
Exemple #10
0
    def setUp(self):
        # don't build PDF to speed up the tests
        settings.ZDS_APP['content']['build_pdf_when_published'] = False

        settings.EMAIL_BACKEND = 'django.core.mail.backends.locmem.EmailBackend'
        self.mas = ProfileFactory().user
        settings.ZDS_APP['member']['bot_account'] = self.mas.username

        self.category, self.forum = create_category()

        self.user = ProfileFactory().user
        self.staff = StaffProfileFactory().user

        self.index_manager = ESIndexManager(**settings.ES_SEARCH_INDEX)
Exemple #11
0
    def test_success_create_featured(self):
        staff = StaffProfileFactory()
        login_check = self.client.login(username=staff.user.username,
                                        password='******')

        self.assertTrue(login_check)
        self.assertEqual(0, FeaturedResource.objects.all().count())

        pubdate = date(2016, 1, 1).strftime('%d/%m/%Y %H:%M:%S')

        fields = {
            'title': 'title',
            'type': 'type',
            'image_url': 'http://test.com/image.png',
            'url': 'http://test.com',
            'authors': staff.user.username,
            'pubdate': pubdate
        }

        response = self.client.post(reverse('featured-resource-create'),
                                    fields,
                                    follow=True)

        self.assertEqual(200, response.status_code)
        self.assertEqual(1, FeaturedResource.objects.all().count())

        featured = FeaturedResource.objects.first()

        for field, value in list(fields.items()):
            if field != 'pubdate':
                self.assertEqual(value,
                                 getattr(featured, field),
                                 msg='Error on {}'.format(field))
            else:
                self.assertEqual(
                    value, featured.pubdate.strftime('%d/%m/%Y %H:%M:%S'))

        # now with major_update
        fields['major_update'] = 'on'

        response = self.client.post(reverse('featured-resource-create'),
                                    fields,
                                    follow=True)
        self.assertEqual(200, response.status_code)
        self.assertEqual(2, FeaturedResource.objects.all().count())

        featured = FeaturedResource.objects.last()
        self.assertTrue(
            (datetime.now() - featured.pubdate).total_seconds() < 10)
Exemple #12
0
    def test_success_create_featured(self):
        staff = StaffProfileFactory()
        login_check = self.client.login(username=staff.user.username,
                                        password="******")

        self.assertTrue(login_check)
        self.assertEqual(0, FeaturedResource.objects.all().count())

        pubdate = date(2016, 1, 1).strftime("%d/%m/%Y %H:%M:%S")

        fields = {
            "title": "title",
            "type": "type",
            "image_url": "http://test.com/image.png",
            "url": "http://test.com",
            "authors": staff.user.username,
            "pubdate": pubdate,
        }

        response = self.client.post(reverse("featured-resource-create"),
                                    fields,
                                    follow=True)

        self.assertEqual(200, response.status_code)
        self.assertEqual(1, FeaturedResource.objects.all().count())

        featured = FeaturedResource.objects.first()

        for field, value in list(fields.items()):
            if field != "pubdate":
                self.assertEqual(value,
                                 getattr(featured, field),
                                 msg="Error on {}".format(field))
            else:
                self.assertEqual(
                    value, featured.pubdate.strftime("%d/%m/%Y %H:%M:%S"))

        # now with major_update
        fields["major_update"] = "on"

        response = self.client.post(reverse("featured-resource-create"),
                                    fields,
                                    follow=True)
        self.assertEqual(200, response.status_code)
        self.assertEqual(2, FeaturedResource.objects.all().count())

        featured = FeaturedResource.objects.last()
        self.assertTrue(
            (datetime.now() - featured.pubdate).total_seconds() < 10)
Exemple #13
0
    def test_update(self):
        # create topic and content and toggle request
        author = ProfileFactory().user
        category = ForumCategoryFactory(position=1)
        forum = ForumFactory(category=category, position_in_category=1)
        topic = TopicFactory(forum=forum, author=author)

        FeaturedRequested.objects.toogle_request(topic, author)

        # ignore
        staff = StaffProfileFactory()
        login_check = self.client.login(username=staff.user.username,
                                        password="******")
        self.assertTrue(login_check)

        content_type = ContentType.objects.get_for_model(topic)
        q = FeaturedRequested.objects.get(object_id=topic.pk,
                                          content_type__pk=content_type.pk)
        self.assertFalse(q.rejected)

        response = self.client.post(reverse("featured-resource-request-update",
                                            kwargs={"pk": q.pk}),
                                    {"operation": "REJECT"},
                                    follow=False)
        self.assertEqual(200, response.status_code)

        q = FeaturedRequested.objects.get(pk=q.pk)
        self.assertTrue(q.rejected)
        self.assertFalse(q.rejected_for_good)

        response = self.client.post(reverse("featured-resource-request-update",
                                            kwargs={"pk": q.pk}),
                                    {"operation": "CONSIDER"},
                                    follow=False)
        self.assertEqual(200, response.status_code)

        q = FeaturedRequested.objects.get(pk=q.pk)
        self.assertFalse(q.rejected)

        response = self.client.post(
            reverse("featured-resource-request-update", kwargs={"pk": q.pk}),
            {"operation": "REJECT_FOR_GOOD"},
            follow=False,
        )
        self.assertEqual(200, response.status_code)

        q = FeaturedRequested.objects.get(pk=q.pk)
        self.assertTrue(q.rejected)
        self.assertTrue(q.rejected_for_good)
Exemple #14
0
 def setUp(self):
     settings.EMAIL_BACKEND = \
         'django.core.mail.backends.locmem.EmailBackend'
     self.mas = ProfileFactory()
     settings.ZDS_APP['member']['bot_account'] = self.mas.user.username
     self.anonymous = UserFactory(
         username=settings.ZDS_APP["member"]["anonymous_account"],
         password="******")
     self.external = UserFactory(
         username=settings.ZDS_APP["member"]["external_account"],
         password="******")
     self.category1 = CategoryFactory(position=1)
     self.forum11 = ForumFactory(category=self.category1,
                                 position_in_category=1)
     self.staff = StaffProfileFactory().user
Exemple #15
0
    def test_success_list_create_message(self):
        staff = StaffProfileFactory()
        self.client.force_login(staff.user)

        response = self.client.post(
            reverse("featured-message-create"),
            {
                "message": "message",
                "url": "http://test.com",
            },
            follow=True,
        )

        self.assertEqual(200, response.status_code)
        self.assertEqual(1, FeaturedMessage.objects.count())
    def setUp(self):
        # Create users
        self.author = ProfileFactory().user
        self.staff = StaffProfileFactory().user
        self.outsider = ProfileFactory().user

        # Create a content
        self.content = PublishableContentFactory(author_list=[self.author])

        # Get information to be reused in tests
        self.form_url = reverse("content:edit-tags", kwargs={"pk": self.content.pk})
        self.form_data = {"tags": "test2, test2"}
        self.content_data = {"pk": self.content.pk, "slug": self.content.slug}
        self.content_url = reverse("content:view", kwargs=self.content_data)
        self.login_url = reverse("member-login") + "?next=" + self.form_url
Exemple #17
0
 def test_success_initial_content_topic(self):
     author = ProfileFactory().user
     category = ForumCategoryFactory(position=1)
     forum = ForumFactory(category=category, position_in_category=1)
     topic = TopicFactory(forum=forum, author=author)
     staff = StaffProfileFactory()
     self.client.force_login(staff.user)
     response = self.client.get(
         "{}?content_type=topic&content_id={}".format(reverse("featured-resource-create"), topic.id)
     )
     initial_dict = response.context["form"].initial
     self.assertEqual(initial_dict["title"], topic.title)
     self.assertEqual(initial_dict["authors"], str(author))
     self.assertEqual(initial_dict["type"], _("Un sujet"))
     self.assertEqual(initial_dict["url"], f"http://testserver{topic.get_absolute_url()}")
Exemple #18
0
    def test_success_delete_featured(self):
        staff = StaffProfileFactory()
        login_check = self.client.login(username=staff.user.username,
                                        password='******')
        self.assertTrue(login_check)

        news = FeaturedResourceFactory()
        self.assertEqual(1, FeaturedResource.objects.all().count())
        response = self.client.post(reverse('featured-resource-delete',
                                            args=[news.pk]),
                                    follow=True)

        self.assertEqual(200, response.status_code)
        self.assertEqual(0,
                         FeaturedResource.objects.filter(pk=news.pk).count())
Exemple #19
0
    def setUp(self):
        self.user = ProfileFactory().user
        self.staff = StaffProfileFactory().user

        category, forum = create_category()
        topic = add_topic_in_a_forum(forum, self.user.profile)

        self.assertTrue(self.client.login(username=self.user.username, password='******'))
        data = {
            'text': 'A new post!'
        }
        self.client.post(
            reverse('post-edit') + '?message={}'.format(topic.last_message.pk), data, follow=False)
        self.post = topic.last_message
        self.edit = CommentEdit.objects.latest('date')
Exemple #20
0
    def setUp(self):

        # Create some forum's category
        self.category1 = CategoryFactory(position=1)
        self.category2 = CategoryFactory(position=2)

        # Create forum
        self.forum11 = ForumFactory(category=self.category1, position_in_category=1)

        # Only for staff
        self.staff1 = StaffProfileFactory()

        self.forum12 = ForumFactory(category=self.category2, position_in_category=2)
        self.forum12.group.add(Group.objects.filter(name='staff').first())
        self.forum12.save()
Exemple #21
0
 def test_intervention_filter_for_tribunes(self):
     author = ProfileFactory()
     opinion = PublishedContentFactory(type='OPINION', author_list=[author.user])
     alerter = ProfileFactory()
     staff = StaffProfileFactory()
     alert = Alert()
     alert.scope = 'CONTENT'
     alert.author = alerter.user
     alert.content = opinion
     alert.pubdate = datetime.datetime.now()
     alert.text = 'Something to say.'
     alert.save()
     filter_result = get_header_notifications(staff.user)['alerts']
     self.assertEqual(1, filter_result['total'])
     self.assertEqual(alert.text, filter_result['list'][0]['text'])
Exemple #22
0
class ForumNotification(TestCase):
    def setUp(self):
        self.user1 = ProfileFactory().user
        self.user2 = ProfileFactory().user
        self.staff = StaffProfileFactory().user
        self.assertTrue(self.staff.has_perm('forum.change_topic'))
        self.category1 = CategoryFactory(position=1)
        self.forum11 = ForumFactory(category=self.category1, position_in_category=1)
        self.forum12 = ForumFactory(category=self.category1, position_in_category=2)
        for group in self.staff.groups.all():
            self.forum12.group.add(group)
        self.forum12.save()

    def test_no_dead_notif_on_moving(self):
        NewTopicSubscription.objects.get_or_create_active(self.user1, self.forum11)
        self.assertTrue(self.client.login(username=self.user2.username, password='******'))
        result = self.client.post(
            reverse('topic-new') + '?forum={0}'.format(self.forum11.pk),
            {
                'title': u'Super sujet',
                'subtitle': u'Pour tester les notifs',
                'text': u"En tout cas l'un abonnement",
                'tags': ''
            },
            follow=False)
        self.assertEqual(result.status_code, 302)

        topic = Topic.objects.filter(title=u'Super sujet').first()
        subscription = NewTopicSubscription.objects.get_existing(self.user1, self.forum11, True)
        self.assertIsNotNone(subscription, 'There must be an active subscription for now')
        self.assertIsNotNone(subscription.last_notification, 'There must be a notification for now')
        self.assertFalse(subscription.last_notification.is_read)
        self.client.logout()
        self.assertTrue(self.client.login(username=self.staff.username, password='******'))
        data = {
            'move': '',
            'forum': self.forum12.pk,
            'topic': topic.pk
        }
        response = self.client.post(reverse('topic-edit'), data, follow=False)
        self.assertEqual(302, response.status_code)
        subscription = NewTopicSubscription.objects.get_existing(self.user1, self.forum11, True)
        self.assertIsNotNone(subscription, 'There must still be an active subscription')
        self.assertIsNotNone(subscription.last_notification,
                             'There must still be a notification as object is not removed.')
        self.assertEqual(subscription.last_notification,
                         Notification.objects.filter(sender=self.user2).first())
        self.assertTrue(subscription.last_notification.is_read, 'As forum is not reachable, notification is read')
Exemple #23
0
 def test_intervention_filter_for_tribunes(self):
     author = ProfileFactory()
     opinion = PublishedContentFactory(type="OPINION",
                                       author_list=[author.user])
     alerter = ProfileFactory()
     staff = StaffProfileFactory()
     alert = Alert()
     alert.scope = "CONTENT"
     alert.author = alerter.user
     alert.content = opinion
     alert.pubdate = datetime.datetime.now()
     alert.text = "Something to say."
     alert.save()
     filter_result = get_header_notifications(staff.user)["alerts"]
     self.assertEqual(1, filter_result["total"])
     self.assertEqual(alert.text, filter_result["list"][0]["text"])
Exemple #24
0
    def test_success_list_create_message(self):
        staff = StaffProfileFactory()
        login_check = self.client.login(username=staff.user.username, password="******")
        self.assertTrue(login_check)

        response = self.client.post(
            reverse("featured-message-create"),
            {
                "message": "message",
                "url": "http://test.com",
            },
            follow=True,
        )

        self.assertEqual(200, response.status_code)
        self.assertEqual(1, FeaturedMessage.objects.count())
Exemple #25
0
    def setUp(self):

        settings.EMAIL_BACKEND = 'django.core.mail.backends.locmem.EmailBackend'
        self.mas = ProfileFactory().user
        settings.ZDS_APP['member']['bot_account'] = self.mas.username

        self.category, self.forum = create_category_and_forum()

        self.user = ProfileFactory().user
        self.staff = StaffProfileFactory().user

        self.manager = ESIndexManager(**settings.ES_SEARCH_INDEX)
        self.indexable = [FakeChapter, PublishedContent, Topic, Post]

        self.manager.reset_es_index(self.indexable)
        self.manager.setup_custom_analyzer()
        self.manager.refresh_index()
Exemple #26
0
    def setUp(self):

        settings.EMAIL_BACKEND = 'django.core.mail.backends.locmem.EmailBackend'
        self.mas = ProfileFactory().user
        settings.ZDS_APP['member']['bot_account'] = self.mas.username

        self.category, self.forum = create_category_and_forum()

        self.user = ProfileFactory().user
        self.staff = StaffProfileFactory().user

        self.manager = ESIndexManager(**settings.ES_SEARCH_INDEX)
        self.indexable = [FakeChapter, PublishedContent, Topic, Post]

        self.manager.reset_es_index(self.indexable)
        self.manager.setup_custom_analyzer()
        self.manager.refresh_index()
Exemple #27
0
    def setUp(self):
        self.user = ProfileFactory().user
        self.staff = StaffProfileFactory().user

        _, forum = create_category_and_forum()
        topic = create_topic_in_forum(forum, self.user.profile)

        self.assertTrue(
            self.client.login(username=self.user.username,
                              password="******"))
        data = {"text": "A new post!"}
        self.client.post(reverse("post-edit") +
                         "?message={}".format(topic.last_message.pk),
                         data,
                         follow=False)
        self.post = topic.last_message
        self.edit = CommentEdit.objects.latest("date")
Exemple #28
0
    def test_move_topic_from_forum_followed_to_forum_followed_too(self):
        NewTopicSubscription.objects.toggle_follow(self.forum11, self.user1)
        NewTopicSubscription.objects.toggle_follow(self.forum12, self.user1)

        topic = TopicFactory(forum=self.forum11, author=self.user2)
        PostFactory(topic=topic, author=self.user2, position=1)
        self.assertEqual(
            1,
            len(
                Notification.objects.filter(object_id=topic.pk,
                                            is_read=False).all()))

        # Move the topic to another forum.
        self.client.logout()
        staff = StaffProfileFactory()
        self.assertTrue(
            self.client.login(username=staff.user.username,
                              password='******'))
        data = {'move': '', 'forum': self.forum12.pk, 'topic': topic.pk}
        response = self.client.post(reverse('topic-edit'), data, follow=False)
        self.assertEqual(302, response.status_code)

        topic = Topic.objects.get(pk=topic.pk)
        self.assertEqual(self.forum12, topic.forum)
        self.assertEqual(
            1,
            len(
                Notification.objects.filter(object_id=topic.pk,
                                            is_read=False,
                                            is_dead=False).all()))

        self.client.logout()
        self.assertTrue(
            self.client.login(username=self.user1.username,
                              password='******'))
        response = self.client.get(
            reverse('topic-posts-list', args=[topic.pk, topic.slug()]))
        self.assertEqual(200, response.status_code)

        self.assertEqual(
            1,
            len(
                Notification.objects.filter(object_id=topic.pk,
                                            is_read=True,
                                            is_dead=False).all()))
Exemple #29
0
 def test_no_alert_on_unpublish(self):
     """related to #4860"""
     published = PublishedContentFactory(type='OPINION',
                                         author_list=[self.user_author])
     reaction = ContentReactionFactory(related_content=published,
                                       author=ProfileFactory().user,
                                       position=1,
                                       pubdate=datetime.datetime.now())
     Alert.objects.create(scope='CONTENT',
                          comment=reaction,
                          text='a text',
                          author=ProfileFactory().user,
                          pubdate=datetime.datetime.now(),
                          content=published)
     staff = StaffProfileFactory().user
     self.assertEqual(1, get_header_notifications(staff)['alerts']['total'])
     unpublish_content(published, staff)
     self.assertEqual(0, get_header_notifications(staff)['alerts']['total'])
Exemple #30
0
    def test_mark_as_potential_spam_forum(self):
        author = ProfileFactory()
        staff = StaffProfileFactory()

        _, forum = create_category_and_forum()
        topic = create_topic_in_forum(forum, author)
        PostFactory(topic=topic, author=author.user, position=2)

        comment = topic.last_message

        self.common_test_mark_as_potential_spam(
            url_comments_list=reverse("topic-posts-list",
                                      args=[topic.pk, topic.slug()]),
            url_comment_edit=reverse("post-edit") + f"?message={comment.pk}",
            comment=comment,
            author=author,
            staff=staff,
        )
Exemple #31
0
    def test_subscription_deactivated_and_notification_read_when_topic_moved(
            self):
        """
        When a topic is moved to a forum where subscribers can't read it, the subscriptions
        should be deactivated and notifications marked as read.
        """
        topic = TopicFactory(forum=self.forum11, author=self.user1)
        PostFactory(topic=topic, author=self.user1, position=1)
        other_user = ProfileFactory().user
        TopicAnswerSubscription.objects.toggle_follow(topic, other_user)
        PostFactory(topic=topic, author=ProfileFactory().user, position=2)

        self.assertIsNotNone(
            TopicAnswerSubscription.objects.get_existing(self.user1,
                                                         topic,
                                                         is_active=True))
        self.assertIsNotNone(
            Notification.objects.get(subscription__user=self.user1,
                                     is_read=False))

        forum_not_read = ForumFactory(category=self.category1,
                                      position_in_category=2)
        forum_not_read.groups.add(Group.objects.create(name='DummyGroup_1'))

        self.assertTrue(
            self.client.login(username=StaffProfileFactory().user.username,
                              password='******'))
        data = {'move': '', 'forum': forum_not_read.pk, 'topic': topic.pk}
        response = self.client.post(reverse('topic-edit'), data, follow=False)

        self.assertEqual(302, response.status_code)
        self.assertIsNotNone(
            TopicAnswerSubscription.objects.get_existing(self.user1,
                                                         topic,
                                                         is_active=False))
        self.assertIsNotNone(
            Notification.objects.get(subscription__user=self.user1,
                                     is_read=True))
        self.assertFalse(
            TopicAnswerSubscription.objects.get_existing(other_user,
                                                         topic).is_active)
        self.assertIsNotNone(
            Notification.objects.get(subscription__user=other_user,
                                     is_read=True))
Exemple #32
0
    def test_success_update_featured(self):
        staff = StaffProfileFactory()
        self.client.force_login(staff.user)

        news = FeaturedResourceFactory()
        self.assertEqual(1, FeaturedResource.objects.all().count())

        old_featured = FeaturedResource.objects.first()

        pubdate = date(2016, 1, 1).strftime("%d/%m/%Y %H:%M:%S")

        fields = {
            "title": "title",
            "type": "type",
            "image_url": "http://test.com/image.png",
            "url": "http://test.com",
            "authors": staff.user.username,
            "pubdate": pubdate,
        }

        response = self.client.post(reverse("featured-resource-update", args=[news.pk]), fields, follow=True)

        self.assertEqual(200, response.status_code)
        self.assertEqual(1, FeaturedResource.objects.all().count())

        featured = FeaturedResource.objects.first()

        for field, value in list(fields.items()):
            self.assertNotEqual(getattr(featured, field), getattr(old_featured, field))

            if field != "pubdate":
                self.assertEqual(value, getattr(featured, field), msg=f"Error on {field}")
            else:
                self.assertEqual(value, featured.pubdate.strftime("%d/%m/%Y %H:%M:%S"))

        # now with major_update
        self.assertFalse((datetime.now() - featured.pubdate).total_seconds() < 10)

        fields["major_update"] = "on"

        response = self.client.post(reverse("featured-resource-update", args=[news.pk]), fields, follow=True)
        self.assertEqual(200, response.status_code)
        featured = FeaturedResource.objects.first()
        self.assertTrue((datetime.now() - featured.pubdate).total_seconds() < 10)
Exemple #33
0
    def test_filter_member_ip(self):
        """
        Test filter member by ip.
        """

        # create users (one regular and one staff and superuser)
        tester = ProfileFactory()
        staff = StaffProfileFactory()

        # test login normal user
        result = self.client.post(reverse('member-login'), {
            'username': tester.user.username,
            'password': '******',
            'remember': 'remember'
        },
                                  follow=False)
        # good password then redirection
        self.assertEqual(result.status_code, 302)

        # Check that the filter can't be access from normal user
        result = self.client.post(
            reverse('member-from-ip',
                    kwargs={'ip_address': tester.last_ip_address}), {},
            follow=False)
        self.assertEqual(result.status_code, 403)

        # log the staff user
        result = self.client.post(reverse('member-login'), {
            'username': staff.user.username,
            'password': '******',
            'remember': 'remember'
        },
                                  follow=False)
        # good password then redirection
        self.assertEqual(result.status_code, 302)

        # test that we retrieve correctly the 2 members (staff + user) from this ip
        result = self.client.post(
            reverse('member-from-ip',
                    kwargs={'ip_address': staff.last_ip_address}), {},
            follow=False)
        self.assertEqual(result.status_code, 200)
        self.assertEqual(len(result.context['members']), 2)
Exemple #34
0
class ForumNotification(TestCase):
    def setUp(self):
        self.user1 = ProfileFactory().user
        self.user2 = ProfileFactory().user
        self.to_be_changed_staff = StaffProfileFactory().user
        self.staff = StaffProfileFactory().user
        self.assertTrue(self.staff.has_perm('forum.change_topic'))
        self.category1 = CategoryFactory(position=1)
        self.forum11 = ForumFactory(category=self.category1, position_in_category=1)
        self.forum12 = ForumFactory(category=self.category1, position_in_category=2)
        for group in self.staff.groups.all():
            self.forum12.groups.add(group)
        self.forum12.save()

    def test_ping_unknown(self):
        overridden_zds_app['comment']['enable_pings'] = True
        self.assertTrue(self.client.login(username=self.user2.username, password='******'))
        result = self.client.post(
            reverse('topic-new') + '?forum={0}'.format(self.forum11.pk),
            {
                'title': 'Super sujet',
                'subtitle': 'Pour tester les notifs',
                'text': '@anUnExistingUser is pinged, also a special chars user @{}',
                'tags': ''
            },
            follow=False)
        self.assertEqual(result.status_code, 302, 'Request must succeed')
        self.assertEqual(0, PingSubscription.objects.count(),
                         'As one user is pinged, only one subscription is created.')

    def test_no_auto_ping(self):
        overridden_zds_app['comment']['enable_pings'] = True
        self.assertTrue(self.client.login(username=self.user2.username, password='******'))
        result = self.client.post(
            reverse('topic-new') + '?forum={0}'.format(self.forum11.pk),
            {
                'title': 'Super sujet',
                'subtitle': 'Pour tester les notifs',
                'text': '@{} is pinged, not @{}'.format(self.user1.username, self.user2.username),
                'tags': ''
            },
            follow=False)
        self.assertEqual(result.status_code, 302)
        self.assertEqual(1, PingSubscription.objects.count(),
                         'As one user is pinged, only one subscription is created.')

    def test_no_reping_on_edition(self):
        """
        to be more accurate : on edition, only ping **new** members
        """
        overridden_zds_app['comment']['enable_pings'] = True
        self.assertTrue(self.client.login(username=self.user2.username, password='******'))
        result = self.client.post(
            reverse('topic-new') + '?forum={0}'.format(self.forum11.pk),
            {
                'title': 'Super sujet',
                'subtitle': 'Pour tester les notifs',
                'text': '@{} is pinged'.format(self.user1.username),
                'tags': ''
            },
            follow=False)
        self.assertEqual(result.status_code, 302)
        self.assertEqual(1, PingSubscription.objects.count(),
                         'As one user is pinged, only one subscription is created.')
        self.assertEqual(1, Notification.objects.count())
        user3 = ProfileFactory().user
        post = Topic.objects.last().last_message
        result = self.client.post(
            reverse('post-edit') + '?message={0}'.format(post.pk),
            {
                'title': 'Super sujet',
                'subtitle': 'Pour tester les notifs',
                'text': '@{} is pinged even twice @{}'.format(self.user1.username, self.user1.username),
                'tags': ''
            },
            follow=False)
        self.assertEqual(result.status_code, 302)
        self.assertEqual(1, PingSubscription.objects.count(),
                         'No added subscription.')
        self.assertEqual(1, Notification.objects.count())
        result = self.client.post(
            reverse('post-edit') + '?message={0}'.format(post.pk),
            {
                'title': 'Super sujet',
                'subtitle': 'Pour tester les notifs',
                'text': '@{} is pinged even twice @{} and add @{}'.format(self.user1.username,
                                                                          self.user1.username, user3.username),
                'tags': ''
            },
            follow=False)
        self.assertEqual(result.status_code, 302)
        self.assertEqual(2, PingSubscription.objects.count())
        self.assertEqual(2, Notification.objects.count())

    def test_loose_ping_on_edition(self):
        """
        to be more accurate : on edition, only ping **new** members
        """
        overridden_zds_app['comment']['enable_pings'] = True
        self.assertTrue(self.client.login(username=self.user2.username, password='******'))
        result = self.client.post(
            reverse('topic-new') + '?forum={0}'.format(self.forum11.pk),
            {
                'title': 'Super sujet',
                'subtitle': 'Pour tester les notifs',
                'text': '@{} is pinged'.format(self.user1.username),
                'tags': ''
            },
            follow=False)
        self.assertEqual(result.status_code, 302)
        self.assertEqual(1, PingSubscription.objects.count(),
                         'As one user is pinged, only one subscription is created.')
        self.assertEqual(1, Notification.objects.count())
        post = Topic.objects.last().last_message
        result = self.client.post(
            reverse('post-edit') + '?message={0}'.format(post.pk),
            {
                'title': 'Super sujet',
                'subtitle': 'Pour tester les notifs',
                'text': '@ {} is no more pinged '.format(self.user1.username),
                'tags': ''
            },
            follow=False)
        self.assertEqual(result.status_code, 302)
        self.assertEqual(1, PingSubscription.objects.count(),
                         'No added subscription.')
        self.assertFalse(PingSubscription.objects.first().is_active)
        self.assertEqual(1, Notification.objects.count())
        self.assertTrue(Notification.objects.first().is_read)

    def test_no_dead_notif_on_moving(self):
        NewTopicSubscription.objects.get_or_create_active(self.user1, self.forum11)
        self.assertTrue(self.client.login(username=self.user2.username, password='******'))
        result = self.client.post(
            reverse('topic-new') + '?forum={0}'.format(self.forum11.pk),
            {
                'title': 'Super sujet',
                'subtitle': 'Pour tester les notifs',
                'text': "En tout cas l'un abonnement",
                'tags': ''
            },
            follow=False)
        self.assertEqual(result.status_code, 302)

        topic = Topic.objects.filter(title='Super sujet').first()
        subscription = NewTopicSubscription.objects.get_existing(self.user1, self.forum11, True)
        self.assertIsNotNone(subscription, 'There must be an active subscription for now')
        self.assertIsNotNone(subscription.last_notification, 'There must be a notification for now')
        self.assertFalse(subscription.last_notification.is_read)
        self.client.logout()
        self.assertTrue(self.client.login(username=self.staff.username, password='******'))
        data = {
            'move': '',
            'forum': self.forum12.pk,
            'topic': topic.pk
        }
        response = self.client.post(reverse('topic-edit'), data, follow=False)
        self.assertEqual(302, response.status_code)
        subscription = NewTopicSubscription.objects.get_existing(self.user1, self.forum11, True)
        self.assertIsNotNone(subscription, 'There must still be an active subscription')
        self.assertIsNotNone(subscription.last_notification,
                             'There must still be a notification as object is not removed.')
        self.assertEqual(subscription.last_notification,
                         Notification.objects.filter(sender=self.user2).first())
        self.assertTrue(subscription.last_notification.is_read, 'As forum is not reachable, notification is read')

    def test_no_ping_on_private_forum(self):
        self.assertTrue(self.client.login(username=self.staff.username, password='******'))
        result = self.client.post(
            reverse('topic-new') + '?forum={0}'.format(self.forum12.pk),
            {
                'title': 'Super sujet',
                'subtitle': 'Pour tester les notifs',
                'text': 'ping @{}'.format(self.user1.username),
                'tags': ''
            },
            follow=False)
        self.assertEqual(result.status_code, 302)

        topic = Topic.objects.filter(title='Super sujet').first()
        subscription = PingSubscription.objects.get_existing(self.user1, topic.last_message, True)
        self.assertIsNone(subscription, 'There must be no active subscription for now')

    def test_no_dead_ping_notif_on_moving_to_private_forum(self):
        self.assertTrue(self.client.login(username=self.user2.username, password='******'))
        result = self.client.post(
            reverse('topic-new') + '?forum={0}'.format(self.forum11.pk),
            {
                'title': 'Super sujet',
                'subtitle': 'Pour tester les notifs',
                'text': 'ping @{}'.format(self.user1.username),
                'tags': ''
            },
            follow=False)
        self.assertEqual(result.status_code, 302)

        topic = Topic.objects.filter(title='Super sujet').first()
        subscription = PingSubscription.objects.get_existing(self.user1, topic.last_message, True)
        self.assertIsNotNone(subscription, 'There must be an active subscription for now')
        self.assertIsNotNone(subscription.last_notification, 'There must be a notification for now')
        self.assertFalse(subscription.last_notification.is_read)
        self.client.logout()
        self.assertTrue(self.client.login(username=self.staff.username, password='******'))
        data = {
            'move': '',
            'forum': self.forum12.pk,
            'topic': topic.pk
        }
        response = self.client.post(reverse('topic-edit'), data, follow=False)
        self.assertEqual(302, response.status_code)
        subscription = PingSubscription.objects.get_existing(self.user1, topic.last_message, True)
        self.assertIsNotNone(subscription, 'There must still be an active subscription')
        self.assertIsNotNone(subscription.last_notification,
                             'There must still be a notification as object is not removed.')
        self.assertEqual(subscription.last_notification,
                         Notification.objects.filter(sender=self.user2).first())
        self.assertTrue(subscription.last_notification.is_read, 'As forum is not reachable, notification is read')

    def test_no_more_notif_on_losing_all_groups(self):
        NewTopicSubscription.objects.get_or_create_active(self.to_be_changed_staff, self.forum12)
        self.assertTrue(self.client.login(username=self.staff.username, password='******'))
        self.client.post(
            reverse('topic-new') + '?forum={0}'.format(self.forum12.pk),
            {
                'title': 'Super sujet',
                'subtitle': 'Pour tester les notifs',
                'text': "En tout cas l'un abonnement",
                'tags': ''
            },
            follow=False)
        subscription = NewTopicSubscription.objects.get_existing(self.to_be_changed_staff, self.forum12, True)
        self.assertIsNotNone(subscription, 'There must be an active subscription for now')
        self.to_be_changed_staff.groups.clear()
        self.to_be_changed_staff.save()
        subscription = NewTopicSubscription.objects.get_existing(self.to_be_changed_staff, self.forum12, False)
        self.assertIsNotNone(subscription, 'There must be an active subscription for now')
        self.assertFalse(subscription.is_active)

    def test_no_more_notif_on_losing_one_group(self):
        NewTopicSubscription.objects.get_or_create_active(self.to_be_changed_staff, self.forum12)
        self.assertTrue(self.client.login(username=self.staff.username, password='******'))
        self.client.post(
            reverse('topic-new') + '?forum={0}'.format(self.forum12.pk),
            {
                'title': 'Super sujet',
                'subtitle': 'Pour tester les notifs',
                'text': "En tout cas l'un abonnement",
                'tags': ''
            },
            follow=False)
        subscription = NewTopicSubscription.objects.get_existing(self.to_be_changed_staff, self.forum12, True)
        self.assertIsNotNone(subscription, 'There must be an active subscription for now')
        self.to_be_changed_staff.groups.remove(list(self.to_be_changed_staff.groups.all())[0])
        self.to_be_changed_staff.save()
        subscription = NewTopicSubscription.objects.get_existing(self.to_be_changed_staff, self.forum12, False)
        self.assertIsNotNone(subscription, 'There must be an active subscription for now')
        self.assertFalse(subscription.is_active)
Exemple #35
0
class ViewsTests(TutorialTestMixin, TestCase):
    def setUp(self):

        settings.EMAIL_BACKEND = 'django.core.mail.backends.locmem.EmailBackend'
        self.mas = ProfileFactory().user
        settings.ZDS_APP['member']['bot_account'] = self.mas.username

        self.category, self.forum = create_category_and_forum()

        self.user = ProfileFactory().user
        self.staff = StaffProfileFactory().user

        self.manager = ESIndexManager(**settings.ES_SEARCH_INDEX)
        self.indexable = [FakeChapter, PublishedContent, Topic, Post]

        self.manager.reset_es_index(self.indexable)
        self.manager.setup_custom_analyzer()
        self.manager.refresh_index()

    def test_basic_search(self):
        """Basic search and filtering"""

        if not self.manager.connected_to_es:
            return

        # 1. Index and test search:
        text = 'test'

        topic_1 = TopicFactory(forum=self.forum, author=self.user, title=text)
        post_1 = PostFactory(topic=topic_1, author=self.user, position=1)
        post_1.text = post_1.text_html = text
        post_1.save()

        # create a middle-size content and publish it
        tuto = PublishableContentFactory(type='TUTORIAL')
        tuto_draft = tuto.load_version()

        tuto.title = text
        tuto.authors.add(self.user)
        tuto.save()

        tuto_draft.repo_update_top_container(text, tuto.slug, text, text)  # change title to be sure it will match

        chapter1 = ContainerFactory(parent=tuto_draft, db_object=tuto)
        extract = ExtractFactory(container=chapter1, db_object=tuto)
        extract.repo_update(text, text)

        published = publish_content(tuto, tuto_draft, is_major_update=True)

        tuto.sha_public = tuto_draft.current_version
        tuto.sha_draft = tuto_draft.current_version
        tuto.public_version = published
        tuto.save()

        # nothing has been indexed yet:
        self.assertEqual(len(self.manager.setup_search(Search().query(MatchAll())).execute()), 0)

        # index
        for model in self.indexable:
            if model is FakeChapter:
                continue
            self.manager.es_bulk_indexing_of_model(model)
        self.manager.refresh_index()

        result = self.client.get(reverse('search:query') + '?q=' + text, follow=False)
        self.assertEqual(result.status_code, 200)

        response = result.context['object_list'].execute()

        self.assertEqual(response.hits.total, 4)  # get 4 results

        # 2. Test filtering:
        topic_1 = Topic.objects.get(pk=topic_1.pk)
        post_1 = Post.objects.get(pk=post_1.pk)
        published = PublishedContent.objects.get(pk=published.pk)

        ids = {
            'topic': [topic_1.es_id],
            'post': [post_1.es_id],
            'content': [published.es_id, published.content_public_slug + '__' + chapter1.slug],
        }

        search_groups = [k for k, v in settings.ZDS_APP['search']['search_groups'].items()]
        group_to_model = {k: v[1] for k, v in settings.ZDS_APP['search']['search_groups'].items()}

        for doc_type in search_groups:
            result = self.client.get(reverse('search:query') + '?q=' + text + '&models=' + doc_type, follow=False)
            self.assertEqual(result.status_code, 200)

            response = result.context['object_list'].execute()

            self.assertEqual(response.hits.total, len(ids[doc_type]))  # get 1 result of each …
            for i, r in enumerate(response):
                self.assertIn(r.meta.doc_type, group_to_model[doc_type])  # … and only of the right type …
                self.assertEqual(r.meta.id, ids[doc_type][i])  # … with the right id !

    def test_get_similar_topics(self):
        """Get similar topics lists"""

        if not self.manager.connected_to_es:
            return

        text = 'Clem ne se mange pas'

        topic_1 = TopicFactory(forum=self.forum, author=self.user, title=text)
        post_1 = PostFactory(topic=topic_1, author=self.user, position=1)
        post_1.text = post_1.text_html = text
        post_1.save()

        text = 'Clem est la meilleure mascotte'

        topic_2 = TopicFactory(forum=self.forum, author=self.user, title=text)
        post_2 = PostFactory(topic=topic_2, author=self.user, position=1)
        post_2.text = post_1.text_html = text
        post_2.save()

        # 1. Should not get any result
        result = self.client.get(reverse('search:similar') + '?q=est', follow=False)
        self.assertEqual(result.status_code, 200)
        content = json_handler.loads(result.content.decode('utf-8'))
        self.assertEqual(len(content['results']), 0)

        # index
        for model in self.indexable:
            if model is FakeChapter:
                continue
            self.manager.es_bulk_indexing_of_model(model)
        self.manager.refresh_index()

        # 2. Should get exactly one result
        result = self.client.get(reverse('search:similar') + '?q=mange', follow=False)
        self.assertEqual(result.status_code, 200)
        content = json_handler.loads(result.content.decode('utf-8'))
        self.assertEqual(len(content['results']), 1)

        # 2. Should get exactly two results
        result = self.client.get(reverse('search:similar') + '?q=Clem', follow=False)
        self.assertEqual(result.status_code, 200)
        content = json_handler.loads(result.content.decode('utf-8'))
        self.assertEqual(len(content['results']), 2)

    def test_hidden_post_are_not_result(self):
        """Hidden posts should not show up in the search results"""

        if not self.manager.connected_to_es:
            return

        # 1. Index and test search:
        text = 'test'

        topic_1 = TopicFactory(forum=self.forum, author=self.user, title=text)
        post_1 = PostFactory(topic=topic_1, author=self.user, position=1)
        post_1.text = post_1.text_html = text
        post_1.save()

        self.manager.es_bulk_indexing_of_model(Topic)
        self.manager.es_bulk_indexing_of_model(Post)
        self.manager.refresh_index()

        self.assertEqual(len(self.manager.setup_search(Search().query(MatchAll())).execute()), 2)  # indexing ok

        post_1 = Post.objects.get(pk=post_1.pk)

        result = self.client.get(
            reverse('search:query') + '?q=' + text + '&models=' + Post.get_es_document_type(), follow=False)

        self.assertEqual(result.status_code, 200)

        response = result.context['object_list'].execute()

        self.assertEqual(response.hits.total, 1)
        self.assertEqual(response[0].meta.id, post_1.es_id)

        # 2. Hide, reindex and search again:
        post_1.hide_comment_by_user(self.staff, 'Un abus de pouvoir comme un autre ;)')
        self.manager.refresh_index()

        result = self.client.get(
            reverse('search:query') + '?q=' + text + '&models=' + Post.get_es_document_type(), follow=False)

        self.assertEqual(result.status_code, 200)
        response = result.context['object_list'].execute()
        self.assertEqual(response.hits.total, 0)  # nothing in the results

    def test_hidden_forums_give_no_results_if_user_not_allowed(self):
        """Long name, isn't ?"""

        if not self.manager.connected_to_es:
            return

        # 1. Create a hidden forum belonging to a hidden staff group.
        text = 'test'

        group = Group.objects.create(name='Les illuminatis anonymes de ZdS')
        _, hidden_forum = create_category_and_forum(group)

        self.staff.groups.add(group)
        self.staff.save()

        topic_1 = TopicFactory(forum=hidden_forum, author=self.staff, title=text)
        post_1 = PostFactory(topic=topic_1, author=self.user, position=1)
        post_1.text = post_1.text_html = text
        post_1.save()

        self.manager.es_bulk_indexing_of_model(Topic)
        self.manager.es_bulk_indexing_of_model(Post)
        self.manager.refresh_index()

        self.assertEqual(len(self.manager.setup_search(Search().query(MatchAll())).execute()), 2)  # indexing ok

        # 2. search without connection and get not result
        result = self.client.get(reverse('search:query') + '?q=' + text, follow=False)

        self.assertEqual(result.status_code, 200)
        response = result.context['object_list'].execute()
        self.assertEqual(response.hits.total, 0)

        # 3. Connect with user (not a member of the group), search, and get no result
        self.assertTrue(self.client.login(username=self.user.username, password='******'))

        result = self.client.get(reverse('search:query') + '?q=' + text, follow=False)

        self.assertEqual(result.status_code, 200)
        response = result.context['object_list'].execute()
        self.assertEqual(response.hits.total, 0)

        # 4. Connect with staff, search, and get the topic and the post
        self.client.logout()
        self.assertTrue(self.client.login(username=self.staff.username, password='******'))

        result = self.client.get(reverse('search:query') + '?q=' + text, follow=False)

        self.assertEqual(result.status_code, 200)
        response = result.context['object_list'].execute()
        self.assertEqual(response.hits.total, 2)  # ok !

    def test_boosts(self):
        """Check if boosts are doing their job"""

        if not self.manager.connected_to_es:
            return

        # 1. Create topics (with identical titles), posts (with identical texts), an article and a tuto
        text = 'test'

        topic_1_solved_sticky = TopicFactory(forum=self.forum, author=self.user)
        topic_1_solved_sticky.title = text
        topic_1_solved_sticky.subtitle = ''
        topic_1_solved_sticky.solved_by = self.user
        topic_1_solved_sticky.is_sticky = True
        topic_1_solved_sticky.save()

        post_1 = PostFactory(topic=topic_1_solved_sticky, author=self.user, position=1)
        post_1.text = post_1.text_html = text
        post_1.save()

        post_2_useful = PostFactory(topic=topic_1_solved_sticky, author=self.user, position=2)
        post_2_useful.text = post_2_useful.text_html = text
        post_2_useful.is_useful = True
        post_2_useful.like = 5
        post_2_useful.dislike = 2  # l/d ratio above 1
        post_2_useful.save()

        topic_2_locked = TopicFactory(forum=self.forum, author=self.user, title=text)
        topic_2_locked.title = text
        topic_2_locked.subtitle = ''
        topic_2_locked.is_locked = True
        topic_2_locked.save()

        post_3_ld_below_1 = PostFactory(topic=topic_2_locked, author=self.user, position=1)
        post_3_ld_below_1.text = post_3_ld_below_1.text_html = text
        post_3_ld_below_1.like = 2
        post_3_ld_below_1.dislike = 5  # l/d ratio below 1
        post_3_ld_below_1.save()

        tuto = PublishableContentFactory(type='TUTORIAL')
        tuto_draft = tuto.load_version()

        tuto.title = text
        tuto.authors.add(self.user)
        tuto.save()

        tuto_draft.repo_update_top_container(text, tuto.slug, text, text)

        chapter1 = ContainerFactory(parent=tuto_draft, db_object=tuto)
        chapter1.repo_update(text, 'Who cares ?', 'Same here')
        ExtractFactory(container=chapter1, db_object=tuto)

        published_tuto = publish_content(tuto, tuto_draft, is_major_update=True)

        tuto.sha_public = tuto_draft.current_version
        tuto.sha_draft = tuto_draft.current_version
        tuto.public_version = published_tuto
        tuto.save()

        article = PublishedContentFactory(type='ARTICLE', title=text)
        published_article = PublishedContent.objects.get(content_pk=article.pk)

        opinion_not_picked = PublishedContentFactory(type='OPINION', title=text)
        published_opinion_not_picked = PublishedContent.objects.get(content_pk=opinion_not_picked.pk)

        opinion_picked = PublishedContentFactory(type='OPINION', title=text)
        opinion_picked.sha_picked = opinion_picked.sha_draft
        opinion_picked.date_picked = datetime.datetime.now()
        opinion_picked.save()

        published_opinion_picked = PublishedContent.objects.get(content_pk=opinion_picked.pk)

        for model in self.indexable:
            if model is FakeChapter:
                continue
            self.manager.es_bulk_indexing_of_model(model)
        self.manager.refresh_index()

        self.assertEqual(len(self.manager.setup_search(Search().query(MatchAll())).execute()), 10)

        # 2. Reset all boosts to 1
        for doc_type in settings.ZDS_APP['search']['boosts']:
            for key in settings.ZDS_APP['search']['boosts'][doc_type]:
                settings.ZDS_APP['search']['boosts'][doc_type][key] = 1.0

        # 3. Test posts
        result = self.client.get(
            reverse('search:query') + '?q=' + text + '&models=' + Post.get_es_document_type(), follow=False)

        self.assertEqual(result.status_code, 200)
        response = result.context['object_list'].execute()
        self.assertEqual(response.hits.total, 3)

        # score are equals without boost:
        self.assertTrue(response[0].meta.score == response[1].meta.score == response[2].meta.score)

        settings.ZDS_APP['search']['boosts']['post']['if_first'] = 2.0

        result = self.client.get(
            reverse('search:query') + '?q=' + text + '&models=' + Post.get_es_document_type(), follow=False)

        self.assertEqual(result.status_code, 200)
        response = result.context['object_list'].execute()
        self.assertEqual(response.hits.total, 3)

        self.assertTrue(response[0].meta.score == response[1].meta.score > response[2].meta.score)
        self.assertEqual(response[2].meta.id, str(post_2_useful.pk))  # post 2 is the only one not first

        settings.ZDS_APP['search']['boosts']['post']['if_first'] = 1.0
        settings.ZDS_APP['search']['boosts']['post']['if_useful'] = 2.0

        result = self.client.get(
            reverse('search:query') + '?q=' + text + '&models=' + Post.get_es_document_type(), follow=False)

        self.assertEqual(result.status_code, 200)
        response = result.context['object_list'].execute()
        self.assertEqual(response.hits.total, 3)

        self.assertTrue(response[0].meta.score > response[1].meta.score == response[2].meta.score)
        self.assertEqual(response[0].meta.id, str(post_2_useful.pk))  # post 2 is useful

        settings.ZDS_APP['search']['boosts']['post']['if_useful'] = 1.0
        settings.ZDS_APP['search']['boosts']['post']['ld_ratio_above_1'] = 2.0

        result = self.client.get(
            reverse('search:query') + '?q=' + text + '&models=' + Post.get_es_document_type(), follow=False)

        self.assertEqual(result.status_code, 200)
        response = result.context['object_list'].execute()
        self.assertEqual(response.hits.total, 3)

        self.assertTrue(response[0].meta.score > response[1].meta.score == response[2].meta.score)
        self.assertEqual(response[0].meta.id, str(post_2_useful.pk))  # post 2 have a l/d ratio of 5/2

        settings.ZDS_APP['search']['boosts']['post']['ld_ratio_above_1'] = 1.0
        settings.ZDS_APP['search']['boosts']['post']['ld_ratio_below_1'] = 2.0  # no one would do that in real life

        result = self.client.get(
            reverse('search:query') + '?q=' + text + '&models=' + Post.get_es_document_type(), follow=False)

        self.assertEqual(result.status_code, 200)
        response = result.context['object_list'].execute()
        self.assertEqual(response.hits.total, 3)

        self.assertTrue(response[0].meta.score > response[1].meta.score == response[2].meta.score)
        self.assertEqual(response[0].meta.id, str(post_3_ld_below_1.pk))  # post 3 have a l/d ratio of 2/5

        settings.ZDS_APP['search']['boosts']['post']['ld_ratio_below_1'] = 1.0

        # 4. Test topics
        result = self.client.get(
            reverse('search:query') + '?q=' + text + '&models=' + Topic.get_es_document_type(), follow=False)

        self.assertEqual(result.status_code, 200)
        response = result.context['object_list'].execute()
        self.assertEqual(response.hits.total, 2)

        # score are equals without boost:
        self.assertTrue(response[0].meta.score == response[1].meta.score)

        settings.ZDS_APP['search']['boosts']['topic']['if_sticky'] = 2.0

        result = self.client.get(
            reverse('search:query') + '?q=' + text + '&models=' + Topic.get_es_document_type(), follow=False)

        self.assertEqual(result.status_code, 200)
        response = result.context['object_list'].execute()
        self.assertEqual(response.hits.total, 2)

        self.assertTrue(response[0].meta.score > response[1].meta.score)
        self.assertEqual(response[0].meta.id, str(topic_1_solved_sticky.pk))  # topic 1 is sticky

        settings.ZDS_APP['search']['boosts']['topic']['if_sticky'] = 1.0
        settings.ZDS_APP['search']['boosts']['topic']['if_solved'] = 2.0

        result = self.client.get(
            reverse('search:query') + '?q=' + text + '&models=' + Topic.get_es_document_type(), follow=False)

        self.assertEqual(result.status_code, 200)
        response = result.context['object_list'].execute()
        self.assertEqual(response.hits.total, 2)

        self.assertTrue(response[0].meta.score > response[1].meta.score)
        self.assertEqual(response[0].meta.id, str(topic_1_solved_sticky.pk))  # topic 1 is solved

        settings.ZDS_APP['search']['boosts']['topic']['if_solved'] = 1.0
        settings.ZDS_APP['search']['boosts']['topic']['if_locked'] = 2.0  # no one would do that in real life

        result = self.client.get(
            reverse('search:query') + '?q=' + text + '&models=' + Topic.get_es_document_type(), follow=False)

        self.assertEqual(result.status_code, 200)
        response = result.context['object_list'].execute()
        self.assertEqual(response.hits.total, 2)

        self.assertTrue(response[0].meta.score > response[1].meta.score)
        self.assertEqual(response[0].meta.id, str(topic_2_locked.pk))  # topic 2 is locked

        settings.ZDS_APP['search']['boosts']['topic']['if_locked'] = 1.0  # no one would do that in real life

        # 5. Test published contents
        result = self.client.get(
            reverse('search:query') + '?q=' + text + '&models=content', follow=False)

        self.assertEqual(result.status_code, 200)
        response = result.context['object_list'].execute()
        self.assertEqual(response.hits.total, 5)

        # score are equals without boost:
        self.assertTrue(response[0].meta.score ==
                        response[1].meta.score ==
                        response[2].meta.score ==
                        response[3].meta.score ==
                        response[4].meta.score)

        settings.ZDS_APP['search']['boosts']['publishedcontent']['if_article'] = 2.0

        result = self.client.get(
            reverse('search:query') + '?q=' + text + '&models=content', follow=False)

        self.assertEqual(result.status_code, 200)
        response = result.context['object_list'].execute()
        self.assertEqual(response.hits.total, 5)

        self.assertTrue(response[0].meta.score > response[1].meta.score)
        self.assertEqual(response[0].meta.id, str(published_article.pk))  # obvious

        settings.ZDS_APP['search']['boosts']['publishedcontent']['if_article'] = 1.0
        settings.ZDS_APP['search']['boosts']['publishedcontent']['if_tutorial'] = 2.0

        result = self.client.get(
            reverse('search:query') + '?q=' + text + '&models=content', follow=False)

        self.assertEqual(result.status_code, 200)
        response = result.context['object_list'].execute()
        self.assertEqual(response.hits.total, 5)

        self.assertTrue(response[0].meta.score > response[1].meta.score)
        self.assertEqual(response[0].meta.id, str(published_tuto.pk))  # obvious

        settings.ZDS_APP['search']['boosts']['publishedcontent']['if_tutorial'] = 1.0
        settings.ZDS_APP['search']['boosts']['publishedcontent']['if_opinion'] = 2.0
        settings.ZDS_APP['search']['boosts']['publishedcontent']['if_opinion_not_picked'] = 4.0
        # Note: in "real life", unpicked opinion would get a boost < 1.

        result = self.client.get(
            reverse('search:query') + '?q=' + text + '&models=content', follow=False)

        self.assertEqual(result.status_code, 200)
        response = result.context['object_list'].execute()
        self.assertEqual(response.hits.total, 5)

        self.assertTrue(response[0].meta.score > response[1].meta.score > response[2].meta.score)
        self.assertEqual(response[0].meta.id, str(published_opinion_not_picked.pk))  # unpicked opinion got first
        self.assertEqual(response[1].meta.id, str(published_opinion_picked.pk))

        settings.ZDS_APP['search']['boosts']['publishedcontent']['if_opinion'] = 1.0
        settings.ZDS_APP['search']['boosts']['publishedcontent']['if_opinion_not_picked'] = 1.0
        settings.ZDS_APP['search']['boosts']['publishedcontent']['if_medium_or_big_tutorial'] = 2.0

        result = self.client.get(
            reverse('search:query') + '?q=' + text + '&models=content', follow=False)

        self.assertEqual(result.status_code, 200)
        response = result.context['object_list'].execute()
        self.assertEqual(response.hits.total, 5)

        self.assertTrue(response[0].meta.score > response[1].meta.score)
        self.assertEqual(response[0].meta.id, str(published_tuto.pk))  # obvious

        settings.ZDS_APP['search']['boosts']['publishedcontent']['if_medium_or_big_tutorial'] = 1.0

        # 6. Test global boosts
        # NOTE: score are NOT the same for all documents, no matter how hard it tries to, small differences exists

        for model in self.indexable:

            # set a huge number to overcome the small differences:
            settings.ZDS_APP['search']['boosts'][model.get_es_document_type()]['global'] = 10.0

            result = self.client.get(
                reverse('search:query') + '?q=' + text, follow=False)

            self.assertEqual(result.status_code, 200)
            response = result.context['object_list'].execute()
            self.assertEqual(response.hits.total, 10)

            self.assertEqual(response[0].meta.doc_type, model.get_es_document_type())  # obvious

            settings.ZDS_APP['search']['boosts'][model.get_es_document_type()]['global'] = 1.0

    def test_change_topic_impacts_posts(self):

        if not self.manager.connected_to_es:
            return

        # 1. Create a hidden forum belonging to a hidden group and add staff in it.
        text = 'test'

        group = Group.objects.create(name='Les illuminatis anonymes de ZdS')
        _, hidden_forum = create_category_and_forum(group)

        self.staff.groups.add(group)
        self.staff.save()

        # 2. Create a normal topic and index it
        topic_1 = TopicFactory(forum=self.forum, author=self.user, title=text)
        post_1 = PostFactory(topic=topic_1, author=self.user, position=1)
        post_1.text = post_1.text_html = text
        post_1.save()

        self.manager.es_bulk_indexing_of_model(Topic)
        self.manager.es_bulk_indexing_of_model(Post)
        self.manager.refresh_index()

        self.assertEqual(len(self.manager.setup_search(Search().query(MatchAll())).execute()), 2)  # indexing ok

        result = self.client.get(
            reverse('search:query') + '?q=' + text + '&models=' + Post.get_es_document_type(), follow=False)

        self.assertEqual(result.status_code, 200)
        response = result.context['object_list'].execute()
        self.assertEqual(response.hits.total, 1)  # ok
        self.assertEqual(response[0].meta.doc_type, Post.get_es_document_type())
        self.assertEqual(response[0].forum_pk, self.forum.pk)
        self.assertEqual(response[0].topic_pk, topic_1.pk)
        self.assertEqual(response[0].topic_title, topic_1.title)

        # 3. Change topic title and reindex
        topic_1.title = 'new title'
        topic_1.save()

        self.manager.es_bulk_indexing_of_model(Topic)
        self.manager.es_bulk_indexing_of_model(Post)
        self.manager.refresh_index()

        result = self.client.get(
            reverse('search:query') + '?q=' + text + '&models=' + Post.get_es_document_type(), follow=False)

        self.assertEqual(result.status_code, 200)
        response = result.context['object_list'].execute()
        self.assertEqual(response.hits.total, 1)  # ok

        self.assertEqual(response[0].topic_title, topic_1.title)  # title was changed

        # 4. connect with staff and move topic
        self.assertTrue(self.client.login(username=self.staff.username, password='******'))

        data = {
            'move': '',
            'forum': hidden_forum.pk,
            'topic': topic_1.pk
        }
        response = self.client.post(reverse('topic-edit'), data, follow=False)

        self.assertEqual(302, response.status_code)

        self.manager.es_bulk_indexing_of_model(Topic)
        self.manager.es_bulk_indexing_of_model(Post)
        self.manager.refresh_index()

        result = self.client.get(
            reverse('search:query') + '?q=' + text + '&models=' + Post.get_es_document_type(), follow=False)

        self.assertEqual(result.status_code, 200)
        response = result.context['object_list'].execute()
        self.assertEqual(response.hits.total, 1)  # Note: without staff, would not get any results (see below)

        self.assertEqual(response[0].forum_pk, hidden_forum.pk)  # post was updated with new forum

        # 5. Topic is now hidden
        self.client.logout()

        result = self.client.get(
            reverse('search:query') + '?q=' + text + '&models=' + Post.get_es_document_type(), follow=False)

        self.assertEqual(result.status_code, 200)
        response = result.context['object_list'].execute()
        self.assertEqual(response.hits.total, 0)  # ok

    def test_change_publishedcontents_impacts_chapter(self):

        if not self.manager.connected_to_es:
            return

        # 1. Create middle-size content and index it
        text = 'test'

        tuto = PublishableContentFactory(type='TUTORIAL')
        tuto_draft = tuto.load_version()

        tuto.title = text
        tuto.authors.add(self.user)
        tuto.save()

        tuto_draft.repo_update_top_container(text, tuto.slug, text, text)  # change title to be sure it will match

        chapter1 = ContainerFactory(parent=tuto_draft, db_object=tuto)
        chapter1.repo_update(text, text, text)
        extract = ExtractFactory(container=chapter1, db_object=tuto)
        extract.repo_update(text, text)

        published = publish_content(tuto, tuto_draft, is_major_update=True)

        tuto.sha_public = tuto_draft.current_version
        tuto.sha_draft = tuto_draft.current_version
        tuto.public_version = published
        tuto.save()

        self.manager.es_bulk_indexing_of_model(PublishedContent)
        self.manager.refresh_index()

        self.assertEqual(len(self.manager.setup_search(Search().query(MatchAll())).execute()), 2)  # indexing ok

        result = self.client.get(
            reverse('search:query') + '?q=' + text + '&models=content', follow=False)
        self.assertEqual(result.status_code, 200)

        response = result.context['object_list'].execute()

        self.assertEqual(response.hits.total, 2)

        chapters = [r for r in response if r.meta.doc_type == 'chapter']
        self.assertEqual(chapters[0].meta.doc_type, FakeChapter.get_es_document_type())
        self.assertEqual(chapters[0].meta.id, published.content_public_slug + '__' + chapter1.slug)

        # 2. Change tuto: delete chapter and insert new one !
        tuto = PublishableContent.objects.get(pk=tuto.pk)
        tuto_draft = tuto.load_version()

        tuto_draft.children[0].repo_delete()  # chapter 1 is gone !

        another_text = 'another thing'
        self.assertTrue(text not in another_text)  # to prevent a future modification from breaking this test

        chapter2 = ContainerFactory(parent=tuto_draft, db_object=tuto)
        chapter2.repo_update(another_text, another_text, another_text)
        extract2 = ExtractFactory(container=chapter2, db_object=tuto)
        extract2.repo_update(another_text, another_text)

        published = publish_content(tuto, tuto_draft, is_major_update=False)

        tuto.sha_public = tuto_draft.current_version
        tuto.sha_draft = tuto_draft.current_version
        tuto.public_version = published
        tuto.save()

        self.manager.es_bulk_indexing_of_model(PublishedContent)
        self.manager.refresh_index()

        self.assertEqual(len(self.manager.setup_search(Search().query(MatchAll())).execute()), 2)  # 2 objects, not 3 !

        result = self.client.get(
            reverse('search:query') + '?q=' + text + '&models=content', follow=False)
        self.assertEqual(result.status_code, 200)

        response = result.context['object_list'].execute()

        contents = [r for r in response if r.meta.doc_type != 'chapter']
        self.assertEqual(response.hits.total, len(contents))  # no chapter found anymore

        result = self.client.get(
            reverse('search:query') + '?q=' + another_text + '&models=content',
            follow=False
        )

        self.assertEqual(result.status_code, 200)

        response = result.context['object_list'].execute()
        chapters = [r for r in response if r.meta.doc_type == 'chapter']
        self.assertEqual(response.hits.total, 1)
        self.assertEqual(chapters[0].meta.doc_type, FakeChapter.get_es_document_type())
        self.assertEqual(chapters[0].meta.id, published.content_public_slug + '__' + chapter2.slug)  # got new chapter

    def test_opensearch(self):

        result = self.client.get(
            reverse('search:opensearch'),
            follow=False
        )

        self.assertEqual(result.status_code, 200)

        self.assertContains(result, reverse('search:query'))
        self.assertContains(result, reverse('search:opensearch'))

    def test_upercase_and_lowercase_search_give_same_results(self):
        """Pretty self-explanatory function name, isn't it ?"""

        if not self.manager.connected_to_es:
            return

        # 1. Index lowercase stuffs
        text_lc = 'test'

        topic_1_lc = TopicFactory(forum=self.forum, author=self.user, title=text_lc)

        tag_lc = TagFactory(title=text_lc)
        topic_1_lc.tags.add(tag_lc)
        topic_1_lc.subtitle = text_lc
        topic_1_lc.save()

        post_1_lc = PostFactory(topic=topic_1_lc, author=self.user, position=1)
        post_1_lc.text = post_1_lc.text_html = text_lc
        post_1_lc.save()

        tuto_lc = PublishableContentFactory(type='TUTORIAL')
        tuto_draft_lc = tuto_lc.load_version()

        tuto_lc.title = text_lc
        tuto_lc.authors.add(self.user)
        subcategory_lc = SubCategoryFactory(title=text_lc)
        tuto_lc.subcategory.add(subcategory_lc)
        tuto_lc.tags.add(tag_lc)
        tuto_lc.save()

        tuto_draft_lc.description = text_lc
        tuto_draft_lc.repo_update_top_container(text_lc, tuto_lc.slug, text_lc, text_lc)

        chapter1_lc = ContainerFactory(parent=tuto_draft_lc, db_object=tuto_lc)
        extract_lc = ExtractFactory(container=chapter1_lc, db_object=tuto_lc)
        extract_lc.repo_update(text_lc, text_lc)

        published_lc = publish_content(tuto_lc, tuto_draft_lc, is_major_update=True)

        tuto_lc.sha_public = tuto_draft_lc.current_version
        tuto_lc.sha_draft = tuto_draft_lc.current_version
        tuto_lc.public_version = published_lc
        tuto_lc.save()

        # 2. Index uppercase stuffs
        text_uc = 'TEST'

        topic_1_uc = TopicFactory(forum=self.forum, author=self.user, title=text_uc)

        topic_1_uc.tags.add(tag_lc)  # Note: a constraint forces tags title to be unique
        topic_1_uc.subtitle = text_uc
        topic_1_uc.save()

        post_1_uc = PostFactory(topic=topic_1_uc, author=self.user, position=1)
        post_1_uc.text = post_1_uc.text_html = text_uc
        post_1_uc.save()

        tuto_uc = PublishableContentFactory(type='TUTORIAL')
        tuto_draft_uc = tuto_uc.load_version()

        tuto_uc.title = text_uc
        tuto_uc.authors.add(self.user)
        tuto_uc.subcategory.add(subcategory_lc)
        tuto_uc.tags.add(tag_lc)
        tuto_uc.save()

        tuto_draft_uc.description = text_uc
        tuto_draft_uc.repo_update_top_container(text_uc, tuto_uc.slug, text_uc, text_uc)

        chapter1_uc = ContainerFactory(parent=tuto_draft_uc, db_object=tuto_uc)
        extract_uc = ExtractFactory(container=chapter1_uc, db_object=tuto_uc)
        extract_uc.repo_update(text_uc, text_uc)

        published_uc = publish_content(tuto_uc, tuto_draft_uc, is_major_update=True)

        tuto_uc.sha_public = tuto_draft_uc.current_version
        tuto_uc.sha_draft = tuto_draft_uc.current_version
        tuto_uc.public_version = published_uc
        tuto_uc.save()

        # 3. Index and search:
        self.assertEqual(len(self.manager.setup_search(Search().query(MatchAll())).execute()), 0)

        # index
        for model in self.indexable:
            if model is FakeChapter:
                continue
            self.manager.es_bulk_indexing_of_model(model)
        self.manager.refresh_index()

        result = self.client.get(reverse('search:query') + '?q=' + text_lc, follow=False)
        self.assertEqual(result.status_code, 200)

        response_lc = result.context['object_list'].execute()
        self.assertEqual(response_lc.hits.total, 8)

        result = self.client.get(reverse('search:query') + '?q=' + text_uc, follow=False)
        self.assertEqual(result.status_code, 200)

        response_uc = result.context['object_list'].execute()
        self.assertEqual(response_uc.hits.total, 8)

        for responses in zip(response_lc, response_uc):  # we should get results in the same order!
            self.assertEqual(responses[0].meta.id, responses[1].meta.id)

    def test_category_and_subcategory_impact_search(self):
        """If two contents do not belong to the same (sub)category"""

        if not self.manager.connected_to_es:
            return

        text = 'Did you ever hear the tragedy of Darth Plagueis The Wise?'

        # 1. Create two contents with different subcategories
        category_1 = 'category 1'
        subcategory_1 = SubCategoryFactory(title=category_1)
        category_2 = 'category 2'
        subcategory_2 = SubCategoryFactory(title=category_2)

        tuto_1 = PublishableContentFactory(type='TUTORIAL')
        tuto_1_draft = tuto_1.load_version()

        tuto_1.title = text
        tuto_1.authors.add(self.user)
        tuto_1.subcategory.add(subcategory_1)
        tuto_1.save()

        tuto_1_draft.description = text
        tuto_1_draft.repo_update_top_container(text, tuto_1.slug, text, text)

        chapter_1 = ContainerFactory(parent=tuto_1_draft, db_object=tuto_1)
        extract_1 = ExtractFactory(container=chapter_1, db_object=tuto_1)
        extract_1.repo_update(text, text)

        published_1 = publish_content(tuto_1, tuto_1_draft, is_major_update=True)

        tuto_1.sha_public = tuto_1_draft.current_version
        tuto_1.sha_draft = tuto_1_draft.current_version
        tuto_1.public_version = published_1
        tuto_1.save()

        tuto_2 = PublishableContentFactory(type='TUTORIAL')
        tuto_2_draft = tuto_2.load_version()

        tuto_2.title = text
        tuto_2.authors.add(self.user)
        tuto_2.subcategory.add(subcategory_2)
        tuto_2.save()

        tuto_2_draft.description = text
        tuto_2_draft.repo_update_top_container(text, tuto_2.slug, text, text)

        chapter_2 = ContainerFactory(parent=tuto_2_draft, db_object=tuto_2)
        extract_2 = ExtractFactory(container=chapter_2, db_object=tuto_2)
        extract_2.repo_update(text, text)

        published_2 = publish_content(tuto_2, tuto_2_draft, is_major_update=True)

        tuto_2.sha_public = tuto_2_draft.current_version
        tuto_2.sha_draft = tuto_2_draft.current_version
        tuto_2.public_version = published_2
        tuto_2.save()

        # 2. Index:
        self.assertEqual(len(self.manager.setup_search(Search().query(MatchAll())).execute()), 0)

        # index
        for model in self.indexable:
            if model is FakeChapter:
                continue
            self.manager.es_bulk_indexing_of_model(model)
        self.manager.refresh_index()

        result = self.client.get(reverse('search:query') + '?q=' + text, follow=False)
        self.assertEqual(result.status_code, 200)

        response = result.context['object_list'].execute()
        self.assertEqual(response.hits.total, 4)  # Ok

        # 3. Test
        result = self.client.get(
            reverse('search:query') + '?q=' + text + '&model=content&subcategory=' + subcategory_1.slug, follow=False)

        self.assertEqual(result.status_code, 200)

        response = result.context['object_list'].execute()
        self.assertEqual(response.hits.total, 2)

        self.assertEqual([int(r.meta.id) for r in response if r.meta.doc_type == 'publishedcontent'][0], published_1.pk)
        self.assertEqual(
            [r.meta.id for r in response if r.meta.doc_type == 'chapter'][0],
            tuto_1.slug + '__' + chapter_1.slug)

        result = self.client.get(
            reverse('search:query') + '?q=' + text + '&model=content&subcategory=' + subcategory_2.slug, follow=False)

        self.assertEqual(result.status_code, 200)

        response = result.context['object_list'].execute()
        self.assertEqual(response.hits.total, 2)

        self.assertEqual([int(r.meta.id) for r in response if r.meta.doc_type == 'publishedcontent'][0], published_2.pk)
        self.assertEqual(
            [r.meta.id for r in response if r.meta.doc_type == 'chapter'][0],
            tuto_2.slug + '__' + chapter_2.slug)

    def tearDown(self):
        super().tearDown()

        # delete index:
        self.manager.clear_es_index()
Exemple #36
0
class MemberModelsTest(TutorialTestMixin, TestCase):

    def setUp(self):
        self.user1 = ProfileFactory()
        self.staff = StaffProfileFactory()

        # Create a forum for later test
        self.forumcat = CategoryFactory()
        self.forum = ForumFactory(category=self.forumcat)
        self.forumtopic = TopicFactory(forum=self.forum, author=self.staff.user)

    def test_get_absolute_url_for_details_of_member(self):
        self.assertEqual(self.user1.get_absolute_url(), '/membres/voir/{0}/'.format(self.user1.user.username))

    def test_get_avatar_url(self):
        # if no url was specified -> gravatar !
        self.assertEqual(self.user1.get_avatar_url(),
                         'https://secure.gravatar.com/avatar/{0}?d=identicon'.
                         format(md5(self.user1.user.email.lower().encode()).hexdigest()))
        # if an url is specified -> take it !
        user2 = ProfileFactory()
        testurl = 'http://test.com/avatar.jpg'
        user2.avatar_url = testurl
        self.assertEqual(user2.get_avatar_url(), testurl)

        # if url is relative, send absolute url
        gallerie_avtar = GalleryFactory()
        image_avatar = ImageFactory(gallery=gallerie_avtar)
        user2.avatar_url = image_avatar.physical.url
        self.assertNotEqual(user2.get_avatar_url(), image_avatar.physical.url)
        self.assertIn('http', user2.get_avatar_url())

    def test_get_post_count(self):
        # Start with 0
        self.assertEqual(self.user1.get_post_count(), 0)
        # Post !
        PostFactory(topic=self.forumtopic, author=self.user1.user, position=1)
        # Should be 1
        self.assertEqual(self.user1.get_post_count(), 1)

    def test_get_topic_count(self):
        # Start with 0
        self.assertEqual(self.user1.get_topic_count(), 0)
        # Create Topic !
        TopicFactory(forum=self.forum, author=self.user1.user)
        # Should be 1
        self.assertEqual(self.user1.get_topic_count(), 1)

    def test_get_tuto_count(self):
        # Start with 0
        self.assertEqual(self.user1.get_tuto_count(), 0)
        # Create Tuto !
        minituto = PublishableContentFactory(type='TUTORIAL')
        minituto.authors.add(self.user1.user)
        minituto.gallery = GalleryFactory()
        minituto.save()
        # Should be 1
        self.assertEqual(self.user1.get_tuto_count(), 1)

    def test_get_tutos(self):
        # Start with 0
        self.assertEqual(len(self.user1.get_tutos()), 0)
        # Create Tuto !
        minituto = PublishableContentFactory(type='TUTORIAL')
        minituto.authors.add(self.user1.user)
        minituto.gallery = GalleryFactory()
        minituto.save()
        # Should be 1
        tutos = self.user1.get_tutos()
        self.assertEqual(len(tutos), 1)
        self.assertEqual(minituto, tutos[0])

    def test_get_draft_tutos(self):
        # Start with 0
        self.assertEqual(len(self.user1.get_draft_tutos()), 0)
        # Create Tuto !
        drafttuto = PublishableContentFactory(type='TUTORIAL')
        drafttuto.authors.add(self.user1.user)
        drafttuto.gallery = GalleryFactory()
        drafttuto.save()
        # Should be 1
        drafttutos = self.user1.get_draft_tutos()
        self.assertEqual(len(drafttutos), 1)
        self.assertEqual(drafttuto, drafttutos[0])

    def test_get_public_tutos(self):
        # Start with 0
        self.assertEqual(len(self.user1.get_public_tutos()), 0)
        # Create Tuto !
        publictuto = PublishableContentFactory(type='TUTORIAL')
        publictuto.authors.add(self.user1.user)
        publictuto.gallery = GalleryFactory()
        publictuto.sha_public = 'whatever'
        publictuto.save()
        # Should be 0 because publication was not used
        publictutos = self.user1.get_public_tutos()
        self.assertEqual(len(publictutos), 0)
        PublishedContentFactory(author_list=[self.user1.user])
        self.assertEqual(len(self.user1.get_public_tutos()), 1)

    def test_get_validate_tutos(self):
        # Start with 0
        self.assertEqual(len(self.user1.get_validate_tutos()), 0)
        # Create Tuto !
        validatetuto = PublishableContentFactory(type='TUTORIAL', author_list=[self.user1.user])
        validatetuto.sha_validation = 'whatever'
        validatetuto.save()
        # Should be 1
        validatetutos = self.user1.get_validate_tutos()
        self.assertEqual(len(validatetutos), 1)
        self.assertEqual(validatetuto, validatetutos[0])

    def test_get_beta_tutos(self):
        # Start with 0
        self.assertEqual(len(self.user1.get_beta_tutos()), 0)
        # Create Tuto !
        betatetuto = PublishableContentFactory(type='TUTORIAL')
        betatetuto.authors.add(self.user1.user)
        betatetuto.gallery = GalleryFactory()
        betatetuto.sha_beta = 'whatever'
        betatetuto.save()
        # Should be 1
        betatetutos = self.user1.get_beta_tutos()
        self.assertEqual(len(betatetutos), 1)
        self.assertEqual(betatetuto, betatetutos[0])

    def test_get_article_count(self):
        # Start with 0
        self.assertEqual(self.user1.get_tuto_count(), 0)
        # Create article !
        minituto = PublishableContentFactory(type='ARTICLE')
        minituto.authors.add(self.user1.user)
        minituto.gallery = GalleryFactory()
        minituto.save()
        # Should be 1
        self.assertEqual(self.user1.get_article_count(), 1)

    def test_get_articles(self):
        # Start with 0
        self.assertEqual(len(self.user1.get_articles()), 0)
        # Create article !
        article = PublishableContentFactory(type='ARTICLE')
        article.authors.add(self.user1.user)
        article.save()
        # Should be 1
        articles = self.user1.get_articles()
        self.assertEqual(len(articles), 1)
        self.assertEqual(article, articles[0])

    def test_get_public_articles(self):
        # Start with 0
        self.assertEqual(len(self.user1.get_public_articles()), 0)
        # Create article !
        article = PublishableContentFactory(type='ARTICLE')
        article.authors.add(self.user1.user)
        article.sha_public = 'whatever'
        article.save()
        # Should be 0
        articles = self.user1.get_public_articles()
        self.assertEqual(len(articles), 0)
        # Should be 1
        PublishedContentFactory(author_list=[self.user1.user], type='ARTICLE')
        self.assertEqual(len(self.user1.get_public_articles()), 1)
        self.assertEqual(len(self.user1.get_public_tutos()), 0)

    def test_get_validate_articles(self):
        # Start with 0
        self.assertEqual(len(self.user1.get_validate_articles()), 0)
        # Create article !
        article = PublishableContentFactory(type='ARTICLE')
        article.authors.add(self.user1.user)
        article.sha_validation = 'whatever'
        article.save()
        # Should be 1
        articles = self.user1.get_validate_articles()
        self.assertEqual(len(articles), 1)
        self.assertEqual(article, articles[0])

    def test_get_draft_articles(self):
        # Start with 0
        self.assertEqual(len(self.user1.get_draft_articles()), 0)
        # Create article !
        article = PublishableContentFactory(type='ARTICLE')
        article.authors.add(self.user1.user)
        article.save()
        # Should be 1
        articles = self.user1.get_draft_articles()
        self.assertEqual(len(articles), 1)
        self.assertEqual(article, articles[0])

    def test_get_beta_articles(self):
        # Start with 0
        self.assertEqual(len(self.user1.get_beta_articles()), 0)
        # Create article !
        article = PublishableContentFactory(type='ARTICLE')
        article.authors.add(self.user1.user)
        article.sha_beta = 'whatever'
        article.save()
        # Should be 1
        articles = self.user1.get_beta_articles()
        self.assertEqual(len(articles), 1)
        self.assertEqual(article, articles[0])

    def test_get_posts(self):
        # Start with 0
        self.assertEqual(len(self.user1.get_posts()), 0)
        # Post !
        apost = PostFactory(topic=self.forumtopic, author=self.user1.user, position=1)
        # Should be 1
        posts = self.user1.get_posts()
        self.assertEqual(len(posts), 1)
        self.assertEqual(apost, posts[0])

    def test_get_hidden_by_staff_posts_count(self):
        # Start with 0
        self.assertEqual(self.user1.get_hidden_by_staff_posts_count(), 0)
        # Post and hide it by poster
        PostFactory(topic=self.forumtopic, author=self.user1.user, position=1, is_visible=False, editor=self.user1.user)
        # Should be 0
        self.assertEqual(self.user1.get_hidden_by_staff_posts_count(), 0)
        # Post and hide it by staff
        PostFactory(topic=self.forumtopic, author=self.user1.user, position=1, is_visible=False, editor=self.staff.user)
        # Should be 1
        self.assertEqual(self.user1.get_hidden_by_staff_posts_count(), 1)

    def test_get_hidden_by_staff_posts_count_staff_poster(self):
        # Start with 0
        self.assertEqual(self.staff.get_hidden_by_staff_posts_count(), 0)
        # Post and hide it by poster which is staff
        PostFactory(topic=self.forumtopic, author=self.staff.user, position=1, is_visible=False, editor=self.staff.user)
        # Should be 0 because even if poster is staff, he is the poster
        self.assertEqual(self.staff.get_hidden_by_staff_posts_count(), 0)

    def test_get_active_alerts_count(self):
        # Start with 0
        self.assertEqual(self.user1.get_active_alerts_count(), 0)
        # Post and Alert it !
        post = PostFactory(topic=self.forumtopic, author=self.user1.user, position=1)
        Alert.objects.create(author=self.user1.user, comment=post, scope='FORUM', pubdate=datetime.now())
        # Should be 1
        self.assertEqual(self.user1.get_active_alerts_count(), 1)

    def test_can_read_now(self):

        profile = ProfileFactory()
        profile.is_active = True
        profile.can_read = True
        self.assertTrue(profile.can_read_now())

        # Was banned in the past, ban no longer active
        profile = ProfileFactory()
        profile.end_ban_read = datetime.now() - timedelta(days=1)
        self.assertTrue(profile.can_read_now())

        profile = ProfileFactory()
        profile.is_active = True
        profile.can_read = False
        self.assertFalse(profile.can_read_now())

        # Ban is active
        profile = ProfileFactory()
        profile.is_active = True
        profile.can_read = False
        profile.end_ban_read = datetime.now() + timedelta(days=1)
        self.assertFalse(profile.can_read_now())

        self.user1.user.is_active = False
        self.assertFalse(self.user1.can_read_now())

    def test_can_write_now(self):

        self.user1.user.is_active = True
        self.user1.user.can_write = True
        self.assertTrue(self.user1.can_write_now())

        # Was banned in the past, ban no longer active
        profile = ProfileFactory()
        profile.can_write = True
        profile.end_ban_read = datetime.now() - timedelta(days=1)
        self.assertTrue(profile.can_write_now())

        profile = ProfileFactory()
        profile.can_write = False
        profile.is_active = True
        self.assertFalse(profile.can_write_now())

        # Ban is active
        profile = ProfileFactory()
        profile.can_write = False
        profile.end_ban_write = datetime.now() + timedelta(days=1)
        self.assertFalse(profile.can_write_now())

        self.user1.user.is_active = False
        self.user1.user.can_write = True
        self.assertFalse(self.user1.can_write_now())

    def test_get_followed_topics(self):
        # Start with 0
        self.assertEqual(len(TopicAnswerSubscription.objects.get_objects_followed_by(self.user1.user)), 0)
        # Follow !
        TopicAnswerSubscription.objects.toggle_follow(self.forumtopic, self.user1.user)
        # Should be 1
        topicsfollowed = TopicAnswerSubscription.objects.get_objects_followed_by(self.user1.user)
        self.assertEqual(len(topicsfollowed), 1)
        self.assertEqual(self.forumtopic, topicsfollowed[0])

    def test_get_city_with_wrong_ip(self):
        # Set a local IP to the user
        self.user1.last_ip_address = '127.0.0.1'
        # Then the get_city is not found and return empty string
        self.assertEqual('', self.user1.get_city())

        # Same goes for IPV6
        # Set a local IP to the user
        self.user1.last_ip_address = '0000:0000:0000:0000:0000:0000:0000:0001'
        # Then the get_city is not found and return empty string
        self.assertEqual('', self.user1.get_city())

    def test_remove_token_on_removing_from_dev_group(self):
        dev = DevProfileFactory()
        dev.github_token = 'test'
        dev.save()
        dev.user.save()

        self.assertEqual('test', dev.github_token)

        # remove dev from dev group
        dev.user.groups.clear()
        dev.user.save()

        self.assertEqual('', dev.github_token)

    def test_reachable_manager(self):
        # profile types
        profile_normal = ProfileFactory()
        profile_superuser = ProfileFactory()
        profile_superuser.user.is_superuser = True
        profile_superuser.user.save()
        profile_inactive = ProfileFactory()
        profile_inactive.user.is_active = False
        profile_inactive.user.save()
        profile_bot = ProfileFactory()
        profile_bot.user.username = settings.ZDS_APP['member']['bot_account']
        profile_bot.user.save()
        profile_anonymous = ProfileFactory()
        profile_anonymous.user.username = settings.ZDS_APP['member']['anonymous_account']
        profile_anonymous.user.save()
        profile_external = ProfileFactory()
        profile_external.user.username = settings.ZDS_APP['member']['external_account']
        profile_external.user.save()
        profile_ban_def = ProfileFactory()
        profile_ban_def.can_read = False
        profile_ban_def.can_write = False
        profile_ban_def.save()
        profile_ban_temp = ProfileFactory()
        profile_ban_temp.can_read = False
        profile_ban_temp.can_write = False
        profile_ban_temp.end_ban_read = datetime.now() + timedelta(days=1)
        profile_ban_temp.save()
        profile_unban = ProfileFactory()
        profile_unban.can_read = False
        profile_unban.can_write = False
        profile_unban.end_ban_read = datetime.now() - timedelta(days=1)
        profile_unban.save()
        profile_ls_def = ProfileFactory()
        profile_ls_def.can_write = False
        profile_ls_def.save()
        profile_ls_temp = ProfileFactory()
        profile_ls_temp.can_write = False
        profile_ls_temp.end_ban_write = datetime.now() + timedelta(days=1)
        profile_ls_temp.save()

        # groups

        bot = Group(name=settings.ZDS_APP['member']['bot_group'])
        bot.save()

        # associate account to groups
        bot.user_set.add(profile_anonymous.user)
        bot.user_set.add(profile_external.user)
        bot.user_set.add(profile_bot.user)
        bot.save()

        # test reachable user
        profiles_reacheable = Profile.objects.contactable_members().all()
        self.assertIn(profile_normal, profiles_reacheable)
        self.assertIn(profile_superuser, profiles_reacheable)
        self.assertNotIn(profile_inactive, profiles_reacheable)
        self.assertNotIn(profile_anonymous, profiles_reacheable)
        self.assertNotIn(profile_external, profiles_reacheable)
        self.assertNotIn(profile_bot, profiles_reacheable)
        self.assertIn(profile_unban, profiles_reacheable)
        self.assertNotIn(profile_ban_def, profiles_reacheable)
        self.assertNotIn(profile_ban_temp, profiles_reacheable)
        self.assertIn(profile_ls_def, profiles_reacheable)
        self.assertIn(profile_ls_temp, profiles_reacheable)

    def test_remove_hats_linked_to_group(self):
        # create a hat linked to a group
        hat_name = 'Test hat'
        hat, _ = Hat.objects.get_or_create(name__iexact=hat_name, defaults={'name': hat_name})
        group, _ = Group.objects.get_or_create(name='test_hat')
        hat.group = group
        hat.save()
        # add it to a user
        self.user1.hats.add(hat)
        self.user1.save()
        # the user shound't have the hat through their profile
        self.assertNotIn(hat, self.user1.hats.all())