Example #1
0
    def test_question_topics(self):
        """Search questions for topics."""
        t1 = old_topic(slug="doesnotexist", save=True)
        t2 = old_topic(slug="cookies", save=True)
        t3 = old_topic(slug="sync", save=True)

        # TODO: This is a hack until we move questions to new topics.
        # We need to create these for the search form validation.
        topic(slug="doesnotexist", save=True)
        topic(slug="cookies", save=True)
        topic(slug="sync", save=True)

        q = question(save=True)
        q.topics.add(t2)
        q = question(save=True)
        q.topics.add(t2)
        q.topics.add(t3)

        self.refresh()

        topic_vals = ((t1.slug, 0), (t2.slug, 2), (t3.slug, 1), ([t2.slug, t3.slug], 1))

        qs = {"a": 1, "w": 2, "format": "json"}
        for topics, number in topic_vals:
            qs.update({"topics": topics})
            response = self.client.get(reverse("search"), qs)
            eq_(number, json.loads(response.content)["total"])
Example #2
0
    def test_lock_old_questions(self):
        last_updated = datetime.now() - timedelta(days=100)

        # created just now
        q1 = question(save=True)

        # created 200 days ago
        q2 = question(created=(datetime.now() - timedelta(days=200)),
                      updated=last_updated,
                      save=True)

        # created 200 days ago, already locked
        q3 = question(created=(datetime.now() - timedelta(days=200)),
                      is_locked=True,
                      updated=last_updated,
                      save=True)

        self.refresh()

        auto_lock_old_questions()

        # There are three questions.
        eq_(len(list(Question.objects.all())), 3)

        # q2 and q3 are now locked and updated times are the same
        locked_questions = list(Question.uncached.filter(is_locked=True))
        eq_(sorted([(q.id, q.updated.date()) for q in locked_questions]),
            [(q.id, q.updated.date()) for q in [q2, q3]])

        # q1 is still unlocked.
        locked_questions = list(Question.uncached.filter(is_locked=False))
        eq_(sorted([q.id for q in locked_questions]),
            [q1.id])
Example #3
0
    def test_locale_filter(self):
        """Only questions for the current locale should be shown on the
        questions front page for AAQ locales."""

        eq_(Question.objects.count(), 0)
        p = product(slug=u"firefox", save=True)
        topic(title="Fix problems", slug="fix-problems", product=p, save=True)

        q1 = question(title="question cupcakes?", save=True, locale="en-US")
        q1.products.add(p)
        q2 = question(title="question donuts?", save=True, locale="en-US")
        q2.products.add(p)
        q3 = question(title="question pies?", save=True, locale="pt-BR")
        q3.products.add(p)
        q4 = question(title="question pastries?", save=True, locale="de")
        q4.products.add(p)

        def sub_test(locale, *titles):
            url = urlparams(reverse("questions.questions", locale=locale))
            response = self.client.get(url, follow=True)
            doc = pq(response.content)
            eq_msg(len(doc("section[id^=question]")), len(titles), "Wrong number of results for {0}".format(locale))
            for substr in titles:
                assert substr in doc(".questions section .content h2 a").text()

        # en-US and pt-BR are both in AAQ_LANGUAGES, so should be filtered.
        sub_test("en-US", "cupcakes?", "donuts?")
        sub_test("pt-BR", "pies?")
        # de is not in AAQ_LANGUAGES, so should show en-US, but not pt-BR
        sub_test("de", "cupcakes?", "donuts?", "pastries?")
Example #4
0
    def test_visit_count_from_analytics(self, pageviews_by_question):
        """Verify stored visit counts from mocked data."""
        q1 = question(save=True)
        q2 = question(save=True)
        q3 = question(save=True)

        pageviews_by_question.return_value = {
            q1.id: 42,
            q2.id: 27,
            q3.id: 1337,
            123459: 3,
        }

        QuestionVisits.reload_from_analytics()
        eq_(3, QuestionVisits.objects.count())
        eq_(42, QuestionVisits.objects.get(question_id=q1.id).visits)
        eq_(27, QuestionVisits.objects.get(question_id=q2.id).visits)
        eq_(1337, QuestionVisits.objects.get(question_id=q3.id).visits)

        # Change the data and run again to cover the update case.
        pageviews_by_question.return_value = {
            q1.id: 100,
            q2.id: 200,
            q3.id: 300,
        }
        QuestionVisits.reload_from_analytics()
        eq_(3, QuestionVisits.uncached.count())
        eq_(100, QuestionVisits.uncached.get(question_id=q1.id).visits)
        eq_(200, QuestionVisits.uncached.get(question_id=q2.id).visits)
        eq_(300, QuestionVisits.uncached.get(question_id=q3.id).visits)
Example #5
0
    def test_search_suggestion_questions_locale(self):
        """Verifies the right languages show up in search suggestions."""
        p = product(slug=u"firefox", save=True)
        topic(title="Fix problems", slug="fix-problems", product=p, save=True)

        q1 = question(title="question cupcakes?", save=True, locale="en-US")
        q1.products.add(p)
        q2 = question(title="question donuts?", save=True, locale="en-US")
        q2.products.add(p)
        q3 = question(title="question pies?", save=True, locale="pt-BR")
        q3.products.add(p)
        q4 = question(title="question pastries?", save=True, locale="de")
        q4.products.add(p)

        self.refresh()

        def sub_test(locale, *titles):
            url = urlparams(
                reverse("questions.aaq_step4", args=["desktop", "fix-problems"], locale=locale), search="question"
            )
            response = self.client.get(url, follow=True)
            doc = pq(response.content)
            eq_msg(len(doc(".result.question")), len(titles), "Wrong number of results for {0}".format(locale))
            for substr in titles:
                assert substr in doc(".result.question h3 a").text()

        sub_test("en-US", "cupcakes?", "donuts?")
        sub_test("pt-BR", "cupcakes?", "donuts?", "pies?")
        sub_test("de", "cupcakes?", "donuts?", "pastries?")
Example #6
0
    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])
Example #7
0
    def test_question_products(self):
        """Search questions for products."""
        p1 = product(slug='b2g', save=True)
        p2 = product(slug='mobile', save=True)
        p3 = product(slug='desktop', save=True)

        q = question(save=True)
        q.products.add(p2)
        q = question(save=True)
        q.products.add(p2)
        q.products.add(p3)

        self.refresh()

        product_vals = (
            (p1.slug, 0),
            (p2.slug, 2),
            (p3.slug, 1),
            ([p2.slug, p3.slug], 1),
        )

        qs = {'a': 1, 'w': 2, 'format': 'json'}
        for products, number in product_vals:
            qs.update({'product': products})
            response = self.client.get(reverse('search'), qs)
            eq_(number, json.loads(response.content)['total'])
Example #8
0
    def test_question_topics(self):
        """Search questions for topics."""
        t1 = old_topic(slug='doesnotexist', save=True)
        t2 = old_topic(slug='cookies', save=True)
        t3 = old_topic(slug='sync', save=True)

        # TODO: This is a hack until we move questions to new topics.
        # We need to create these for the search form validation.
        topic(slug='doesnotexist', save=True)
        topic(slug='cookies', save=True)
        topic(slug='sync', save=True)

        q = question(save=True)
        q.topics.add(t2)
        q = question(save=True)
        q.topics.add(t2)
        q.topics.add(t3)

        self.refresh()

        topic_vals = (
            (t1.slug, 0),
            (t2.slug, 2),
            (t3.slug, 1),
            ([t2.slug, t3.slug], 1),
        )

        qs = {'a': 1, 'w': 2, 'format': 'json'}
        for topics, number in topic_vals:
            qs.update({'topics': topics})
            response = self.client.get(reverse('search'), qs)
            eq_(number, json.loads(response.content)['total'])
Example #9
0
    def test_autowatch_reply(self, get_current):
        """
        Tests the autowatch setting of users.

        If a user has the setting turned on, they should get
        notifications after posting in a thread for that thread. If they
        have that setting turned off, they should not.
        """

        get_current.return_value.domain = 'testserver'

        u = user(save=True)
        t1 = question(save=True)
        t2 = question(save=True)
        assert not QuestionReplyEvent.is_notifying(u, t1)
        assert not QuestionReplyEvent.is_notifying(u, t2)

        self.client.login(username=u.username, password='******')
        s = Setting.objects.create(user=u, name='questions_watch_after_reply',
                                   value='True')
        data = {'content': 'some content'}
        post(self.client, 'questions.reply', data, args=[t1.id])
        assert QuestionReplyEvent.is_notifying(u, t1)

        s.value = 'False'
        s.save()
        post(self.client, 'questions.reply', data, args=[t2.id])
        assert not QuestionReplyEvent.is_notifying(u, t2)
Example #10
0
    def test_search_suggestion_questions_locale(self):
        """Verifies the right languages show up in search suggestions."""
        topic(title='Fix problems', slug='fix-problems', save=True)
        p = product(slug=u'firefox', save=True)

        q1 = question(title='question cupcakes?', save=True, locale='en-US')
        q1.products.add(p)
        q2 = question(title='question donuts?', save=True, locale='en-US')
        q2.products.add(p)
        q3 = question(title='question pies?', save=True, locale='pt-BR')
        q3.products.add(p)
        q4 = question(title='question pastries?', save=True, locale='de')
        q4.products.add(p)

        self.refresh()

        def sub_test(locale, *titles):
            url = urlparams(reverse('questions.aaq_step4',
                                    args=['desktop', 'fix-problems'],
                                    locale=locale),
                            search='question')
            response = self.client.get(url, follow=True)
            doc = pq(response.content)
            eq_msg(len(doc('.result.question')), len(titles),
                   'Wrong number of results for {0}'.format(locale))
            for substr in titles:
                assert substr in doc('.result.question h3 a').text()

        sub_test('en-US', 'cupcakes?', 'donuts?')
        sub_test('pt-BR', 'cupcakes?', 'donuts?', 'pies?')
        sub_test('de', 'cupcakes?', 'donuts?', 'pastries?')
Example #11
0
    def test_locale_filter(self):
        """Only questions for the current locale should be shown on the
        questions front page for AAQ locales."""

        eq_(Question.objects.count(), 0)
        topic(title='Fix problems', slug='fix-problems', save=True)
        p = product(slug=u'firefox', save=True)

        q1 = question(title='question cupcakes?', save=True, locale='en-US')
        q1.products.add(p)
        q2 = question(title='question donuts?', save=True, locale='en-US')
        q2.products.add(p)
        q3 = question(title='question pies?', save=True, locale='pt-BR')
        q3.products.add(p)
        q4 = question(title='question pastries?', save=True, locale='de')
        q4.products.add(p)

        def sub_test(locale, *titles):
            url = urlparams(reverse('questions.questions', locale=locale))
            response = self.client.get(url, follow=True)
            doc = pq(response.content)
            eq_msg(len(doc('section[id^=question]')), len(titles),
                   'Wrong number of results for {0}'.format(locale))
            for substr in titles:
                assert substr in doc('.questions section .content h2 a').text()

        # en-US and pt-BR are both in AAQ_LOCALES, so should be filtered.
        sub_test('en-US', 'cupcakes?', 'donuts?')
        sub_test('pt-BR', 'pies?')
        # de is not in AAQ_LOCALES, so should show en-US, but not pt-BR
        sub_test('de', 'cupcakes?', 'donuts?', 'pastries?')
Example #12
0
 def test_is_not_taken(self):
     u = user(save=True)
     taken_until = datetime.now() + timedelta(seconds=30)
     question(taken_by=u, taken_until=taken_until, save=True)
     q = question(save=True)
     res = self.filter_instance.filter_is_taken(self.queryset, False)
     eq_(list(res), [q])
Example #13
0
    def test_search_suggestion_question_age(self):
        """Verifies the view doesn't return old questions."""
        topic(title='Fix problems', slug='fix-problems', save=True)
        p = product(slug=u'firefox', save=True)

        q1 = question(title='Fresh Cupcakes', save=True)
        q1.products.add(p)

        max_age = settings.SEARCH_DEFAULT_MAX_QUESTION_AGE
        too_old = datetime.now() - timedelta(seconds=max_age * 2)
        q2 = question(title='Stale Cupcakes', created=too_old, updated=too_old,
                      save=True)
        q2.products.add(p)

        self.refresh()

        url = urlparams(
            reverse('questions.aaq_step4', args=['desktop', 'fix-problems']),
                    search='cupcakes')

        response = self.client.get(url, follow=True)
        eq_(200, response.status_code)

        self.assertContains(response, q1.title)
        self.assertNotContains(response, q2.title)
Example #14
0
    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])
Example #15
0
    def test_question_topics(self):
        """Search questions for topics."""
        p = product(save=True)
        t1 = topic(slug='doesnotexist', product=p, save=True)
        t2 = topic(slug='cookies', product=p, save=True)
        t3 = topic(slug='sync', product=p, save=True)

        q = question(save=True)
        q.topics.add(t2)
        q = question(save=True)
        q.topics.add(t2)
        q.topics.add(t3)

        self.refresh()

        topic_vals = (
            (t1.slug, 0),
            (t2.slug, 2),
            (t3.slug, 1),
            ([t2.slug, t3.slug], 1),
        )

        qs = {'a': 1, 'w': 2, 'format': 'json'}
        for topics, number in topic_vals:
            qs.update({'topics': topics})
            response = self.client.get(reverse('search'), qs)
            eq_(number, json.loads(response.content)['total'])
Example #16
0
    def test_filter_creator_with_username(self):
        q1 = question(save=True)
        question(save=True)

        querystring = '?creator={0}'.format(q1.creator.username)
        res = self.client.get(reverse('question-list') + querystring)
        eq_(res.status_code, 200)
        eq_(len(res.data['results']), 1)
        eq_(res.data['results'][0]['id'], q1.id)
Example #17
0
 def test_it_works_with_users_who_have_gotten_first_contrib_emails(self):
     # This flag caused a regression, tracked in bug 1163855.
     # The error was that the help text on the field was a str instead of a
     # unicode. Yes, really, that matters apparently.
     u = profile(first_answer_email_sent=True).user
     question(creator=u, save=True)
     url = reverse('question-list')
     res = self.client.get(url)
     eq_(res.status_code, 200)
Example #18
0
    def test_filter_product_with_slug(self):
        p1 = product(save=True)
        p2 = product(save=True)
        q1 = question(product=p1, save=True)
        question(product=p2, save=True)

        querystring = '?product={0}'.format(p1.slug)
        res = self.client.get(reverse('question-list') + querystring)
        eq_(len(res.data['results']), 1)
        eq_(res.data['results'][0]['id'], q1.id)
Example #19
0
    def test_filter_is_taken_false(self):
        q1 = question(save=True)
        q2 = question(save=True)
        q2.take(q1.creator)

        url = reverse('question-list') + '?is_taken=0'
        res = self.client.get(url)

        eq_(res.status_code, 200)
        eq_(res.data['count'], 1)
        eq_(res.data['results'][0]['id'], q1.id)
Example #20
0
    def test_filter_taken_by_username(self):
        q1 = question(save=True)
        q2 = question(save=True)
        q2.take(q1.creator)

        url = reverse('question-list') + '?taken_by=' + q1.creator.username
        res = self.client.get(url)

        eq_(res.status_code, 200)
        eq_(res.data['count'], 1)
        eq_(res.data['results'][0]['id'], q2.id)
Example #21
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.filter_is_solved(self.qs, True)
        eq_(list(res), [q1])

        res = self.filter.filter_is_solved(self.qs, False)
        eq_(list(res), [q2])
Example #22
0
    def test_filter_involved(self):
        q1 = question(save=True)
        a1 = answer(question=q1, save=True)
        q2 = question(creator=a1.creator, save=True)

        qs = self.filter_instance.filter_involved(self.queryset, q1.creator.username)
        eq_(list(qs), [q1])

        qs = self.filter_instance.filter_involved(self.queryset, q2.creator.username)
        # The filter does not have a strong order.
        qs = sorted(qs, key=lambda q: q.id)
        eq_(qs, [q1, q2])
Example #23
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)

        qs = self.filter_instance.filter_is_solved(self.queryset, True)
        eq_(list(qs), [q1])

        qs = self.filter_instance.filter_is_solved(self.queryset, False)
        eq_(list(qs), [q2])
Example #24
0
    def test_user_num_questions(self):
        """Answers are counted correctly on a user."""
        u = user(save=True)

        eq_(user_num_questions(u), 0)
        q1 = question(creator=u, save=True)
        eq_(user_num_questions(u), 1)
        q2 = question(creator=u, save=True)
        eq_(user_num_questions(u), 2)
        q1.delete()
        eq_(user_num_questions(u), 1)
        q2.delete()
        eq_(user_num_questions(u), 0)
Example #25
0
    def test_age(self):
        now = datetime.now()
        ten_days_ago = now - timedelta(days=10)
        thirty_seconds_ago = now - timedelta(seconds=30)

        q1 = question(created=ten_days_ago, save=True)
        q2 = question(created=thirty_seconds_ago, save=True)

        # This test relies on datetime.now() being called in the age
        # property, so this delta check makes it less likely to fail
        # randomly.
        assert abs(q1.age - 10 * 24 * 60 * 60) < 2, ('q1.age ({0!s}) != 10 days'.format(q1.age))
        assert abs(q2.age - 30) < 2, 'q2.age ({0!s}) != 30 seconds'.format(q2.age)
Example #26
0
    def test_escalate_questions_cron(self, submit_ticket):
        """Verify the escalate cronjob escalates the right questions."""

        questions_to_escalate = [
            # Questions over 24 hours old without an answer.
            question(
                created=datetime.now() - timedelta(hours=24, minutes=10),
                save=True),
            question(
                created=datetime.now() - timedelta(hours=24, minutes=50),
                save=True),
        ]

        questions_not_to_escalate = [
            # Questions newer than 24 hours without an answer.
            question(save=True),
            question(created=datetime.now() - timedelta(hours=11), save=True),
            question(created=datetime.now() - timedelta(hours=21), save=True),
        ]

        # Question older than 24 hours with a recent answer.
        q = question(
            created=datetime.now() - timedelta(hours=24, minutes=10),
            save=True)
        answer(created=datetime.now() - timedelta(hours=10), question=q,
               save=True)
        answer(created=datetime.now() - timedelta(hours=1), creator=q.creator,
               question=q, save=True)
        questions_not_to_escalate.append(q)

        # Question older than 24 hours with a recent answer by the asker.
        q = question(
            created=datetime.now() - timedelta(hours=24, minutes=10),
            save=True)
        answer(
            created=datetime.now() - timedelta(hours=15), creator=q.creator,
            question=q, save=True)
        questions_not_to_escalate.append(q)

        # Question older than 24 hours without an answer already escalated.
        q = question(
            created=datetime.now() - timedelta(hours=24, minutes=10),
            save=True)
        q.tags.add(config.ESCALATE_TAG_NAME)
        questions_not_to_escalate.append(q)

        # Question with an inactive user.
        q = question(
            created=datetime.now() - timedelta(hours=24, minutes=10),
            save=True)
        q.creator.is_active = False
        q.creator.save()
        questions_not_to_escalate.append(q)

        # Run the cron job and verify only 3 questions were escalated.
        eq_(len(questions_to_escalate), escalate_questions())
Example #27
0
    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))
Example #28
0
    def test_ordering(self):
        q1 = question(save=True)
        q2 = question(save=True)

        res = self.client.get(reverse('question-list'))
        eq_(res.data['results'][0]['id'], q2.id)
        eq_(res.data['results'][1]['id'], q1.id)

        res = self.client.get(reverse('question-list') + '?ordering=id')
        eq_(res.data['results'][0]['id'], q1.id)
        eq_(res.data['results'][1]['id'], q2.id)

        res = self.client.get(reverse('question-list') + '?ordering=-id')
        eq_(res.data['results'][0]['id'], q2.id)
        eq_(res.data['results'][1]['id'], q1.id)
Example #29
0
    def test_answer_welcome_email(self):
        u1 = profile().user
        u2 = profile(first_answer_email_sent=True).user
        u3 = profile().user

        two_days = datetime.now() - timedelta(hours=48)

        q = question(creator=u1, save=True)
        answer(question=q, creator=u1, created=two_days, save=True)
        answer(question=q, creator=u2, created=two_days, save=True)
        answer(question=q, creator=u3, created=two_days, save=True)

        # Clear out the notifications that were sent
        mail.outbox = []
        # Send email(s) for welcome messages
        cron.send_welcome_emails()

        # There should be an email for u3 only.
        # u1 was the asker, and so did not make a contribution.
        # u2 has already recieved the email

        eq_(len(mail.outbox), 1)
        attrs_eq(mail.outbox[0], to=[u3.email])

        # u3's flag should now be set.
        u3 = User.objects.get(id=u3.id)
        eq_(u3.profile.first_answer_email_sent, True)
Example #30
0
    def test_from_url(self):
        """Verify question returned from valid URL."""
        q = question(save=True)

        eq_(q, Question.from_url('/en-US/questions/%s' % q.id))
        eq_(q, Question.from_url('/es/questions/%s' % q.id))
        eq_(q, Question.from_url('/questions/%s' % q.id))
Example #31
0
 def test_helpful(self):
     q = question(save=True)
     u = profile().user
     self.client.force_authenticate(user=u)
     res = self.client.post(reverse('question-helpful', args=[q.id]))
     eq_(res.status_code, 200)
     eq_(res.data, {'num_votes': 1})
     eq_(Question.objects.get(id=q.id).num_votes, 1)
Example #32
0
    def test_from_invalid_url(self):
        """Verify question returned from valid URL."""
        q = question(save=True)

        eq_(None, Question.from_url('/en-US/questions/%s/edit' % q.id))
        eq_(None, Question.from_url('/en-US/kb/%s' % q.id))
        eq_(None, Question.from_url('/random/url'))
        eq_(None, Question.from_url('/en-US/questions/dashboard/metrics'))
Example #33
0
    def test_advanced_search_questions_sortby(self):
        """Tests advanced search for questions with a sortby"""
        question(title=u'tags tags tags', save=True)

        self.refresh()

        # Advanced search for questions with sortby set to 3 which is
        # '-replies' which is different between Sphinx and ES.
        response = self.client.get(reverse('search'), {
            'q': 'tags', 'tags': 'desktop', 'w': '2', 'a': '1', 'sortby': '3',
            'format': 'json'
        })

        eq_(200, response.status_code)

        content = json.loads(response.content)
        eq_(content['total'], 1)
Example #34
0
    def setUp(self):
        p = profile()
        p.save()
        self.user = p.user
        self.client.login(username=self.user.username, password='******')

        self.question = question(creator=self.user, save=True)
        QuestionReplyEvent.notify(self.user, self.question)
Example #35
0
    def test_vote_updates_count(self):
        q = question(save=True)
        eq_(0, q.num_votes_past_week)

        questionvote(question=q, anonymous_id='abc123', save=True)

        q = Question.uncached.get(id=q.id)
        eq_(1, q.num_votes_past_week)
Example #36
0
 def test_answer_create_action(self):
     """When an answer is created, an Action is created too."""
     q = question(save=True)
     ans = answer(question=q, save=True)
     act = Action.objects.action_object(ans).get()
     eq_(act.actor, ans.creator)
     eq_(act.verb, 'answered')
     eq_(act.target, q)
Example #37
0
    def test_search_suggestion_questions_locale(self):
        """Verifies the right languages show up in search suggestions."""
        questionlocale(locale='de', save=True)

        p = product(slug=u'firefox', save=True)

        for l in QuestionLocale.objects.all():
            p.questions_locales.add(l)

        topic(title='Fix problems', slug='fix-problems', product=p, save=True)

        q1 = question(title='question cupcakes?',
                      product=p,
                      save=True,
                      locale='en-US')
        q2 = question(title='question donuts?',
                      product=p,
                      save=True,
                      locale='en-US')
        q3 = question(title='question pies?',
                      product=p,
                      save=True,
                      locale='pt-BR')
        q4 = question(title='question pastries?',
                      product=p,
                      save=True,
                      locale='de')

        self.refresh()

        def sub_test(locale, *titles):
            url = urlparams(reverse('questions.aaq_step4',
                                    args=['desktop', 'fix-problems'],
                                    locale=locale),
                            search='question')
            response = self.client.get(url, follow=True)
            doc = pq(response.content)
            eq_msg(len(doc('.result.question')), len(titles),
                   'Wrong number of results for {0}'.format(locale))
            for substr in titles:
                assert substr in doc('.result.question h3 a').text()

        sub_test('en-US', 'cupcakes?', 'donuts?')
        sub_test('pt-BR', 'cupcakes?', 'donuts?', 'pies?')
        sub_test('de', 'cupcakes?', 'donuts?', 'pastries?')
Example #38
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(save=True)
        q.products.add(firefox_os)
        a = answer(question=q, save=True)
        q.solution = a
        q.save()

        # A Firefox OS question with an answer:
        q = question(save=True)
        q.products.add(firefox_os)
        answer(question=q, save=True)

        # A Firefox OS question without answers:
        q = question(save=True)
        q.products.add(firefox_os)

        # A Firefox question without answers:
        q = question(locale='pt-BR', save=True)
        q.products.add(firefox)

        # 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]
Example #39
0
    def test_weird_list_troubleshooting_info(self):
        """Test the corner case in which 'modifiedPReferences' is in a
        list in troubleshooting data. This is weird, but caused a bug."""
        q = question(save=True)
        q.add_metadata(troubleshooting='["modifiedPreferences"]')

        # This case should not raise an error.
        response = get(self.client, 'questions.details', args=[q.id])
        eq_(200, response.status_code)
Example #40
0
 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)
Example #41
0
    def test_filter_involved(self):
        q1 = question(save=True)
        a1 = answer(question=q1, save=True)
        q2 = question(creator=a1.creator, save=True)

        querystring = '?involved={0}'.format(q1.creator.username)
        res = self.client.get(reverse('question-list') + querystring)
        eq_(res.status_code, 200)
        eq_(len(res.data['results']), 1)
        eq_(res.data['results'][0]['id'], q1.id)

        querystring = '?involved={0}'.format(q2.creator.username)
        res = self.client.get(reverse('question-list') + querystring)
        eq_(res.status_code, 200)
        eq_(len(res.data['results']), 2)
        # The API has a default sort, so ordering will be consistent.
        eq_(res.data['results'][0]['id'], q2.id)
        eq_(res.data['results'][1]['id'], q1.id)
Example #42
0
    def test_tagged_feed(self):
        """Test the tagged feed."""
        t = tag(name='green', slug='green', save=True)
        q = question(save=True)
        q.tags.add('green')
        items = TaggedQuestionsFeed().items(t)
        eq_(1, len(items))
        eq_(q.id, items[0].id)

        cache.clear()

        q = question(save=True)
        q.tags.add('green')
        q.updated = datetime.now() + timedelta(days=1)
        q.save()
        items = TaggedQuestionsFeed().items(t)
        eq_(2, len(items))
        eq_(q.id, items[0].id)
Example #43
0
 def test_follow(self):
     q = question(save=True)
     u = profile().user
     self.client.force_authenticate(user=u)
     res = self.client.post(reverse('question-follow', args=[q.id]))
     eq_(res.status_code, 204)
     f = Follow.objects.get(user=u)
     eq_(f.follow_object, q)
     eq_(f.actor_only, False)
Example #44
0
 def test_unfollow(self):
     q = question(save=True)
     u = profile().user
     actstream.actions.follow(u, q, actor_only=False)
     eq_(Follow.objects.filter(user=u).count(), 1)  # pre-condition
     self.client.force_authenticate(user=u)
     res = self.client.post(reverse('question-unfollow', args=[q.id]))
     eq_(res.status_code, 204)
     eq_(Follow.objects.filter(user=u).count(), 0)
Example #45
0
    def setUp(self):
        self.client = APIClient()

        self.follower = profile().user
        self.followed = profile().user
        self.question = question(creator=self.followed, save=True)
        # The above might make follows, which this test isn't about. Clear them out.
        Follow.objects.all().delete()
        follow(self.follower, self.followed)
Example #46
0
    def test_no_notification_on_update(self):
        """Saving an existing question does not watch it."""

        q = question(save=True)
        QuestionReplyEvent.stop_notifying(q.creator, q)
        assert not QuestionReplyEvent.is_notifying(q.creator, q)

        q.save()
        assert not QuestionReplyEvent.is_notifying(q.creator, q)
Example #47
0
 def test_is_taken_clears(self):
     u = user(save=True)
     taken_until = datetime.now() - timedelta(seconds=30)
     q = question(taken_by=u, taken_until=taken_until, save=True)
     # Testin q.is_taken should clear out ``taken_by`` and ``taken_until``,
     # since taken_until is in the past.
     eq_(q.is_taken, False)
     eq_(q.taken_by, None)
     eq_(q.taken_until, None)
Example #48
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)
Example #49
0
    def test_done(self):
        """Verify the done queryset."""
        # Create a question, there shouldn't be any done yet.
        q = question(save=True)
        eq_(0, Question.objects.done().count())

        # Add an answer, there shouldn't be any done yet.
        a = answer(question=q, save=True)
        eq_(0, Question.objects.done().count())

        # Make it the solution, there should be one done.
        q.solution = a
        q.save()
        eq_(1, Question.objects.done().count())

        # Create a locked questions, there should be two done.
        question(is_locked=True, save=True)
        eq_(2, Question.objects.done().count())
Example #50
0
    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='******')
Example #51
0
    def test_stats(self):
        """Tests questions/dashboard/metrics view"""
        p = product(save=True)
        t = topic(title='Websites', slug='websites', product=p, save=True)

        question(title=u'cupcakes',
                 content=u'Cupcakes rock!',
                 created=datetime.now() - timedelta(days=1),
                 topic=t,
                 save=True)

        self.refresh()

        response = self.client.get(reverse('questions.metrics'))
        eq_(200, response.status_code)

        # If there's histogram data, this is probably good enough to
        # denote its existence.
        assert ' data-graph="[' in response.content
Example #52
0
    def test_num_votes_none(self):
        """Tests num_voted filtering where num_votes is ''"""
        q = question(save=True)
        questionvote(question=q, save=True)

        self.refresh()

        qs = {'q': '', 'w': 2, 'a': 1, 'num_voted': 2, 'num_votes': ''}
        response = self.client.get(reverse('search'), qs)
        eq_(200, response.status_code)
Example #53
0
    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)
Example #54
0
    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)
Example #55
0
 def test_helpful_double_vote(self):
     q = question(save=True)
     u = profile().user
     questionvote(question=q, creator=u, save=True)
     self.client.force_authenticate(user=u)
     res = self.client.post(reverse('question-helpful', args=[q.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_(Question.objects.get(id=q.id).num_votes, 1)
Example #56
0
 def test_take_conflict(self):
     u1 = user(save=True)
     u2 = user(save=True)
     taken_until = datetime.now() + timedelta(seconds=30)
     q = question(save=True, taken_until=taken_until, taken_by=u1)
     self.client.force_authenticate(user=u2)
     res = self.client.post(reverse('question-take', args=[q.id]))
     eq_(res.status_code, 409)
     q = Question.objects.get(id=q.id)
     eq_(q.taken_by, u1)
Example #57
0
    def test_question_is_unindexed_on_creator_delete(self):
        search = QuestionMappingType.search()

        q = question(title=u'Does this work?', save=True)
        self.refresh()
        eq_(search.query(question_title__match='work').count(), 1)

        q.creator.delete()
        self.refresh()
        eq_(search.query(question_title__match='work').count(), 0)
Example #58
0
    def test_question_no_answers_deleted(self):
        search = QuestionMappingType.search()

        q = question(title=u'Does this work?', save=True)
        self.refresh()
        eq_(search.query(question_title__match='work').count(), 1)

        q.delete()
        self.refresh()
        eq_(search.query(question_title__match='work').count(), 0)
Example #59
0
    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])
Example #60
0
    def test_question_vote_limit(self):
        """Test that an anonymous user's votes are ignored after 10
        question votes."""
        questions = [question(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_question_vote(questions[i], False)

        # Now make another, it should fail.
        self._check_question_vote(questions[10], True)