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.client.force_login(self.user) 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.client.force_login(self.staff) 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_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 __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(f" Topic {topic_index + 1}/{nb_topics} \tPost {post_index + 1}/{nb_posts} \r") sys.stdout.flush() tps2 = time.time() cli.stdout.write(f"\nFait en {tps2 - tps1} sec")
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_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_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.client.force_login(self.staff) 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_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_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_unregister(self): """ To test that unregistering user is working. """ # test not logged user can't unregister. self.client.logout() result = self.client.post(reverse("member-unregister"), follow=False) self.assertEqual(result.status_code, 302) # test logged user can unregister. user = ProfileFactory() self.client.force_login(user.user) result = self.client.post(reverse("member-unregister"), follow=False) self.assertEqual(result.status_code, 302) self.assertEqual(User.objects.filter(username=user.user.username).count(), 0) # Attach a user at tutorials, articles, topics and private topics. After that, # unregister this user and check that he is well removed in all contents. user = ProfileFactory() user2 = ProfileFactory() alone_gallery = GalleryFactory() UserGalleryFactory(gallery=alone_gallery, user=user.user) shared_gallery = GalleryFactory() UserGalleryFactory(gallery=shared_gallery, user=user.user) UserGalleryFactory(gallery=shared_gallery, user=user2.user) # first case : a published tutorial with only one author published_tutorial_alone = PublishedContentFactory(type="TUTORIAL") published_tutorial_alone.authors.add(user.user) published_tutorial_alone.save() # second case : a published tutorial with two authors published_tutorial_2 = PublishedContentFactory(type="TUTORIAL") published_tutorial_2.authors.add(user.user) published_tutorial_2.authors.add(user2.user) published_tutorial_2.save() # third case : a private tutorial with only one author writing_tutorial_alone = PublishableContentFactory(type="TUTORIAL") writing_tutorial_alone.authors.add(user.user) writing_tutorial_alone.save() writing_tutorial_alone_galler_path = writing_tutorial_alone.gallery.get_gallery_path() # fourth case : a private tutorial with at least two authors writing_tutorial_2 = PublishableContentFactory(type="TUTORIAL") writing_tutorial_2.authors.add(user.user) writing_tutorial_2.authors.add(user2.user) writing_tutorial_2.save() self.client.force_login(self.staff) # same thing for articles published_article_alone = PublishedContentFactory(type="ARTICLE") published_article_alone.authors.add(user.user) published_article_alone.save() published_article_2 = PublishedContentFactory(type="ARTICLE") published_article_2.authors.add(user.user) published_article_2.authors.add(user2.user) published_article_2.save() writing_article_alone = PublishableContentFactory(type="ARTICLE") writing_article_alone.authors.add(user.user) writing_article_alone.save() writing_article_2 = PublishableContentFactory(type="ARTICLE") writing_article_2.authors.add(user.user) writing_article_2.authors.add(user2.user) writing_article_2.save() # beta content beta_forum = ForumFactory(category=ForumCategoryFactory()) beta_content = BetaContentFactory(author_list=[user.user], forum=beta_forum) beta_content_2 = BetaContentFactory(author_list=[user.user, user2.user], forum=beta_forum) # about posts and topics authored_topic = TopicFactory(author=user.user, forum=self.forum11, solved_by=user.user) answered_topic = TopicFactory(author=user2.user, forum=self.forum11) PostFactory(topic=answered_topic, author=user.user, position=2) edited_answer = PostFactory(topic=answered_topic, author=user.user, position=3) edited_answer.editor = user.user edited_answer.save() upvoted_answer = PostFactory(topic=answered_topic, author=user2.user, position=4) upvoted_answer.like += 1 upvoted_answer.save() CommentVote.objects.create(user=user.user, comment=upvoted_answer, positive=True) private_topic = PrivateTopicFactory(author=user.user) private_topic.participants.add(user2.user) private_topic.save() PrivatePostFactory(author=user.user, privatetopic=private_topic, position_in_topic=1) # add API key self.assertEqual(Application.objects.count(), 0) self.assertEqual(AccessToken.objects.count(), 0) api_application = Application() api_application.client_id = "foobar" api_application.user = user.user api_application.client_type = "confidential" api_application.authorization_grant_type = "password" api_application.client_secret = "42" api_application.save() token = AccessToken() token.user = user.user token.token = "r@d0m" token.application = api_application token.expires = datetime.now() token.save() self.assertEqual(Application.objects.count(), 1) self.assertEqual(AccessToken.objects.count(), 1) # add a karma note and a sanction with this user note = KarmaNote(moderator=user.user, user=user2.user, note="Good!", karma=5) note.save() ban = Ban(moderator=user.user, user=user2.user, type="Ban définitif", note="Test") ban.save() # login and unregister: self.client.force_login(user.user) result = self.client.post(reverse("member-unregister"), follow=False) self.assertEqual(result.status_code, 302) # check that the bot have taken authorship of tutorial: self.assertEqual(published_tutorial_alone.authors.count(), 1) self.assertEqual( published_tutorial_alone.authors.first().username, settings.ZDS_APP["member"]["external_account"] ) self.assertFalse(os.path.exists(writing_tutorial_alone_galler_path)) self.assertEqual(published_tutorial_2.authors.count(), 1) self.assertEqual( published_tutorial_2.authors.filter(username=settings.ZDS_APP["member"]["external_account"]).count(), 0 ) # check that published tutorials remain published and accessible self.assertIsNotNone(published_tutorial_2.public_version.get_prod_path()) self.assertTrue(os.path.exists(published_tutorial_2.public_version.get_prod_path())) self.assertIsNotNone(published_tutorial_alone.public_version.get_prod_path()) self.assertTrue(os.path.exists(published_tutorial_alone.public_version.get_prod_path())) self.assertEqual( self.client.get( reverse("tutorial:view", args=[published_tutorial_alone.pk, published_tutorial_alone.slug]), follow=False, ).status_code, 200, ) self.assertEqual( self.client.get( reverse("tutorial:view", args=[published_tutorial_2.pk, published_tutorial_2.slug]), follow=False ).status_code, 200, ) # test that published articles remain accessible self.assertTrue(os.path.exists(published_article_alone.public_version.get_prod_path())) self.assertEqual( self.client.get( reverse("article:view", args=[published_article_alone.pk, published_article_alone.slug]), follow=True ).status_code, 200, ) self.assertEqual( self.client.get( reverse("article:view", args=[published_article_2.pk, published_article_2.slug]), follow=True ).status_code, 200, ) # check that the tutorial for which the author was alone does not exists anymore self.assertEqual(PublishableContent.objects.filter(pk=writing_tutorial_alone.pk).count(), 0) self.assertFalse(os.path.exists(writing_tutorial_alone.get_repo_path())) # check that bot haven't take the authorship of the tuto with more than one author self.assertEqual(writing_tutorial_2.authors.count(), 1) self.assertEqual( writing_tutorial_2.authors.filter(username=settings.ZDS_APP["member"]["external_account"]).count(), 0 ) # authorship for the article for which user was the only author self.assertEqual(published_article_alone.authors.count(), 1) self.assertEqual( published_article_alone.authors.first().username, settings.ZDS_APP["member"]["external_account"] ) self.assertEqual(published_article_2.authors.count(), 1) self.assertEqual(PublishableContent.objects.filter(pk=writing_article_alone.pk).count(), 0) self.assertFalse(os.path.exists(writing_article_alone.get_repo_path())) # not bot if another author: self.assertEqual( published_article_2.authors.filter(username=settings.ZDS_APP["member"]["external_account"]).count(), 0 ) self.assertEqual(writing_article_2.authors.count(), 1) self.assertEqual( writing_article_2.authors.filter(username=settings.ZDS_APP["member"]["external_account"]).count(), 0 ) # topics, gallery and PMs: self.assertEqual(Topic.objects.filter(author__username=user.user.username).count(), 0) self.assertEqual(Topic.objects.filter(solved_by=user.user).count(), 0) self.assertEqual(Topic.objects.filter(solved_by=self.anonymous).count(), 1) self.assertEqual(Post.objects.filter(author__username=user.user.username).count(), 0) self.assertEqual(Post.objects.filter(editor__username=user.user.username).count(), 0) self.assertEqual(PrivatePost.objects.filter(author__username=user.user.username).count(), 0) self.assertEqual(PrivateTopic.objects.filter(author__username=user.user.username).count(), 0) self.assertIsNotNone(Topic.objects.get(pk=authored_topic.pk)) self.assertIsNotNone(PrivateTopic.objects.get(pk=private_topic.pk)) self.assertIsNotNone(Gallery.objects.get(pk=alone_gallery.pk)) self.assertEqual(alone_gallery.get_linked_users().count(), 1) self.assertEqual(shared_gallery.get_linked_users().count(), 1) self.assertEqual(UserGallery.objects.filter(user=user.user).count(), 0) self.assertEqual(CommentVote.objects.filter(user=user.user, positive=True).count(), 0) self.assertEqual(Post.objects.filter(pk=upvoted_answer.id).first().like, 0) # zep 12, published contents and beta self.assertIsNotNone(PublishedContent.objects.filter(content__pk=published_tutorial_alone.pk).first()) self.assertIsNotNone(PublishedContent.objects.filter(content__pk=published_tutorial_2.pk).first()) self.assertTrue(Topic.objects.get(pk=beta_content.beta_topic.pk).is_locked) self.assertFalse(Topic.objects.get(pk=beta_content_2.beta_topic.pk).is_locked) # check API self.assertEqual(Application.objects.count(), 0) self.assertEqual(AccessToken.objects.count(), 0) # check that the karma note and the sanction were kept self.assertTrue(KarmaNote.objects.filter(pk=note.pk).exists()) self.assertTrue(Ban.objects.filter(pk=ban.pk).exists())
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.client.force_login(profile.user) # 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 previous_limit = settings.VOTES_ID_LIMIT 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"]) settings.VOTES_ID_LIMIT = previous_limit
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