Example #1
0
    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 !
Example #2
0
    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
Example #3
0
 def _prepare(cls, create, **kwargs):
     beta_forum = kwargs.pop("forum", None)
     publishable_content = super(BetaContentFactory, cls)._prepare(create, **kwargs)
     if publishable_content.authors.count() > 0 and beta_forum is not None:
         beta_topic = TopicFactory(title="[beta]" + publishable_content.title,
                                   author=publishable_content.authors.first(),
                                   forum=beta_forum)
         publishable_content.sha_beta = publishable_content.sha_draft
         publishable_content.beta_topic = beta_topic
         publishable_content.save()
         PostFactory(topic=beta_topic, position=1, author=publishable_content.authors.first())
         beta_topic.save()
     return publishable_content
Example #4
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)
Example #5
0
    def test_mark_read_a_topic_from_view_list_posts(self):
        """
        To ensure we can subscribe to a topic, we first generate a new notification when
        another user posts a message, then mark the notification as read after displaying
        the list of messages.
        """
        topic = TopicFactory(forum=self.forum11, author=self.user2)
        PostFactory(topic=topic, author=self.user2, position=1)

        # Follow the topic.
        self.assertIsNone(
            TopicAnswerSubscription.objects.get_existing(self.user1, topic))
        subscription = TopicAnswerSubscription.objects.get_or_create_active(
            self.user1, topic)

        # Creates a new post in the topic to generate a new notification.
        PostFactory(topic=topic, author=self.user2, position=1)
        content_notification_type = ContentType.objects.get_for_model(
            topic.last_message)
        notification = Notification.objects.get(
            subscription=subscription,
            content_type__pk=content_notification_type.pk,
            object_id=topic.last_message.pk,
            is_read=False,
        )
        self.assertIsNotNone(notification)

        response = self.client.get(
            reverse("topic-posts-list", args=[topic.pk, topic.slug()]))
        self.assertEqual(response.status_code, 200)

        # Checks that the notification is reading now.
        notification = Notification.objects.get(
            subscription=subscription,
            content_type__pk=content_notification_type.pk,
            object_id=topic.last_message.pk,
            is_read=True,
        )
        self.assertIsNotNone(notification)
Example #6
0
def load_topics(cli, size, fake):
    """
    Load topics
    """
    nb_topics = size * 10
    cli.stdout.write(u"Nombres de Topics à créer : {}".format(nb_topics))
    tps1 = time.time()
    nb_forums = Forum.objects.count()
    if nb_forums == 0:
        cli.stdout.write(
            u"Il n'y a aucun forum actuellement. "
            u"Vous devez rajouter les forums dans vos fixtures (forum)")
    else:
        forums = list(Forum.objects.all())
        nb_users = User.objects.count()
        if nb_users == 0:
            cli.stdout.write(
                u"Il n'y a aucun membre actuellement. "
                u"Vous devez rajouter les membres dans vos fixtures (member)")
        else:
            profiles = list(Profile.objects.all())
            nb_tags = Tag.objects.count()
            if nb_tags == 0:
                cli.stdout.write(
                    u"Il n'y a aucun tag actuellement. "
                    u"Vous devez rajouter les tags dans vos fixtures (tag)")
            else:
                for i in range(0, nb_topics):
                    topic = TopicFactory(forum=forums[i % nb_forums],
                                         author=profiles[i % nb_users].user)
                    if i % 5 == 0:
                        topic.is_solved = True
                    if i % 10 == 0:
                        topic.is_locked = True
                    if i % 15 == 0:
                        topic.is_sticky = True
                    nb_rand_tags = random.randint(0, 5)
                    for k in range(0, nb_rand_tags):
                        my_random_tag = Tag.objects.filter(
                            pk=random.randint(1, nb_tags)).first()
                        if my_random_tag:
                            topic.tags.add(my_random_tag)
                    topic.title = fake.text(max_nb_chars=80)
                    topic.subtitle = fake.text(max_nb_chars=200)
                    topic.save()
                    PostFactory(topic=topic, author=topic.author, position=1)
                    sys.stdout.write(" Topic {}/{}  \r".format(
                        i + 1, nb_topics))
                    sys.stdout.flush()
                tps2 = time.time()
                cli.stdout.write(u"\nFait en {} sec".format(tps2 - tps1))
Example #7
0
    def test_hide_post_mark_notification_as_read(self):
        """
        Ensure a notification gets deleted when the corresponding post is hidden.
        """
        topic = TopicFactory(forum=self.forum11, author=self.user1)
        PostFactory(topic=topic, author=self.user1, position=1)
        PostFactory(topic=topic, author=self.user2, position=2)
        PostFactory(topic=topic, author=ProfileFactory().user, position=3)

        notifications = Notification.objects.filter(object_id=topic.last_message.pk, is_read=False).all()
        self.assertEqual(1, len(notifications))

        # hide last post
        data = {
            'delete_message': ''
        }
        self.assertTrue(self.client.login(username=StaffProfileFactory().user.username, password='******'))
        response = self.client.post(
            reverse('post-edit') + '?message={}'.format(topic.last_message.pk), data, follow=False)
        self.assertEqual(302, response.status_code)

        notifications = Notification.objects.filter(object_id=topic.last_message.pk, is_read=True).all()
        self.assertEqual(1, len(notifications))
Example #8
0
 def _prepare(cls, create, **kwargs):
     author = kwargs.pop("author", None)
     beta_forum = kwargs.pop("forum", None)
     tuto = super(BetaMiniTutorialFactory, cls)._prepare(create, **kwargs)
     tuto.sha_beta = tuto.sha_draft
     if beta_forum is not None and author is not None:
         tuto.authors.add(author)
         tuto.save()
         beta_topic = TopicFactory(title="[beta]" + tuto.title, author=author,
                                   forum=beta_forum, key=tuto.pk)
         PostFactory(topic=beta_topic, position=1, author=author)
         beta_topic.key = tuto.pk
         beta_topic.save()
     return tuto
Example #9
0
    def test_mark_notifications_as_read(self):
        category = CategoryFactory(position=1)
        forum = ForumFactory(category=category, position_in_category=1)
        topic = TopicFactory(forum=forum, author=self.user1)
        PostFactory(topic=topic, author=self.user1, position=1)
        PostFactory(topic=topic, author=self.user2, position=2)

        self.assertTrue(self.client.login(username=self.user1.username, password='******'))

        notifications = Notification.objects.get_unread_notifications_of(self.user1)
        self.assertEqual(1, len(notifications))

        self.assertFalse(is_read(topic, self.user1))

        result = self.client.post(
            reverse('mark-notifications-as-read'),
            follow=False)
        self.assertEqual(result.status_code, 302)

        notifications = Notification.objects.get_unread_notifications_of(self.user1)
        self.assertEqual(0, len(notifications))

        self.assertTrue(is_read(topic, self.user1))
Example #10
0
    def test_mark_all_notifications_as_read_when_toggle_follow(self):
        """
        When a user unsubscribes from a content, we mark all notifications for
        this content as read.
        """
        category = CategoryFactory(position=1)
        forum = ForumFactory(category=category, position_in_category=1)
        topic = TopicFactory(forum=forum, author=self.user1)
        PostFactory(topic=topic, author=self.user1, position=1)
        PostFactory(topic=topic, author=self.user2, position=2)

        notifications = Notification.objects.get_unread_notifications_of(
            self.user1)
        self.assertEqual(1, len(notifications))
        self.assertIsNotNone(notifications.first())
        self.assertEqual(topic.last_message,
                         notifications.first().content_object)

        TopicAnswerSubscription.objects.toggle_follow(topic, self.user1)

        self.assertEqual(
            0,
            len(Notification.objects.get_unread_notifications_of(self.user1)))
Example #11
0
    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.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.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.loads(result.content.decode('utf-8'))
        self.assertEqual(len(content['results']), 2)
Example #12
0
    def test_mark_notifications_as_read(self):
        category = ForumCategoryFactory(position=1)
        forum = ForumFactory(category=category, position_in_category=1)
        topic = TopicFactory(forum=forum, author=self.user1)
        PostFactory(topic=topic, author=self.user1, position=1)
        PostFactory(topic=topic, author=self.user2, position=2)

        self.client.force_login(self.user1)

        notifications = Notification.objects.get_unread_notifications_of(
            self.user1)
        self.assertEqual(1, len(notifications))

        self.assertFalse(topic.is_read)

        result = self.client.post(reverse("mark-notifications-as-read"),
                                  follow=False)
        self.assertEqual(result.status_code, 302)

        notifications = Notification.objects.get_unread_notifications_of(
            self.user1)
        self.assertEqual(0, len(notifications))

        self.assertTrue(Topic.objects.get(pk=topic.pk).is_read)
Example #13
0
    def test_edit_post(self):
        """To test all aspects of the edition of simple post by member."""
        topic1 = TopicFactory(forum=self.forum11, author=self.user)
        post1 = PostFactory(topic=topic1, author=self.user, position=1)
        post2 = PostFactory(topic=topic1, author=self.user, position=2)
        post3 = PostFactory(topic=topic1, author=self.user, position=3)

        result = self.client.post(reverse(
            'zds.forum.views.edit_post'
        ) + '?message={0}'.format(post2.pk), {
            'text':
            u'C\'est tout simplement l\'histoire de la ville de Paris que je voudrais vous conter '
        },
                                  follow=False)

        self.assertEqual(result.status_code, 302)

        # check topic's number
        self.assertEqual(Topic.objects.all().count(), 1)

        # check post's number
        self.assertEqual(Post.objects.all().count(), 3)

        # check topic and post
        self.assertEqual(post1.topic, topic1)
        self.assertEqual(post2.topic, topic1)
        self.assertEqual(post3.topic, topic1)

        # check values
        self.assertEqual(
            Post.objects.get(pk=post2.pk).text,
            u'C\'est tout simplement l\'histoire de la ville de Paris que je voudrais vous conter '
        )

        # check edit data
        self.assertEqual(Post.objects.get(pk=post2.pk).editor, self.user)
Example #14
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)
        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.group.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))
Example #15
0
    def test_success_post_karma_neutral(self):
        profile = ProfileFactory()
        category, forum = create_category_and_forum()
        topic = create_topic_in_forum(forum, profile)
        another_profile = ProfileFactory()
        post = PostFactory(topic=topic, author=another_profile.user, position=2)

        vote = CommentVote(user=profile.user, comment=post, positive=True)
        vote.save()

        self.assertTrue(CommentVote.objects.filter(pk=vote.pk).exists())
        self.assertTrue(self.client.login(username=profile.user.username, password='******'))
        response = self.client.put(reverse('api:forum:post-karma', args=(post.pk,)), {'vote': 'neutral'})
        self.assertEqual(response.status_code, status.HTTP_200_OK)
        self.assertFalse(CommentVote.objects.filter(pk=vote.pk).exists())
Example #16
0
    def test_failure_post_karma_with_sanctioned_user(self):
        profile = ProfileFactory()
        category, forum = create_category_and_forum()
        topic = create_topic_in_forum(forum, profile)
        another_profile = ProfileFactory()
        post = PostFactory(topic=topic, author=another_profile.user, position=2)

        profile = ProfileFactory()
        profile.can_read = False
        profile.can_write = False
        profile.save()

        self.assertTrue(self.client.login(username=profile.user.username, password='******'))
        response = self.client.put(reverse('api:forum:post-karma', args=(post.pk,)))
        self.assertEqual(response.status_code, status.HTTP_403_FORBIDDEN)
Example #17
0
    def test_mark_read_a_topic_of_a_forum_subscribed(self):
        """
        When a user has a notification on a topic, the notification should be marked as read.
        """
        NewTopicSubscription.objects.toggle_follow(self.forum11, self.user1)

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

        response = self.client.get(reverse('topic-posts-list', args=[topic.pk, topic.slug()]))
        self.assertEqual(response.status_code, 200)

        notifications = Notification.objects.filter(object_id=topic.pk, is_read=False).all()
        self.assertEqual(0, len(notifications))
Example #18
0
    def test_success_post_karma_like_already_disliked(self):
        profile = ProfileFactory()
        category, forum = create_category_and_forum()
        topic = create_topic_in_forum(forum, profile)
        another_profile = ProfileFactory()
        post = PostFactory(topic=topic, author=another_profile.user, position=2)

        vote = CommentVote(user=profile.user, comment=post, positive=False)
        vote.save()

        self.assertTrue(self.client.login(username=profile.user.username, password='******'))
        response = self.client.put(reverse('api:forum:post-karma', args=(post.pk,)), {'vote': 'like'})
        vote.refresh_from_db()

        self.assertEqual(response.status_code, status.HTTP_200_OK)
        self.assertTrue(vote.positive)
Example #19
0
    def test_answer_empty(self):
        """Test behaviour on empty answer."""
        # Topic and 1st post by another user, to avoid antispam limitation
        topic1 = TopicFactory(forum=self.forum11, author=self.user2)
        PostFactory(topic=topic1, author=self.user2, position=1)

        result = self.client.post(reverse('zds.forum.views.answer') +
                                  '?sujet={0}'.format(topic1.pk), {
                                      'last_post': topic1.last_message.pk,
                                      'text': u' '
                                  },
                                  follow=False)

        # Empty text --> preview = HTTP 200 + post not saved (only 1 post in
        # topic)
        self.assertEqual(result.status_code, 200)
        self.assertEqual(Post.objects.filter(topic=topic1.pk).count(), 1)
Example #20
0
def __generate_topic_and_post(cli, fake, nb_avg_posts_in_topic, nb_topics, nb_users, topics, tps1):
    profiles = list(Profile.objects.all())
    for topic_index in range(0, nb_topics):
        nb_posts = randint(0, nb_avg_posts_in_topic * 2) + 1
        for post_index in range(1, nb_posts):
            post = PostFactory(topic=topics[topic_index], author=profiles[post_index % nb_users].user,
                               position=post_index + 1)
            post.text = fake.paragraph(nb_sentences=5, variable_nb_sentences=True)
            post.text_html = emarkdown(post.text)
            post.is_useful = int(nb_posts * 0.3) > 0 and post_index % int(nb_posts * 0.3) == 0
            post.save()
            sys.stdout.write(' Topic {}/{}  \tPost {}/{}  \r'.format(topic_index + 1,
                                                                     nb_topics, post_index + 1, nb_posts))
            sys.stdout.flush()
    tps2 = time.time()
    cli.stdout.write('\nFait en {} sec'.format(tps2 - tps1))
Example #21
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()))
Example #22
0
    def setUp(self):
        self.staff = StaffFactory()
        self.dummy_author = ProfileFactory()

        self.category = CategoryFactory(position=1)
        self.forum = ForumFactory(category=self.category, position_in_category=1)
        self.topic = TopicFactory(forum=self.forum, author=self.dummy_author.user)
        self.post = PostFactory(topic=self.topic, author=self.dummy_author.user, position=1)

        self.alerts = []
        for i in range(20):
            alert = Alert(author=self.dummy_author.user,
                          comment=self.post,
                          scope='FORUM',
                          text=u'pouet-{}'.format(i),
                          pubdate=(datetime.now() + timedelta(minutes=i)))
            alert.save()
            self.alerts.append(alert)
Example #23
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,
        )
Example #24
0
    def _generate(cls, create, attrs):
        # This parameter is only used inside _generate() and won't be saved in the database,
        # which is why we use attrs.pop() (it is removed from attrs).
        beta_forum = attrs.pop("forum", None)

        # Creates the PublishableContent (see PublishableContentFactory._generate() for more info)
        publishable_content = super()._generate(create, attrs)

        if publishable_content.authors.count() > 0 and beta_forum is not None:
            beta_topic = TopicFactory(
                title="[beta]" + publishable_content.title, author=publishable_content.authors.first(), forum=beta_forum
            )
            publishable_content.sha_beta = publishable_content.sha_draft
            publishable_content.beta_topic = beta_topic
            publishable_content.save()
            PostFactory(topic=beta_topic, position=1, author=publishable_content.authors.first())
            beta_topic.save()
        return publishable_content
Example #25
0
def load_topics(cli, size, fake, *_, **__):
    """
    Load topics
    """
    nb_topics = size * 10
    cli.stdout.write("Nombres de Topics à créer : {}".format(nb_topics))
    tps1 = time.time()
    nb_forums = Forum.objects.count()
    if nb_forums == 0:
        cli.stdout.write(
            "Il n'y a aucun forum actuellement. "
            "Vous devez rajouter les forums dans vos fixtures (forum)")
        return
    forums = list(Forum.objects.all())
    nb_users = User.objects.count()
    if nb_users == 0:
        cli.stdout.write(
            "Il n'y a aucun membre actuellement. "
            "Vous devez rajouter les membres dans vos fixtures (member)")
        return
    profiles = list(Profile.objects.all())
    nb_tags = Tag.objects.count()
    if nb_tags == 0:
        cli.stdout.write(
            "Il n'y a aucun tag actuellement. "
            "Vous devez rajouter les tags dans vos fixtures (tag)")
        return
    for i in range(0, nb_topics):
        with contextlib.suppress(IntegrityError):
            topic = TopicFactory(forum=forums[i % nb_forums],
                                 author=profiles[i % nb_users].user)
            topic.solved_by = profiles[i % nb_users].user if i % 5 else None
            topic.is_locked = i % 10 == 0
            topic.is_sticky = i % 15 == 0
            nb_rand_tags = random.randint(0, 5)
            add_generated_tags_to_topic(nb_rand_tags, nb_tags, topic)
            topic.title = fake.text(max_nb_chars=80)
            topic.subtitle = fake.text(max_nb_chars=200)
            topic.save()
            PostFactory(topic=topic, author=topic.author, position=1)
        sys.stdout.write(" Topic {}/{}  \r".format(i + 1, nb_topics))
        sys.stdout.flush()
    tps2 = time.time()
    cli.stdout.write("\nFait en {} sec".format(tps2 - tps1))
Example #26
0
    def setUp(self):
        # prepare a user and 2 Topic (with and without tags)

        settings.EMAIL_BACKEND = \
            'django.core.mail.backends.locmem.EmailBackend'

        self.category1 = CategoryFactory(position=1)
        self.forum = ForumFactory(
            category=self.category1,
            position_in_category=1)
        self.forum2 = ForumFactory(
            category=self.category1,
            position_in_category=2)
        self.forum3 = ForumFactory(
            category=self.category1,
            position_in_category=3)

        self.user = ProfileFactory().user
        log = self.client.login(
            username=self.user.username,
            password='******')
        self.assertEqual(log, True)

        self.tag = TagFactory()
        self.topic1 = TopicFactory(forum=self.forum, author=self.user)
        self.topic2 = TopicFactory(forum=self.forum2, author=self.user)
        self.topic2.tags.add(self.tag)
        self.topic2.save()

        # create 2 posts un each forum
        PostFactory(topic=self.topic1, author=self.user, position=1)
        PostFactory(topic=self.topic1, author=self.user, position=2)
        PostFactory(topic=self.topic2, author=self.user, position=1)
        PostFactory(topic=self.topic2, author=self.user, position=2)

        # and last topic + post alone
        self.tag2 = TagFactory()
        self.topic3 = TopicFactory(forum=self.forum3, author=self.user)
        self.post3 = PostFactory(topic=self.topic3, author=self.user, position=1)
        self.topic3.tags.add(self.tag2)
        self.topic3.save()

        self.postfeed = LastPostsFeedRSS()
Example #27
0
    def test_add_subscribed_tag(self):
        """
            When the topic is edited and a tag is added to which the user has subscribed
        """
        NewTopicSubscription.objects.toggle_follow(self.tag1, self.user2)

        topic = TopicFactory(forum=self.forum11, author=self.user1)
        PostFactory(topic=topic, author=self.user1, position=1)

        self.client.post(
            reverse('topic-edit') + '?topic={0}'.format(topic.pk),
            {
                'title': 'Un autre sujet',
                'subtitle': 'Encore ces lombards en plein ete',
                'text': 'C\'est tout simplement l\'histoire de la ville de Paris que je voudrais vous conter ',
                'tags': 'Linux'
            }, follow=False)

        notifications = Notification.objects.filter(object_id=topic.pk, is_read=False).all()
        self.assertEqual(1, len(notifications))
Example #28
0
    def test_success_post_karma_dislike(self):
        profile = ProfileFactory()
        category, forum = create_category_and_forum()
        topic = create_topic_in_forum(forum, profile)
        another_profile = ProfileFactory()
        post = PostFactory(topic=topic,
                           author=another_profile.user,
                           position=2)

        self.assertTrue(
            self.client.login(username=profile.user.username,
                              password="******"))
        response = self.client.put(
            reverse("api:forum:post-karma", args=(post.pk, )),
            {"vote": "dislike"})
        self.assertEqual(response.status_code, status.HTTP_200_OK)
        self.assertTrue(
            CommentVote.objects.filter(user=profile.user,
                                       comment=post,
                                       positive=False).exists())
Example #29
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.client.force_login(staff.user)
        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.client.force_login(self.user1)
        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()))
Example #30
0
    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
Example #31
0
def load_posts(cli, size, fake):
    """
    Load posts
    """
    nb_avg_posts_in_topic = size * 20
    cli.stdout.write(
        u"Nombres de messages à poster en moyenne dans un sujet : {}".format(
            nb_avg_posts_in_topic))
    tps1 = time.time()
    nb_topics = Topic.objects.count()
    if nb_topics == 0:
        cli.stdout.write(
            u"Il n'y a aucun topic actuellement. "
            u"Vous devez rajouter les topics dans vos fixtures (topic)")
    else:
        topics = list(Topic.objects.all())
        nb_users = User.objects.count()
        if nb_users == 0:
            cli.stdout.write(
                u"Il n'y a aucun membre actuellement. "
                u"Vous devez rajouter les membres dans vos fixtures (member)")
        else:
            profiles = list(Profile.objects.all())
            for i in range(0, nb_topics):
                nb_posts = randint(0, nb_avg_posts_in_topic * 2) + 1
                for j in range(1, nb_posts):
                    post = PostFactory(topic=topics[i],
                                       author=profiles[j % nb_users].user,
                                       position=j + 1)
                    post.text = fake.paragraph(nb_sentences=5,
                                               variable_nb_sentences=True)
                    post.text_html = emarkdown(post.text)
                    if int(nb_posts * 0.3) > 0:
                        if j % int(nb_posts * 0.3) == 0:
                            post.is_useful = True
                    post.save()
                    sys.stdout.write(" Topic {}/{}  \tPost {}/{}  \r".format(
                        i + 1, nb_topics, j + 1, nb_posts))
                    sys.stdout.flush()
            tps2 = time.time()
            cli.stdout.write(u"\nFait en {} sec".format(tps2 - tps1))
Example #32
0
    def test_notification_read(self):
        """
        When we post on a topic, a notification is created for each subscriber. We can
        read a notification when we display the list of messages of the said topic.
        """
        topic1 = TopicFactory(forum=self.forum11, author=self.user2)
        PostFactory(topic=topic1, author=self.user2, position=1)

        result = self.client.post(
            reverse("post-new") + "?sujet={0}".format(topic1.pk),
            {
                "last_post":
                topic1.last_message.pk,
                "text":
                "C'est tout simplement l'histoire de la ville de Paris que je voudrais vous conter ",
            },
            follow=False,
        )

        self.assertEqual(result.status_code, 302)

        notification = Notification.objects.get(subscription__user=self.user2)
        self.assertEqual(notification.is_read, False)

        self.client.logout()
        self.assertTrue(
            self.client.login(username=self.user2.username,
                              password="******"), True)

        result = self.client.get(reverse(
            "topic-posts-list", args=[topic1.pk,
                                      old_slugify(topic1.title)]),
                                 follow=True)
        self.assertEqual(result.status_code, 200)

        notification = Notification.objects.get(subscription__user=self.user2)
        self.assertEqual(notification.is_read, True)
Example #33
0
    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)
Example #34
0
    def test_add_subscribed_tag(self):
        """
        When the topic is edited and a tag is added to which the user has subscribed
        """
        NewTopicSubscription.objects.toggle_follow(self.tag1, self.user2)

        topic = TopicFactory(forum=self.forum11, author=self.user1)
        PostFactory(topic=topic, author=self.user1, position=1)

        self.client.post(
            reverse("topic-edit") + f"?topic={topic.pk}",
            {
                "title": "Un autre sujet",
                "subtitle": "Encore ces lombards en plein ete",
                "text":
                "C'est tout simplement l'histoire de la ville de Paris que je voudrais vous conter ",
                "tags": "Linux",
            },
            follow=False,
        )

        notifications = Notification.objects.filter(object_id=topic.pk,
                                                    is_read=False).all()
        self.assertEqual(1, len(notifications))
Example #35
0
    def test_get_post_voters(self):
        profile = ProfileFactory()
        profile2 = ProfileFactory()
        category, forum = create_category_and_forum()
        topic = create_topic_in_forum(forum, profile)
        another_profile = ProfileFactory()

        upvoted_answer = PostFactory(topic=topic, author=another_profile.user, position=2)
        upvoted_answer.like += 2
        upvoted_answer.save()
        CommentVote.objects.create(user=profile.user, comment=upvoted_answer, positive=True)

        downvoted_answer = PostFactory(topic=topic, author=another_profile.user, position=3)
        downvoted_answer.dislike += 2
        downvoted_answer.save()
        anon_limit = CommentVote.objects.create(user=profile.user, comment=downvoted_answer, positive=False)

        CommentVote.objects.create(user=profile2.user, comment=upvoted_answer, positive=True)
        CommentVote.objects.create(user=profile2.user, comment=downvoted_answer, positive=False)

        equal_answer = PostFactory(topic=topic, author=another_profile.user, position=4)
        equal_answer.like += 1
        equal_answer.dislike += 1
        equal_answer.save()
        CommentVote.objects.create(user=profile.user, comment=equal_answer, positive=True)
        CommentVote.objects.create(user=profile2.user, comment=equal_answer, positive=False)

        self.assertTrue(self.client.login(username=profile.user.username, password='******'))

        # on first message we should see 2 likes and 0 anonymous
        response = self.client.get(reverse('api:forum:post-karma', args=[upvoted_answer.pk]))
        self.assertEqual(response.status_code, status.HTTP_200_OK)
        self.assertEqual(2, len(response.data['like']['users']))
        self.assertEqual(0, len(response.data['dislike']['users']))
        self.assertEqual(2, response.data['like']['count'])
        self.assertEqual(0, response.data['dislike']['count'])

        # on second message we should see 2 dislikes and 0 anonymous
        response = self.client.get(reverse('api:forum:post-karma', args=[downvoted_answer.pk]))
        self.assertEqual(response.status_code, status.HTTP_200_OK)
        self.assertEqual(0, len(response.data['like']['users']))
        self.assertEqual(2, len(response.data['dislike']['users']))
        self.assertEqual(0, response.data['like']['count'])
        self.assertEqual(2, response.data['dislike']['count'])

        # on third message we should see 1 like and 1 dislike and 0 anonymous
        response = self.client.get(reverse('api:forum:post-karma', args=[equal_answer.pk]))
        self.assertEqual(response.status_code, status.HTTP_200_OK)
        self.assertEqual(1, len(response.data['like']['users']))
        self.assertEqual(1, len(response.data['dislike']['users']))
        self.assertEqual(1, response.data['like']['count'])
        self.assertEqual(1, response.data['dislike']['count'])

        # Now we change the settings to keep anonymous the first [dis]like
        settings.VOTES_ID_LIMIT = anon_limit.pk
        # and we run the same tests
        # on first message we should see 1 like and 1 anonymous
        response = self.client.get(reverse('api:forum:post-karma', args=[upvoted_answer.pk]))
        self.assertEqual(response.status_code, status.HTTP_200_OK)
        self.assertEqual(1, len(response.data['like']['users']))
        self.assertEqual(0, len(response.data['dislike']['users']))
        self.assertEqual(2, response.data['like']['count'])
        self.assertEqual(0, response.data['dislike']['count'])

        # on second message we should see 1 dislikes and 1 anonymous
        response = self.client.get(reverse('api:forum:post-karma', args=[downvoted_answer.pk]))
        self.assertEqual(response.status_code, status.HTTP_200_OK)
        self.assertEqual(0, len(response.data['like']['users']))
        self.assertEqual(1, len(response.data['dislike']['users']))
        self.assertEqual(0, response.data['like']['count'])
        self.assertEqual(2, response.data['dislike']['count'])

        # on third message we should see 1 like and 1 dislike and 0 anonymous
        response = self.client.get(reverse('api:forum:post-karma', args=[equal_answer.pk]))
        self.assertEqual(response.status_code, status.HTTP_200_OK)
        self.assertEqual(1, len(response.data['like']['users']))
        self.assertEqual(1, len(response.data['dislike']['users']))
        self.assertEqual(1, response.data['like']['count'])
        self.assertEqual(1, response.data['dislike']['count'])
Example #36
0
class LastPostFeedTest(TestCase):

    def setUp(self):
        # prepare a user and 2 Topic (with and without tags)

        settings.EMAIL_BACKEND = \
            'django.core.mail.backends.locmem.EmailBackend'

        self.category1 = CategoryFactory(position=1)
        self.forum = ForumFactory(
            category=self.category1,
            position_in_category=1)
        self.forum2 = ForumFactory(
            category=self.category1,
            position_in_category=2)
        self.forum3 = ForumFactory(
            category=self.category1,
            position_in_category=3)

        self.user = ProfileFactory().user
        log = self.client.login(
            username=self.user.username,
            password='******')
        self.assertEqual(log, True)

        self.tag = TagFactory()
        self.topic1 = TopicFactory(forum=self.forum, author=self.user)
        self.topic2 = TopicFactory(forum=self.forum2, author=self.user)
        self.topic2.tags.add(self.tag)
        self.topic2.save()

        # create 2 posts un each forum
        PostFactory(topic=self.topic1, author=self.user, position=1)
        PostFactory(topic=self.topic1, author=self.user, position=2)
        PostFactory(topic=self.topic2, author=self.user, position=1)
        PostFactory(topic=self.topic2, author=self.user, position=2)

        # and last topic + post alone
        self.tag2 = TagFactory()
        self.topic3 = TopicFactory(forum=self.forum3, author=self.user)
        self.post3 = PostFactory(topic=self.topic3, author=self.user, position=1)
        self.topic3.tags.add(self.tag2)
        self.topic3.save()

        self.postfeed = LastPostsFeedRSS()

    def test_is_well_setup(self):
        """ Test that base parameters are Ok """

        self.assertEqual(self.postfeed.link, '/forums/')
        reftitle = 'Derniers messages sur {}'.format(settings.ZDS_APP['site']['literal_name'])
        self.assertEqual(self.postfeed.title, reftitle)
        refdescription = ('Les derniers messages '
                          'parus sur le forum de {}.'.format(settings.ZDS_APP['site']['literal_name']))
        self.assertEqual(self.postfeed.description, refdescription)

        atom = LastPostsFeedATOM()
        self.assertEqual(atom.subtitle, refdescription)

    def test_getobjects(self):
        """ Get object should return the given parameteres in an object """

        factory = RequestFactory()
        request = factory.get(reverse('post-feed-rss') + '?forum=fofo&tag=tatag')
        obj = self.postfeed.get_object(request=request)
        self.assertEqual(obj['forum'], 'fofo')
        self.assertEqual(obj['tag'], 'tatag')

    def test_items_success(self):
        """ test that right items are sent back according to obj """

        # test empty obj
        obj = {}
        # should return all topics
        topics = self.postfeed.items(obj=obj)
        self.assertEqual(len(topics), 5)
        # test with a tag
        obj = {'tag': self.tag.pk}
        topics = self.postfeed.items(obj=obj)
        self.assertEqual(len(topics), 2)
        # test with a forum
        obj = {'forum': self.topic1.forum.pk}
        topics = self.postfeed.items(obj=obj)
        self.assertEqual(len(topics), 2)
        # test with a forum and a tag
        obj = {'forum': self.topic1.forum.pk, 'tag': self.tag.pk}
        topics = self.postfeed.items(obj=obj)
        self.assertEqual(len(topics), 0)

    def test_items_bad_cases(self):
        """ test that right items are sent back according to obj """

        # test empty values, return value shoulb be empty
        obj = {'forum': -1, 'tag': -1}
        topics = self.postfeed.items(obj=obj)
        self.assertEqual(len(topics), 0)
        obj = {'forum': -1}
        topics = self.postfeed.items(obj=obj)
        self.assertEqual(len(topics), 0)
        obj = {'tag': -1}
        topics = self.postfeed.items(obj=obj)
        self.assertEqual(len(topics), 0)
        # with a weird object
        obj = {'forum': 'lol'}
        topics = self.postfeed.items(obj=obj)
        self.assertEqual(len(topics), 0)

    def test_get_pubdate(self):
        """ test the return value of pubdate """

        ref = self.post3.pubdate
        posts = self.postfeed.items(obj={'tag': self.tag2.pk})
        ret = self.postfeed.item_pubdate(item=posts[0])
        self.assertEqual(ret.date(), ref.date())

    def test_get_title(self):
        """ test the return value of title """

        ref = '{}, message #{}'.format(self.post3.topic.title, self.post3.pk)
        posts = self.postfeed.items(obj={'tag': self.tag2.pk})
        ret = self.postfeed.item_title(item=posts[0])
        self.assertEqual(ret, ref)

    def test_get_description(self):
        """ test the return value of description """

        ref = self.post3.text_html
        posts = self.postfeed.items(obj={'tag': self.tag2.pk})
        ret = self.postfeed.item_description(item=posts[0])
        self.assertEqual(ret, ref)

    def test_get_author_name(self):
        """ test the return value of author name """

        ref = self.post3.author.username
        posts = self.postfeed.items(obj={'tag': self.tag2.pk})
        ret = self.postfeed.item_author_name(item=posts[0])
        self.assertEqual(ret, ref)

    def test_get_author_link(self):
        """ test the return value of author link """

        ref = self.post3.author.get_absolute_url()
        posts = self.postfeed.items(obj={'tag': self.tag2.pk})
        ret = self.postfeed.item_author_link(item=posts[0])
        self.assertEqual(ret, ref)

    def test_get_item_link(self):
        """ test the return value of item link """

        ref = self.post3.get_absolute_url()
        posts = self.postfeed.items(obj={'tag': self.tag2.pk})
        ret = self.postfeed.item_link(item=posts[0])
        self.assertEqual(ret, ref)
Example #37
0
    def test_es_manager(self):
        """Test the behavior of the ``es_manager`` command"""

        if not self.index_manager.connected_to_es:
            return

        # in the beginning: the void
        self.assertTrue(self.index_manager.index not in self.index_manager.es.cat.indices())

        text = 'Ceci est un texte de test'

        # create a topic with a post
        topic = TopicFactory(forum=self.forum, author=self.user, title=text)
        post = PostFactory(topic=topic, author=self.user, position=1)
        post.text = post.text_html = text
        post.save()

        topic = Topic.objects.get(pk=topic.pk)
        post = Post.objects.get(pk=post.pk)

        self.assertFalse(topic.es_already_indexed)
        self.assertTrue(topic.es_flagged)
        self.assertFalse(post.es_already_indexed)
        self.assertTrue(post.es_flagged)

        # create a middle-tutorial and publish it
        tuto = PublishableContentFactory(type='TUTORIAL')
        tuto.authors.add(self.user)
        tuto.save()

        tuto_draft = tuto.load_version()
        chapter1 = ContainerFactory(parent=tuto_draft, db_object=tuto)
        chapter1.repo_update(text, text, text)
        extract1 = ExtractFactory(container=chapter1, db_object=tuto)
        version = extract1.repo_update(text, text)
        published = publish_content(tuto, tuto_draft, is_major_update=True)

        tuto.sha_public = version
        tuto.sha_draft = version
        tuto.public_version = published
        tuto.save()

        published = PublishedContent.objects.get(content_pk=tuto.pk)
        self.assertFalse(published.es_already_indexed)
        self.assertTrue(published.es_flagged)

        # 1. test "index-all"
        call_command('es_manager', 'index_all')
        self.assertTrue(self.index_manager.es.indices.exists(self.index_manager.index))
        self.index_manager.index_exists = True

        topic = Topic.objects.get(pk=topic.pk)
        post = Post.objects.get(pk=post.pk)

        self.assertTrue(topic.es_already_indexed)
        self.assertFalse(topic.es_flagged)
        self.assertTrue(post.es_already_indexed)
        self.assertFalse(post.es_flagged)

        published = PublishedContent.objects.get(content_pk=tuto.pk)
        self.assertTrue(published.es_already_indexed)
        self.assertFalse(published.es_flagged)

        s = Search()
        s.query(MatchAll())
        results = self.index_manager.setup_search(s).execute()
        self.assertEqual(len(results), 4)  # get 4 results, one of each type

        must_contain = {'post': False, 'topic': False, 'publishedcontent': False, 'chapter': False}
        id_must_be = {
            'post': str(post.pk),
            'topic': str(topic.pk),
            'publishedcontent': str(published.pk),
            'chapter': tuto.slug + '__' + chapter1.slug
        }

        for hit in results:
            doc_type = hit.meta.doc_type
            must_contain[doc_type] = True
            self.assertEqual(hit.meta.id, id_must_be[doc_type])

        self.assertTrue(all(must_contain))

        # 2. test "clear"
        self.assertTrue(self.index_manager.index in self.index_manager.es.cat.indices())  # index in

        call_command('es_manager', 'clear')
        self.assertFalse(self.index_manager.es.indices.exists(self.index_manager.index))
        self.index_manager.index_exists = False

        # must reset every object
        topic = Topic.objects.get(pk=topic.pk)
        post = Post.objects.get(pk=post.pk)

        self.assertFalse(topic.es_already_indexed)
        self.assertTrue(topic.es_flagged)
        self.assertFalse(post.es_already_indexed)
        self.assertTrue(post.es_flagged)

        published = PublishedContent.objects.get(content_pk=tuto.pk)
        self.assertFalse(published.es_already_indexed)
        self.assertTrue(published.es_flagged)

        self.assertTrue(self.index_manager.index not in self.index_manager.es.cat.indices())  # index wiped out !

        # 3. test "setup"
        call_command('es_manager', 'setup')
        self.assertTrue(self.index_manager.es.indices.exists(self.index_manager.index))
        self.index_manager.index_exists = True

        self.assertTrue(self.index_manager.index in self.index_manager.es.cat.indices())  # index back in ...

        s = Search()
        s.query(MatchAll())
        results = self.index_manager.setup_search(s).execute()
        self.assertEqual(len(results), 0)  # ... but with nothing in it

        result = self.index_manager.es.indices.get_settings(index=self.index_manager.index)
        settings_index = result[self.index_manager.index]['settings']['index']
        self.assertTrue('analysis' in settings_index)  # custom analyzer was setup

        # 4. test "index-flagged" once ...
        call_command('es_manager', 'index_flagged')

        topic = Topic.objects.get(pk=topic.pk)
        post = Post.objects.get(pk=post.pk)

        self.assertTrue(topic.es_already_indexed)
        self.assertFalse(topic.es_flagged)
        self.assertTrue(post.es_already_indexed)
        self.assertFalse(post.es_flagged)

        published = PublishedContent.objects.get(content_pk=tuto.pk)
        self.assertTrue(published.es_already_indexed)
        self.assertFalse(published.es_flagged)

        s = Search()
        s.query(MatchAll())
        results = self.index_manager.setup_search(s).execute()
        self.assertEqual(len(results), 4)  # get the 4 results back
Example #38
0
    def test_indexation(self):
        """test the indexation and deletion of the different documents"""

        if not self.manager.connected_to_es:
            return

        # create a topic with a post
        topic = TopicFactory(forum=self.forum, author=self.user)
        post = PostFactory(topic=topic, author=self.user, position=1)

        topic = Topic.objects.get(pk=topic.pk)
        post = Post.objects.get(pk=post.pk)

        self.assertFalse(topic.es_already_indexed)
        self.assertTrue(topic.es_flagged)
        self.assertFalse(post.es_already_indexed)
        self.assertTrue(post.es_flagged)

        # create a middle-tutorial and publish it
        tuto = PublishableContentFactory(type='TUTORIAL')
        tuto.authors.add(self.user)
        tuto.save()

        tuto_draft = tuto.load_version()
        chapter1 = ContainerFactory(parent=tuto_draft, db_object=tuto)
        ExtractFactory(container=chapter1, db_object=tuto)
        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()

        published = PublishedContent.objects.get(content_pk=tuto.pk)
        self.assertFalse(published.es_already_indexed)
        self.assertTrue(published.es_flagged)

        # 1. index all
        for model in self.indexable:
            if model is FakeChapter:
                continue
            self.manager.es_bulk_indexing_of_model(model, force_reindexing=False)
            self.manager.refresh_index()

        topic = Topic.objects.get(pk=topic.pk)
        post = Post.objects.get(pk=post.pk)

        self.assertTrue(topic.es_already_indexed)
        self.assertFalse(topic.es_flagged)
        self.assertTrue(post.es_already_indexed)
        self.assertFalse(post.es_flagged)

        published = PublishedContent.objects.get(content_pk=tuto.pk)
        self.assertTrue(published.es_already_indexed)
        self.assertFalse(published.es_flagged)

        s = Search()
        s.query(MatchAll())
        results = self.manager.setup_search(s).execute()
        self.assertEqual(len(results), 4)  # get 4 results, one of each type

        must_contain = {'post': False, 'topic': False, 'publishedcontent': False, 'chapter': False}
        id_must_be = {
            'post': str(post.pk),
            'topic': str(topic.pk),
            'publishedcontent': str(published.pk),
            'chapter': tuto.slug + '__' + chapter1.slug
        }

        for hit in results:
            doc_type = hit.meta.doc_type
            must_contain[doc_type] = True
            self.assertEqual(hit.meta.id, id_must_be[doc_type])

        self.assertTrue(all(must_contain))

        # 2. Test what reindexation will do:
        new_topic = TopicFactory(forum=self.forum, author=self.user)
        new_post = PostFactory(topic=new_topic, author=self.user, position=1)

        pk_of_topics_to_reindex = []
        for item in Topic.get_es_indexable(force_reindexing=False):
            pk_of_topics_to_reindex.append(item.pk)

        pk_of_posts_to_reindex = []
        for item in Post.get_es_indexable(force_reindexing=False):
            pk_of_posts_to_reindex.append(item.pk)

        self.assertTrue(topic.pk not in pk_of_topics_to_reindex)
        self.assertTrue(new_topic.pk in pk_of_topics_to_reindex)
        self.assertTrue(post.pk not in pk_of_posts_to_reindex)
        self.assertTrue(new_post.pk in pk_of_posts_to_reindex)

        for model in self.indexable:  # ok, so let's index that
            if model is FakeChapter:
                continue
            self.manager.es_bulk_indexing_of_model(model, force_reindexing=False)
        self.manager.refresh_index()

        s = Search()
        s.query(MatchAll())
        results = self.manager.setup_search(s).execute()
        self.assertEqual(len(results), 6)  # good!

        # 3. Test single deletion:
        new_post = Post.objects.get(pk=new_post.pk)

        self.manager.delete_document(new_post)
        self.manager.refresh_index()

        s = Search()
        s.query(MatchAll())
        results = self.manager.setup_search(s).execute()
        self.assertEqual(len(results), 5)  # one is missing

        for hit in results:
            self.assertTrue(hit.meta.doc_type != Post.get_es_document_type() or hit.meta.id != new_post.es_id)

        # 4. Test "delete_by_query_deletion":
        topic = Topic.objects.get(pk=topic.pk)
        new_topic = Topic.objects.get(pk=new_topic.pk)

        self.manager.delete_by_query(Topic.get_es_document_type(), MatchAll())  # the two topic are deleted
        self.manager.refresh_index()

        s = Search()
        s.query(MatchAll())
        results = self.manager.setup_search(s).execute()
        self.assertEqual(len(results), 3)

        for hit in results:
            self.assertTrue(hit.meta.doc_type != Topic.get_es_document_type() or hit.meta.id != new_topic.es_id)
            self.assertTrue(hit.meta.doc_type != Topic.get_es_document_type() or hit.meta.id != topic.es_id)

        # 5. Test that the deletion of an object also triggers its deletion in ES
        post = Post.objects.get(pk=post.pk)
        post.delete()
        self.manager.refresh_index()

        s = Search()
        s.query(MatchAll())
        results = self.manager.setup_search(s).execute()
        self.assertEqual(len(results), 2)

        for hit in results:
            self.assertTrue(hit.meta.doc_type != Post.get_es_document_type() or hit.meta.id != post.es_id)

        # 6. Test full desindexation:
        for model in self.indexable:
            if model is FakeChapter:
                continue
            self.manager.clear_indexing_of_model(model)

        # note "topic" is gone since "post" is gone, due to relationships at the Django level
        new_topic = Topic.objects.get(pk=new_topic.pk)
        new_post = Post.objects.get(pk=new_post.pk)

        self.assertFalse(new_topic.es_already_indexed)
        self.assertTrue(new_topic.es_flagged)
        self.assertFalse(new_post.es_already_indexed)
        self.assertTrue(new_post.es_flagged)

        published = PublishedContent.objects.get(content_pk=tuto.pk)
        self.assertFalse(published.es_already_indexed)
        self.assertTrue(published.es_flagged)
Example #39
0
    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)
Example #40
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
Example #41
0
    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 !
Example #42
0
    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