def test_created(self): """Basic functionality of created filter.""" created_ds = datetime(2010, 6, 19, 12, 00) # on 6/19/2010 q1 = question(title=u"q1 audio", created=created_ds, save=True) q1.tags.add(u"desktop") ans = answer(question=q1, save=True) answervote(answer=ans, helpful=True, save=True) # on 6/21/2010 q2 = question(title=u"q2 audio", created=(created_ds + timedelta(days=2)), save=True) q2.tags.add(u"desktop") ans = answer(question=q2, save=True) answervote(answer=ans, helpful=True, save=True) self.refresh() qs = {"a": 1, "w": 2, "format": "json", "sortby": 2, "created_date": "06/20/2010"} qs["created"] = constants.INTERVAL_BEFORE response = self.client.get(reverse("search"), qs) results = json.loads(response.content)["results"] eq_([q1.get_absolute_url()], [r["url"] for r in results]) qs["created"] = constants.INTERVAL_AFTER response = self.client.get(reverse("search"), qs) results = json.loads(response.content)["results"] eq_([q2.get_absolute_url()], [r["url"] for r in results])
def test_reindex_users_that_contributed_yesterday(self): yesterday = datetime.now() - timedelta(days=1) # Verify for answers. u = user(username='******', save=True) profile(user=u) answer(creator=u, created=yesterday, save=True) reindex_users_that_contributed_yesterday() self.refresh() data = UserMappingType.search().query(username__match='answerer')[0] eq_(data['last_contribution_date'].date(), yesterday.date()) # Verify for edits. u = user(username='******', save=True) profile(user=u) revision(creator=u, created=yesterday, save=True) reindex_users_that_contributed_yesterday() self.refresh() data = UserMappingType.search().query(username__match='editor')[0] eq_(data['last_contribution_date'].date(), yesterday.date()) # Verify for reviews. u = user(username='******', save=True) profile(user=u) revision(reviewer=u, reviewed=yesterday, save=True) reindex_users_that_contributed_yesterday() self.refresh() data = UserMappingType.search().query(username__match='reviewer')[0] eq_(data['last_contribution_date'].date(), yesterday.date())
def test_responded(self): """Verify the responded queryset.""" # Create a question, there shouldn't be any responded yet. q = question(save=True) eq_(0, Question.objects.responded().count()) # Add an answer, there should be one responded. a = answer(question=q, save=True) eq_(1, Question.objects.responded().count()) # Add an answer by the creator, there should be none responded. a = answer(creator=q.creator, question=q, save=True) eq_(0, Question.objects.responded().count()) # Add another answer, there should be one responded. a = answer(question=q, save=True) eq_(1, Question.objects.responded().count()) # Lock it, there should be none responded. q.is_locked = True q.save() eq_(0, Question.objects.responded().count()) # Unlock it and mark solved, there should be none responded. q.is_locked = False q.solution = a q.save() eq_(0, Question.objects.responded().count())
def test_answer_badge(self): """Verify the Support Forum Badge is awarded properly.""" # Create the user and badge. year = date.today().year u = profile().user badge_template = QUESTIONS_BADGES['answer-badge'] b = badge( slug=badge_template['slug'].format(year=year), title=badge_template['title'].format(year=year), description=badge_template['description'].format(year=year), save=True) # Create 29 answers. q = question(save=True) answers = [] for i in range(28): answers.append(answer(question=q, creator=u)) Answer.objects.bulk_create(answers) # Create the 29th answer separately so the signals are triggered. answer(creator=u, save=True) # User should NOT have the badge yet. assert not b.is_awarded_to(u) # Create 1 more answer. answer(creator=u, save=True) # User should have the badge now. assert b.is_awarded_to(u)
def test_asker_replies_arent_a_contribution(self): """Verify that replies posted by the question creator aren't counted. If a user has 10 replies to their own question, they aren't counted as a contributor. """ # A user with 10 answers to own question. q = question(save=True) u = q.creator for x in range(10): answer(creator=u, question=q, save=True) # Create metric kinds and update metrics for tomorrow (today's # activity shows up tomorrow). self._make_contributor_metric_kinds() update_contributor_metrics(day=date.today() + timedelta(days=1)) r = self._get_api_result("kpi_active_contributors") eq_(r["objects"][0]["support_forum"], 0) # Change the question creator, now we should have 1 contributor. q.creator = user(save=True) q.save() cache.clear() # We need to clear the cache for new results. Metric.objects.all().delete() update_contributor_metrics(day=date.today() + timedelta(days=1)) r = self._get_api_result("kpi_active_contributors") eq_(r["objects"][0]["support_forum"], 1)
def test_creator_num_answers(self): a = answer(save=True) eq_(a.creator_num_answers, 1) answer(creator=a.creator, save=True) eq_(a.creator_num_answers, 2)
def test_last_answer_date(self): p = profile() u = p.user answer(creator=u, save=True) serializer = api.ProfileSerializer(instance=p) eq_(serializer.data['last_answer_date'], u.answers.last().created)
def test_it_works(self): u1 = profile().user u2 = profile().user a1 = answer(creator=u1, save=True) # noqa a2 = answer(creator=u1, save=True) a3 = answer(creator=u2, save=True) a1.question.solution = a1 a1.question.save() answervote(answer=a3, helpful=True, save=True) self.refresh() req = self.factory.get('/') data = self.api.get_data(req) eq_(data['count'], 2) eq_(data['results'][0]['user']['username'], u1.username) eq_(data['results'][0]['rank'], 1) eq_(data['results'][0]['answer_count'], 2) eq_(data['results'][0]['solution_count'], 1) eq_(data['results'][0]['helpful_vote_count'], 0) eq_(data['results'][0]['last_contribution_date'], a2.created.replace(microsecond=0)) eq_(data['results'][1]['user']['username'], u2.username) eq_(data['results'][1]['rank'], 2) eq_(data['results'][1]['answer_count'], 1) eq_(data['results'][1]['solution_count'], 0) eq_(data['results'][1]['helpful_vote_count'], 1) eq_(data['results'][1]['last_contribution_date'], a3.created.replace(microsecond=0))
def test_top_contributors_questions(self): firefox = product(slug='firefox', save=True) fxos = product(slug='firefox-os', save=True) a1 = answer(save=True) a1.question.products.add(firefox) a1.question.products.add(fxos) a2 = answer(creator=a1.creator, save=True) a3 = answer(save=True) a3.question.products.add(fxos) a4 = answer(created=datetime.now()-timedelta(days=91), save=True) self.refresh() # By default, we should only get 2 top contributors back. top = top_contributors_questions() eq_(2, len(top)) assert a4.creator_id not in [u['term'] for u in top] eq_(a1.creator_id, top[0]['term']) # Verify, filtering of Firefox questions only. top = top_contributors_questions(product=firefox.slug) eq_(1, len(top)) eq_(a1.creator_id, top[0]['term']) top = top_contributors_questions(product=fxos.slug) eq_(2, len(top))
def test_created(self): """Basic functionality of created filter.""" created_ds = datetime(2010, 6, 19, 12, 00) # on 6/19/2010 q1 = question(title=u'q1 audio', created=created_ds, save=True) q1.tags.add(u'desktop') ans = answer(question=q1, save=True) answervote(answer=ans, helpful=True, save=True) # on 6/21/2010 q2 = question(title=u'q2 audio', created=(created_ds + timedelta(days=2)), save=True) q2.tags.add(u'desktop') ans = answer(question=q2, save=True) answervote(answer=ans, helpful=True, save=True) self.refresh() qs = {'a': 1, 'w': 2, 'format': 'json', 'sortby': 2, 'created_date': '06/20/2010'} qs['created'] = constants.INTERVAL_BEFORE response = self.client.get(reverse('search'), qs) results = json.loads(response.content)['results'] eq_([q1.get_absolute_url()], [r['url'] for r in results]) qs['created'] = constants.INTERVAL_AFTER response = self.client.get(reverse('search'), qs) results = json.loads(response.content)['results'] eq_([q2.get_absolute_url()], [r['url'] for r in results])
def test_recent_counts_with_filter(self): """Verify that recent_asked_count and recent_unanswered_count respect filters passed.""" now = datetime.now() question(created=now, locale='en-US', save=True) q = question(created=now, locale='en-US', save=True) answer(question=q, save=True) question(created=now, locale='pt-BR', save=True) question(created=now, locale='pt-BR', save=True) q = question(created=now, locale='pt-BR', save=True) answer(question=q, save=True) # 5 asked recently, 3 are unanswered eq_(5, Question.recent_asked_count()) eq_(3, Question.recent_unanswered_count()) # check english (2 asked, 1 unanswered) locale_filter = Q(locale='en-US') eq_(2, Question.recent_asked_count(locale_filter)) eq_(1, Question.recent_unanswered_count(locale_filter)) # check pt-BR (3 asked, 2 unanswered) locale_filter = Q(locale='pt-BR') eq_(3, Question.recent_asked_count(locale_filter)) eq_(2, Question.recent_unanswered_count(locale_filter))
def test_delete_updates_pages(self): a1 = answer(save=True) a2 = answer(question=a1.question, save=True) answer(question=a1.question, save=True) a1.page = 7 a1.save() a2.delete() a3 = Answer.objects.filter(question=a1.question)[0] assert a3.page == 1, "Page was %s" % a3.page
def test_last_contribution_date(self): """Verify the last_contribution_date field works properly.""" u = user(username='******', save=True) p = profile(user=u) self.refresh() data = UserMappingType.search().query( username__match='satdav').values_dict()[0] assert not data['last_contribution_date'] # Add a AoA reply. It should be the last contribution. d = datetime(2014, 1, 1) reply(user=u, created=d, save=True) p.save() # we need to resave the profile to force a reindex self.refresh() data = UserMappingType.search().query( username__match='satdav').values_dict()[0] eq_(data['last_contribution_date'], d) # Add a Support Forum answer. It should be the last contribution. d = datetime(2014, 1, 2) answer(creator=u, created=d, save=True) p.save() # we need to resave the profile to force a reindex self.refresh() data = UserMappingType.search().query( username__match='satdav').values_dict()[0] eq_(data['last_contribution_date'], d) # Add a Revision edit. It should be the last contribution. d = datetime(2014, 1, 3) revision(creator=u, created=d, save=True) p.save() # we need to resave the profile to force a reindex self.refresh() data = UserMappingType.search().query( username__match='satdav').values_dict()[0] eq_(data['last_contribution_date'], d) # Add a Revision review. It should be the last contribution. d = datetime(2014, 1, 4) revision(reviewer=u, reviewed=d, save=True) p.save() # we need to resave the profile to force a reindex self.refresh() data = UserMappingType.search().query( username__match='satdav').values_dict()[0] eq_(data['last_contribution_date'], d)
def test_counts(self): p = profile() u = p.user q = question(creator=u, save=True) answer(creator=u, save=True) q.solution = answer(question=q, creator=u, save=True) q.save() serializer = api.ProfileSerializer(instance=p) eq_(serializer.data['question_count'], 1) eq_(serializer.data['answer_count'], 2) eq_(serializer.data['solution_count'], 1)
def test_top_questions(self): a1 = answer(save=True) a2 = answer(save=True) self.refresh() response = self.client.get(urlparams( reverse('community.top_contributors', args=['questions']))) eq_(200, response.status_code) doc = pq(response.content) eq_(2, len(doc('li.results-user'))) assert a1.creator.username in response.content assert a2.creator.username in response.content
def test_user_num_answers(self): u = user(save=True) q = question(save=True) eq_(user_num_answers(u), 0) a1 = answer(creator=u, question=q, save=True) eq_(user_num_answers(u), 1) a2 = answer(creator=u, question=q, save=True) eq_(user_num_answers(u), 2) a1.delete() eq_(user_num_answers(u), 1) a2.delete() eq_(user_num_answers(u), 0)
def test_top_contributors_questions(self): a1 = answer(save=True) a2 = answer(creator=a1.creator, save=True) a3 = answer(save=True) a4 = answer(created=datetime.now()-timedelta(days=91), save=True) self.refresh() # By default, we should only get 2 top contributors back. top = top_contributors_questions() eq_(2, len(top)) assert a4.creator_id not in [u['term'] for u in top] eq_(a1.creator_id, top[0]['term'])
def test_recent_counts(self): """Verify recent_asked_count and recent unanswered count.""" # create a question for each of past 4 days now = datetime.now() question(created=now, save=True) question(created=now - timedelta(hours=12), save=True, is_locked=True) q = question(created=now - timedelta(hours=23), save=True) answer(question=q, save=True) # 25 hours instead of 24 to avoid random test fails. question(created=now - timedelta(hours=25), save=True) # Only 3 are recent from last 72 hours, 1 has an answer. eq_(3, Question.recent_asked_count()) eq_(1, Question.recent_unanswered_count())
def test_ordering(self): a1 = answer(save=True) a2 = answer(save=True) res = self.client.get(reverse('answer-list')) eq_(res.data['results'][0]['id'], a2.id) eq_(res.data['results'][1]['id'], a1.id) res = self.client.get(reverse('answer-list') + '?ordering=id') eq_(res.data['results'][0]['id'], a1.id) eq_(res.data['results'][1]['id'], a2.id) res = self.client.get(reverse('answer-list') + '?ordering=-id') eq_(res.data['results'][0]['id'], a2.id) eq_(res.data['results'][1]['id'], a1.id)
def test_helpfulness(self): p = profile() u = p.user a1 = answer(creator=u, save=True) a2 = answer(creator=u, save=True) answervote(answer=a1, helpful=True, save=True) answervote(answer=a2, helpful=True, save=True) answervote(answer=a2, helpful=True, save=True) # Some red herrings. answervote(creator=u, save=True) answervote(answer=a1, helpful=False, save=True) serializer = api.ProfileSerializer(instance=p) eq_(serializer.data['helpfulness'], 3)
def test_deactivate_and_flag_spam(self): self.client.login(username=self.u.username, password='******') add_permission(self.u, Profile, 'deactivate_users') # Verify content is flagged as spam when requested. p = profile() answer(creator=p.user, save=True) question(creator=p.user, save=True) url = reverse('users.deactivate-spam', locale='en-US') res = self.client.post(url, {'user_id': p.user.id}) eq_(302, res.status_code) eq_(1, Question.objects.filter(creator=p.user, is_spam=True).count()) eq_(0, Question.objects.filter(creator=p.user, is_spam=False).count()) eq_(1, Answer.objects.filter(creator=p.user, is_spam=True).count()) eq_(0, Answer.objects.filter(creator=p.user, is_spam=False).count())
def test_asked_by(self): """Check several author values, including test for (anon)""" author_vals = ( ('DoesNotExist', 0), ('jsocol', 2), ('pcraciunoiu', 2), ) # Set up all the question data---creats users, creates the # questions, shove it all in the index, then query it and see # what happens. for name, number in author_vals: u = user(username=name, save=True) for i in range(number): ques = question(title=u'audio', creator=u, save=True) ques.tags.add(u'desktop') ans = answer(question=ques, save=True) answervote(answer=ans, helpful=True, save=True) self.refresh() qs = {'a': 1, 'w': 2, 'format': 'json'} for author, total in author_vals: qs.update({'asked_by': author}) response = self.client.get(reverse('search'), qs) eq_(total, json.loads(response.content)['total'])
def test_solution_notification_deleted(self, get_current): """Calling QuestionSolvedEvent.fire() should not query the questions_question table. This test attempts to simulate the replication lag presumed to cause bug 585029. """ get_current.return_value.domain = 'testserver' a = answer(save=True) q = a.question q.solution = a q.save() a_user = a.creator QuestionSolvedEvent.notify(a_user, q) event = QuestionSolvedEvent(a) # Delete the question, pretend it hasn't been replicated yet Question.objects.get(pk=q.pk).delete() event.fire(exclude=q.creator) # There should be a reply notification and a solved notification. eq_(2, len(mail.outbox)) eq_('Solution found to Firefox Help question', mail.outbox[1].subject)
def test_is_solved_property(self): a = answer(save=True) q = a.question assert not q.is_solved q.solution = a q.save() assert q.is_solved
def test_suggestions(self, get_current): """Suggestions API is well-formatted.""" get_current.return_value.domain = 'testserver' doc = document(title=u'doc1 audio', locale=u'en-US', is_archived=False, save=True) revision(document=doc, summary=u'audio', content=u'audio', is_approved=True, save=True) ques = question(title=u'q1 audio', save=True) ques.tags.add(u'desktop') ans = answer(question=ques, save=True) answervote(answer=ans, helpful=True, save=True) self.refresh() response = self.client.get(reverse('search.suggestions', locale='en-US'), {'q': 'audio'}) eq_(200, response.status_code) eq_('application/x-suggestions+json', response['content-type']) results = json.loads(response.content) eq_('audio', results[0]) eq_(2, len(results[1])) eq_(0, len(results[2])) eq_(2, len(results[3]))
def test_default_only_shows_wiki_and_questions(self): """Tests that the default search doesn't show forums This verifies that we're only showing documents of the type that should be shown and that the filters on model are working correctly. Bug #767394 """ p = product(slug=u'desktop', save=True) ques = question(title=u'audio', save=True) ques.products.add(p) ans = answer(question=ques, content=u'volume', save=True) answervote(answer=ans, helpful=True, save=True) doc = document(title=u'audio', locale=u'en-US', category=10, save=True) doc.products.add(p) revision(document=doc, is_approved=True, save=True) thread1 = thread(title=u'audio', save=True) post(thread=thread1, save=True) self.refresh() response = self.client.get(reverse('search'), { 'q': 'audio', 'format': 'json'}) eq_(200, response.status_code) content = json.loads(response.content) eq_(content['total'], 2)
def test_solution_is_readonly(self): q = question(save=True) a = answer(question=q, save=True) self.data['solution'] = a.id serializer = api.QuestionSerializer(context=self.context, data=self.data, instance=q) serializer.save() eq_(q.solution, None)
def test_bleaching(self): """Tests whether answer content is bleached.""" a = answer(content=u'<unbleached>Cupcakes are the best</unbleached>', save=True) url = reverse('answer-detail', args=[a.id]) res = self.client.get(url) eq_(res.status_code, 200) assert '<unbleached>' not in res.data['content']
def test_product_facets(self): """Verify the facet counts on the results page.""" # Create products, questions and documents. p1 = product(title='Firefox', slug='firefox', save=True) p2 = product(title='Firefox for mobile', slug='mobile', save=True) ques = question(title=u'audio', save=True) ques.products.add(p1) ans = answer(question=ques, content=u'volume', save=True) answervote(answer=ans, helpful=True, save=True) doc = document(title=u'audio', locale=u'en-US', category=10, save=True) doc.products.add(p1) doc.products.add(p2) revision(document=doc, is_approved=True, save=True) self.refresh() # There should be 2 total results, 2 "firefox" results and # 1 "mobile" result. response = self.client.get(reverse('search'), {'q': 'audio'}) eq_(200, response.status_code) doc = pq(response.content) eq_('Found 2 results for audio in English', doc('h2').text()) facet_text = doc('#product-filter').text() assert 'Firefox (2)' in facet_text assert 'Firefox for mobile (1)' in facet_text
def _make_question(self, solved=True, **kwargs): defaults = { 'title': 'Login to website comments disabled ' + str(time.time()), 'content': """ readersupportednews.org, sends me emails with a list of articles to read. The links to the articles work as normal, except that I cannot login from the linked article - as required - to send my comments. I see a javascript activity statement at the bottom left corner of my screen while the left button is depressed on the Login button. it is gone when I release the left button, but no results. I have the latest (7) version of java enabled, on an XP box. Why this inability to login to this website commentary? """, 'save': True, } defaults.update(kwargs) q = question(**defaults) if solved: a = answer(question=q, save=True) q.solution = a # Trigger a reindex for the question. q.save() return q
def test_delete_last_answer_of_question(self): """Deleting the last_answer of a Question should update the question. """ yesterday = datetime.now() - timedelta(days=1) q = answer(created=yesterday, save=True).question last_answer = q.last_answer # add a new answer and verify last_answer updated a = answer(question=q, content='Test Answer', save=True) q = Question.objects.get(pk=q.id) eq_(q.last_answer.id, a.id) # delete the answer and last_answer should go back to previous value a.delete() q = Question.objects.get(pk=q.id) eq_(q.last_answer.id, last_answer.id) eq_(Answer.objects.filter(pk=a.id).count(), 0)
def test_questions(self): """Test questions API call.""" # A question with a solution: a = answer(save=True) a.question.solution = a a.question.save() # A question with an answer: answer(save=True) # A question without answers: question(save=True) # A locked question that shouldn't be counted for anything question(is_locked=True, save=True) r = self._get_api_result('api.kpi.questions') eq_(r['objects'][0]['solved'], 1) eq_(r['objects'][0]['responded_24'], 2) eq_(r['objects'][0]['responded_72'], 2) eq_(r['objects'][0]['questions'], 3)
def test_fire_on_solution(self, fire): """The event also fires when an answer is marked as a solution.""" a = answer(save=True) q = a.question self.client.login(username=q.creator, password='******') post(self.client, 'questions.solve', args=[q.id, a.id]) assert fire.called
def test_update_page_task(self): a = answer(save=True) a.page = 4 a.save() a = Answer.objects.get(pk=a.id) assert a.page == 4 update_answer_pages(a.question) a = Answer.objects.get(pk=a.id) assert a.page == 1
def test_follow(self): a = answer(save=True) u = profile().user self.client.force_authenticate(user=u) eq_(Follow.objects.filter(user=u).count(), 0) # pre-condition res = self.client.post(reverse('answer-follow', args=[a.id])) eq_(res.status_code, 204) f = Follow.objects.get(user=u) eq_(f.follow_object, a) eq_(f.actor_only, False)
def test_solution_is_readonly(self): q = question(save=True) a = answer(question=q, save=True) self.data['solution'] = a.id serializer = api.QuestionSerializer(context=self.context, data=self.data, instance=q) serializer.is_valid(raise_exception=True) serializer.save() eq_(q.solution, None)
def test_filter_solved_by(self): q1 = question(save=True) a1 = answer(question=q1, save=True) q1.solution = a1 q1.save() q2 = question(save=True) answer(question=q2, creator=a1.creator, save=True) q3 = question(save=True) a3 = answer(question=q3, save=True) q3.solution = a3 q3.save() qs = self.filter_instance.filter_solved_by(self.queryset, a1.creator.username) eq_(list(qs), [q1]) qs = self.filter_instance.filter_solved_by(self.queryset, a3.creator.username) eq_(list(qs), [q3])
def setUp(self): super(FlaggedQueueTestCase, self).setUp() q = question(creator=user(save=True), save=True) self.answer = answer(question=q, creator=user(save=True), save=True) self.flagger = user(save=True) u = user(save=True) add_permission(u, FlaggedObject, 'can_moderate') self.client.login(username=u.username, password='******')
def test_user_num_solutions(self): u = user(save=True) q1 = question(save=True) q2 = question(save=True) a1 = answer(creator=u, question=q1, save=True) a2 = answer(creator=u, question=q2, save=True) eq_(user_num_solutions(u), 0) q1.solution = a1 q1.save() eq_(user_num_solutions(u), 1) q2.solution = a2 q2.save() eq_(user_num_solutions(u), 2) q1.solution = None q1.save() eq_(user_num_solutions(u), 1) a2.delete() eq_(user_num_solutions(u), 0)
def test_question_solved_makes_action(self): """When an answer is marked as the solution to a question, an Action should be created.""" ans = answer(save=True) Action.objects.all().delete() ans.question.set_solution(ans, ans.question.creator) act = Action.objects.action_object(ans).get() eq_(act.actor, ans.question.creator) eq_(act.verb, 'marked as a solution') eq_(act.target, ans.question)
def test_helpful_double_vote(self): a = answer(save=True) u = profile().user answervote(answer=a, creator=u, save=True) self.client.force_authenticate(user=u) res = self.client.post(reverse('answer-helpful', args=[a.id])) eq_(res.status_code, 409) # It's 1, not 0, because one was created above. The failure cause is # if the number of votes is 2, one from above and one from the api call. eq_(Answer.objects.get(id=a.id).num_votes, 1)
def test_with_votes(self): a = answer(save=True) answervote(answer=a, helpful=True, save=True) answervote(answer=a, helpful=True, save=True) answervote(answer=a, helpful=False, save=True) answervote(save=True) serializer = api.AnswerSerializer(instance=a) eq_(serializer.data['num_helpful_votes'], 2) eq_(serializer.data['num_unhelpful_votes'], 1)
def test_solve(self): q = question(save=True) a = answer(question=q, save=True) self.client.force_authenticate(user=q.creator) res = self.client.post(reverse('question-solve', args=[q.id]), data={'answer': a.id}) eq_(res.status_code, 204) q = Question.objects.get(id=q.id) eq_(q.solution, a)
def test_page_size(self): u1 = profile().user u2 = profile().user q1 = question(save=True) answer(question=q1, creator=u1, save=True) q2 = question(save=True) answer(question=q2, creator=u2, save=True) self.refresh() req = self.factory.get('/', {'page_size': 2}) data = self.api.get_data(req) eq_(data['count'], 2) eq_(len(data['results']), 2) req = self.factory.get('/', {'page_size': 1}) data = self.api.get_data(req) eq_(data['count'], 2) eq_(len(data['results']), 1)
def test_case_insensitive_search(self): """Ensure the default searcher is case insensitive.""" answervote(answer=answer(question=question(title='lolrus', content='I am the lolrus.', save=True), save=True), helpful=True).save() self.refresh() result = QuestionMappingType.search().query( question_title__match='LOLRUS', question_content__match='LOLRUS') assert result.count() > 0
def setUp(self): super(TestQuestionUpdates, self).setUp() self.u = user(is_superuser=True, save=True) self.client.login(username=self.u.username, password='******') self.q = question(updated=datetime(2012, 7, 9, 9, 0, 0), save=True) self.a = answer(question=self.q, save=True) # Get the question from the database so we have a consistent level of # precision during the test. self.q = Question.objects.get(pk=self.q.id)
def test_content_parsed_with_locale(self): """Make sure links to localized articles work.""" rev = translated_revision(locale='es', is_approved=True, save=True) doc = rev.document doc.title = u'Un mejor título' doc.save() q = question(locale='es', save=True) a = answer(question=q, content='[[%s]]' % doc.title, save=True) assert 'es/kb/%s' % doc.slug in a.content_parsed
def test_answer_spam_is_unindexed(self): search = QuestionMappingType.search() a = answer(content=u'I am spam', save=True) self.refresh() eq_(search.query(question_answer_content__match='spam').count(), 1) a.is_spam = True a.save() self.refresh() eq_(search.query(question_answer_content__match='spam').count(), 0)
def test_questions_by_product(self): """Test product filtering of questions API call.""" firefox_os = product(slug='firefox-os', save=True) firefox = product(slug='firefox', save=True) # A Firefox OS question with a solution: q = question(product=firefox_os, save=True) a = answer(question=q, save=True) q.solution = a q.save() # A Firefox OS question with an answer: q = question(product=firefox_os, save=True) answer(question=q, save=True) # A Firefox OS question without answers: q = question(product=firefox_os, save=True) # A Firefox question without answers: q = question(product=firefox, locale='pt-BR', save=True) # Verify no product filtering: r = self._get_api_result('api.kpi.questions') eq_(r['objects'][0]['solved'], 1) eq_(r['objects'][0]['responded_24'], 2) eq_(r['objects'][0]['responded_72'], 2) eq_(r['objects'][0]['questions'], 4) # Verify product=firefox-os r = self._get_api_result('api.kpi.questions', product='firefox-os') eq_(r['objects'][0]['solved'], 1) eq_(r['objects'][0]['responded_24'], 2) eq_(r['objects'][0]['responded_72'], 2) eq_(r['objects'][0]['questions'], 3) # Verify product=firefox r = self._get_api_result('api.kpi.questions', product='firefox') eq_(r['objects'][0]['questions'], 1) assert 'solved' not in r['objects'][0] assert 'responded_24' not in r['objects'][0] assert 'responded_72' not in r['objects'][0]
def test_add_and_delete(self): """Adding an answer should add it to the index. Deleting should delete it. """ a = answer(save=True) self.refresh() eq_(AnswerMetricsMappingType.search().count(), 1) a.delete() self.refresh() eq_(AnswerMetricsMappingType.search().count(), 0)
def test_filter_is_solved(self): q1 = question(save=True) a1 = answer(question=q1, save=True) q1.solution = a1 q1.save() q2 = question(save=True) res = self.filter_instance.filter_is_solved(self.queryset, True) eq_(list(res), [q1]) res = self.filter_instance.filter_is_solved(self.queryset, False) eq_(list(res), [q2])
def test_filter_involved(self): q1 = question(save=True) a1 = answer(question=q1, save=True) q2 = question(creator=a1.creator, save=True) res = self.filter_instance.filter_involved(self.queryset, q1.creator.username) eq_(list(res), [q1]) res = self.filter_instance.filter_involved(self.queryset, q2.creator.username) # The filter does not have a strong order. res = sorted(res, key=lambda q: q.id) eq_(res, [q1, q2])
def test_answer_vote_limit(self): """Test that an anonymous user's votes are ignored after 10 answer votes.""" q = question(save=True) answers = [answer(question=q, save=True) for _ in range(11)] # The rate limit is 10 per day. So make 10 requests. (0 through 9) for i in range(10): self._check_answer_vote(q, answers[i], False) # Now make another, it should fail. self._check_answer_vote(q, answers[10], True)
def test_default_only_shows_wiki_and_questions(self): """Tests that the default search doesn't show forums This verifies that we're only showing documents of the type that should be shown and that the filters on model are working correctly. Bug #767394 """ p = product(slug=u'desktop', save=True) ques = question(title=u'audio', save=True) ques.products.add(p) ans = answer(question=ques, content=u'volume', save=True) answervote(answer=ans, helpful=True, save=True) doc = document(title=u'audio', locale=u'en-US', category=10, save=True) doc.products.add(p) revision(document=doc, is_approved=True, save=True) thread1 = thread(title=u'audio', save=True) post(thread=thread1, save=True) self.refresh() response = self.client.get(reverse('search'), { 'q': 'audio', 'format': 'json' }) eq_(200, response.status_code) content = json.loads(response.content) eq_(content['total'], 2) # Archive the article and question. They should no longer appear # in default search results. ques.is_archived = True ques.save() doc.is_archived = True doc.save() self.refresh() response = self.client.get(reverse('search'), { 'q': 'audio', 'format': 'json' }) eq_(200, response.status_code) content = json.loads(response.content) eq_(content['total'], 0)
def test_empty_pages(self): """Tests requesting a page that has no results""" ques = question(title=u'audio', save=True) ques.tags.add(u'desktop') ans = answer(question=ques, content=u'volume', save=True) answervote(answer=ans, helpful=True, save=True) self.refresh() qs = {'q': 'audio', 'page': 81} response = self.client.get(reverse('search'), qs) eq_(200, response.status_code)
def test_top_contributors(self): """Verify the top contributors appear.""" d = document(locale='en-US', save=True) revision(document=d, save=True) d = document(locale='es', save=True) revision(document=d, save=True) revision(document=d, save=True) answer(save=True) answer(save=True) answer(save=True) reply(user=user(save=True), save=True) reply(user=user(save=True), save=True) reply(user=user(save=True), save=True) reply(user=user(save=True), save=True) for u in User.objects.all(): profile(user=u) self.refresh() response = self.client.get(urlparams(reverse('community.home'))) eq_(response.status_code, 200) doc = pq(response.content) eq_(1, len(doc('ul.kb > li'))) eq_(2, len(doc('ul.l10n > li'))) eq_(3, len(doc('ul.questions > li'))) eq_(4, len(doc('ul.army-of-awesome > li')))
def test_delete_solution_of_question(self): """Deleting the solution of a Question should update the question. """ # set a solution to the question q = answer(save=True).question solution = q.last_answer q.solution = solution q.save() # delete the solution and question.solution should go back to None solution.delete() q = Question.objects.get(pk=q.id) eq_(q.solution, None)
def test_reindex_users_that_contributed_yesterday(self): yesterday = datetime.now() - timedelta(days=1) # Verify for answers. u = user(username='******', save=True) p = profile(user=u) answer(creator=u, created=yesterday, save=True) reindex_users_that_contributed_yesterday() self.refresh() data = UserMappingType.search().query( username__match='answerer').values_dict()[0] eq_(data['last_contribution_date'].date(), yesterday.date()) # Verify for edits. u = user(username='******', save=True) p = profile(user=u) revision(creator=u, created=yesterday, save=True) reindex_users_that_contributed_yesterday() self.refresh() data = UserMappingType.search().query( username__match='editor').values_dict()[0] eq_(data['last_contribution_date'].date(), yesterday.date()) # Verify for reviews. u = user(username='******', save=True) p = profile(user=u) revision(reviewer=u, reviewed=yesterday, save=True) reindex_users_that_contributed_yesterday() self.refresh() data = UserMappingType.search().query( username__match='reviewer').values_dict()[0] eq_(data['last_contribution_date'].date(), yesterday.date())
def test_question_is_reindexed_on_username_change(self): search = QuestionMappingType.search() u = user(username='******', save=True) question(creator=u, title=u'Hello', save=True) answer(creator=u, content=u'I love you', save=True) self.refresh() eq_( search.query(question_title__match='hello')[0]['question_creator'], u'dexter') query = search.query(question_answer_content__match='love') eq_(query[0]['question_answer_creator'], [u'dexter']) # Change the username and verify the index. u.username = '******' u.save() self.refresh() eq_( search.query(question_title__match='hello')[0]['question_creator'], u'walter') query = search.query(question_answer_content__match='love') eq_(query[0]['question_answer_creator'], [u'walter'])
def test_delete_answer_removes_flag(self): """Deleting an answer also removes the flags on that answer.""" q = question(title='Test Question', content='Lorem Ipsum Dolor', save=True) a = answer(question=q, content='Test Answer', save=True) u = user(save=True) FlaggedObject.objects.create( status=0, content_object=a, reason='language', creator_id=u.id) eq_(1, FlaggedObject.objects.count()) a.delete() eq_(0, FlaggedObject.objects.count())