Exemplo n.º 1
0
    def test_synonyms_work_in_search_view(self):
        d1 = DocumentFactory(title='frob')
        d2 = DocumentFactory(title='glork')
        RevisionFactory(document=d1, is_approved=True)
        RevisionFactory(document=d2, is_approved=True)

        self.refresh()

        # First search without synonyms
        response = self.client.get(reverse('search'), {'q': 'frob'})
        doc = pq(response.content)
        header = doc.find('#search-results h2').text().strip()
        eq_(header, 'Found 1 result for frob for All Products')

        # Now add a synonym.
        SynonymFactory(from_words='frob', to_words='frob, glork')
        update_synonyms_task()
        self.refresh()

        # Forward search
        response = self.client.get(reverse('search'), {'q': 'frob'})
        doc = pq(response.content)
        header = doc.find('#search-results h2').text().strip()
        eq_(header, 'Found 2 results for frob for All Products')

        # Reverse search
        response = self.client.get(reverse('search'), {'q': 'glork'})
        doc = pq(response.content)
        header = doc.find('#search-results h2').text().strip()
        eq_(header, 'Found 1 result for glork for All Products')
Exemplo n.º 2
0
    def test_needs_change(self):
        """Test setting and unsetting the needs change flag"""
        # Create a new document and edit it, setting needs_change.
        comment = 'Please update for Firefix.next'
        doc = RevisionFactory().document
        data = new_document_data()
        data.update({'needs_change': True,
                     'needs_change_comment': comment,
                     'form': 'doc'})

        # Verify that needs_change can't be set if the user doesn't have
        # the permission.
        self.client.post(reverse('wiki.edit_document', args=[doc.slug]), data)
        doc = Document.objects.get(pk=doc.pk)
        assert not doc.needs_change
        assert not doc.needs_change_comment

        # Give the user permission, now it should work.
        add_permission(self.u, Document, 'edit_needs_change')
        self.client.post(reverse('wiki.edit_document', args=[doc.slug]), data)
        doc = Document.objects.get(pk=doc.pk)
        assert doc.needs_change
        eq_(comment, doc.needs_change_comment)

        # Clear out needs_change.
        data.update({'needs_change': False,
                     'needs_change_comment': comment})
        self.client.post(reverse('wiki.edit_document', args=[doc.slug]), data)
        doc = Document.objects.get(pk=doc.pk)
        assert not doc.needs_change
        eq_('', doc.needs_change_comment)
Exemplo n.º 3
0
    def test_removing_template_category(self):
        d = TemplateDocumentFactory()
        RevisionFactory(document=d)
        eq_(d.category, TEMPLATES_CATEGORY)
        assert d.title.startswith(TEMPLATE_TITLE_PREFIX)

        # First try and change the category without also changing the title. It should fail.
        data = new_document_data()
        data.update({
            'title': d.title,
            'category': CATEGORIES[0][0],
            'slug': d.slug,
            'form': 'doc'
        })
        url = reverse('wiki.edit_document', args=[d.slug])
        res = self.client.post(url, data, follow=True)
        eq_(Document.objects.get(id=d.id).category, TEMPLATES_CATEGORY)
        # This message gets HTML encoded.
        assert ('Documents with titles that start with "Template:" must be in the '
                'templates category.' in res.content)

        # Now try and change the title while also changing the category.
        data['title'] = 'not a template'
        url = reverse('wiki.edit_document', args=[d.slug])
        self.client.post(url, data)
        eq_(Document.objects.get(id=d.id).category, CATEGORIES[0][0])
Exemplo n.º 4
0
    def test_needs_change(self):
        """Test setting and unsetting the needs change flag"""
        # Create a new document and edit it, setting needs_change.
        comment = "Please update for Firefix.next"
        doc = revision(save=True).document
        data = new_document_data()
        data.update({"needs_change": True, "needs_change_comment": comment, "form": "doc"})

        # Verify that needs_change can't be set if the user doesn't have
        # the permission.
        self.client.post(reverse("wiki.edit_document", args=[doc.slug]), data)
        doc = Document.objects.get(pk=doc.pk)
        assert not doc.needs_change
        assert not doc.needs_change_comment

        # Give the user permission, now it should work.
        add_permission(self.u, Document, "edit_needs_change")
        self.client.post(reverse("wiki.edit_document", args=[doc.slug]), data)
        doc = Document.objects.get(pk=doc.pk)
        assert doc.needs_change
        eq_(comment, doc.needs_change_comment)

        # Clear out needs_change.
        data.update({"needs_change": False, "needs_change_comment": comment})
        self.client.post(reverse("wiki.edit_document", args=[doc.slug]), data)
        doc = Document.objects.get(pk=doc.pk)
        assert not doc.needs_change
        eq_("", doc.needs_change_comment)
Exemplo n.º 5
0
    def test_changing_products(self):
        """Changing products works as expected."""
        r = ApprovedRevisionFactory()
        d = r.document
        prod_desktop = ProductFactory(title=u'desktop')
        prod_mobile = ProductFactory(title=u'mobile')

        data = new_document_data()
        data.update({'products': [prod_desktop.id, prod_mobile.id],
                     'title': d.title,
                     'slug': d.slug,
                     'form': 'doc'})
        self.client.post(reverse('wiki.edit_document', args=[d.slug]), data)

        eq_(sorted(Document.objects.get(id=d.id).products
                   .values_list('id', flat=True)),
            sorted([prod.id for prod in [prod_desktop, prod_mobile]]))

        data.update({'products': [prod_desktop.id],
                     'form': 'doc'})
        self.client.post(reverse('wiki.edit_document', args=[data['slug']]),
                         data)
        eq_(sorted(Document.objects.get(id=d.id).products
                   .values_list('id', flat=True)),
            sorted([prod.id for prod in [prod_desktop]]))
Exemplo n.º 6
0
    def test_new_user(self, get_current):
        get_current.return_value.domain = 'su.mo.com'
        response = self.client.post(reverse('users.register', locale='en-US'),
                                    {'username': '******',
                                     'email': '*****@*****.**',
                                     'password': '******',
                                     'password2': 'foobar22'}, follow=True)
        eq_(200, response.status_code)
        u = User.objects.get(username='******')
        assert u.password.startswith('sha256')
        assert not u.is_active
        eq_(1, len(mail.outbox))
        assert mail.outbox[0].subject.find('Please confirm your') == 0
        key = RegistrationProfile.objects.all()[0].activation_key
        assert mail.outbox[0].body.find('activate/%s/%s' % (u.id, key)) > 0

        # By default, users aren't added to any groups
        eq_(0, len(u.groups.all()))

        # Now try to log in
        u.is_active = True
        u.save()
        response = self.client.post(reverse('users.login', locale='en-US'),
                                    {'username': '******',
                                     'password': '******'}, follow=True)
        eq_(200, response.status_code)
        eq_('http://testserver/en-US/home?fpa=1',
            response.redirect_chain[0][0])
Exemplo n.º 7
0
    def test_retitling_template(self):
        d = TemplateDocumentFactory()
        RevisionFactory(document=d)

        old_title = d.title
        new_title = 'Not a template'

        # First try and change the title without also changing the category. It should fail.
        data = new_document_data()
        data.update({
            'title': new_title,
            'category': d.category,
            'slug': d.slug,
            'form': 'doc'
        })
        url = reverse('wiki.edit_document', args=[d.slug])
        res = self.client.post(url, data, follow=True)
        eq_(Document.objects.get(id=d.id).title, old_title)
        # This message gets HTML encoded.
        assert ('Documents in the Template category must have titles that start with '
                '"Template:".'
                in res.content)

        # Now try and change the title while also changing the category.
        data['category'] = CATEGORIES[0][0]
        url = reverse('wiki.edit_document', args=[d.slug])
        self.client.post(url, data, follow=True)
        eq_(Document.objects.get(id=d.id).title, new_title)
Exemplo n.º 8
0
def login(request, template):
    """Try to log the user in."""
    if request.method == 'GET' and not request.MOBILE:
        url = reverse('users.auth') + '?' + request.GET.urlencode()
        return HttpResponsePermanentRedirect(url)

    next_url = get_next_url(request) or reverse('home')
    form = handle_login(request)

    if request.user.is_authenticated():
        # Add a parameter so we know the user just logged in.
        # fpa =  "first page authed" or something.
        next_url = urlparams(next_url, fpa=1)
        res = HttpResponseRedirect(next_url)
        max_age = (None if settings.SESSION_EXPIRE_AT_BROWSER_CLOSE
                        else settings.SESSION_COOKIE_AGE)
        res.set_cookie(settings.SESSION_EXISTS_COOKIE,
                       '1',
                       secure=False,
                       max_age=max_age)
        return res

    if request.MOBILE:
        return render(request, template, {
            'form': form,
            'next_url': next_url})

    return user_auth(request, login_form=form)
Exemplo n.º 9
0
    def test_new_contributor(self, get_current):
        """Verify that interested contributors are added to group."""
        get_current.return_value.domain = 'su.mo.com'
        group_name = 'Registered as contributor'
        group(name=group_name, save=True)
        data = {
            'username': '******',
            'email': '*****@*****.**',
            'password': '******',
            'password2': 'foobar22',
            'interested': 'yes'}
        response = self.client.post(reverse('users.register', locale='en-US'),
                                    data, follow=True)
        eq_(200, response.status_code)
        u = User.objects.get(username='******')
        eq_(group_name, u.groups.all()[0].name)

        # Activate user and verify email is sent.
        key = RegistrationProfile.objects.all()[0].activation_key
        url = reverse('users.activate', args=[u.id, key])
        response = self.client.get(url, follow=True)
        eq_(200, response.status_code)
        eq_(2, len(mail.outbox))
        assert mail.outbox[1].subject.find('Welcome to') == 0
        assert u.username in mail.outbox[1].body
Exemplo n.º 10
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])
Exemplo n.º 11
0
    def test_forums_filter_updated(self):
        """Filter for updated date."""
        post_updated_ds = datetime(2010, 5, 3, 12, 00)

        thread1 = thread(title=u't1 audio', save=True)
        post(thread=thread1, created=post_updated_ds, save=True)

        thread2 = thread(title=u't2 audio', save=True)
        post(thread=thread2,
             created=(post_updated_ds + timedelta(days=2)),
             save=True)

        self.refresh()

        qs = {'a': 1, 'w': 4, 'format': 'json',
              'sortby': 1, 'updated_date': '05/04/2010'}

        qs['updated'] = constants.INTERVAL_BEFORE
        response = self.client.get(reverse('search'), qs)
        results = json.loads(response.content)['results']
        eq_([thread1.get_absolute_url()], [r['url'] for r in results])

        qs['updated'] = constants.INTERVAL_AFTER
        response = self.client.get(reverse('search'), qs)
        results = json.loads(response.content)['results']
        eq_([thread2.get_absolute_url()], [r['url'] for r in results])
Exemplo n.º 12
0
    def test_advanced_search_sortby_documents_helpful(self):
        """Tests advanced search with a sortby_documents by helpful"""
        r1 = revision(is_approved=True, save=True)
        r2 = revision(is_approved=True, save=True)
        helpful_vote(revision=r2, helpful=True, save=True)

        # Note: We have to wipe and rebuild the index because new
        # helpful_votes don't update the index data.
        self.setup_indexes()
        self.reindex_and_refresh()

        # r2.document should come first with 1 vote.
        response = self.client.get(reverse('search'), {
            'w': '1', 'a': '1', 'sortby_documents': 'helpful',
            'format': 'json'})
        eq_(200, response.status_code)

        content = json.loads(response.content)
        eq_(r2.document.title, content['results'][0]['title'])

        # Vote twice on r1, now it should come first.
        helpful_vote(revision=r1, helpful=True, save=True)
        helpful_vote(revision=r1, helpful=True, save=True)

        self.setup_indexes()
        self.reindex_and_refresh()

        response = self.client.get(reverse('search'), {
            'w': '1', 'a': '1', 'sortby_documents': 'helpful',
            'format': 'json'})
        eq_(200, response.status_code)

        content = json.loads(response.content)
        eq_(r1.document.title, content['results'][0]['title'])
Exemplo n.º 13
0
    def test_advanced_search_questions_num_votes(self):
        """Tests advanced search for questions num_votes filter"""
        q = question(title=u'tags tags tags', save=True)

        # Add two question votes
        questionvote(question=q, save=True)
        questionvote(question=q, save=True)

        self.refresh()

        # Advanced search for questions with num_votes > 5. The above
        # question should be not in this set.
        response = self.client.get(reverse('search'), {
            'q': '', 'tags': 'desktop', 'w': '2', 'a': '1',
            'num_voted': 2, 'num_votes': 5,
            'format': 'json'
        })

        eq_(200, response.status_code)

        content = json.loads(response.content)
        eq_(content['total'], 0)

        # Advanced search for questions with num_votes < 1. The above
        # question should be not in this set.
        response = self.client.get(reverse('search'), {
            'q': '', 'tags': 'desktop', 'w': '2', 'a': '1',
            'num_voted': 1, 'num_votes': 1,
            'format': 'json'
        })

        eq_(200, response.status_code)

        content = json.loads(response.content)
        eq_(content['total'], 0)
Exemplo n.º 14
0
def new_message(request, template):
    """Send a new private message."""
    to = request.GET.get('to')
    if to:
        try:
            User.objects.get(username=to)
        except User.DoesNotExist:
            contrib_messages.add_message(
                request, contrib_messages.ERROR,
                _('Invalid username provided. Enter a new username below.'))
            return HttpResponseRedirect(reverse('messages.new'))

    form = MessageForm(request.POST or None, initial={'to': to})

    if (request.method == 'POST' and form.is_valid() and
            not is_ratelimited(request, increment=True, rate='50/d', ip=False,
                           keys=user_or_ip('private-message-day'))):
        send_message(form.cleaned_data['to'], form.cleaned_data['message'],
                     request.user)
        if form.cleaned_data['in_reply_to']:
            irt = form.cleaned_data['in_reply_to']
            try:
                m = InboxMessage.objects.get(pk=irt, to=request.user)
                m.update(replied=True)
            except InboxMessage.DoesNotExist:
                pass
        contrib_messages.add_message(request, contrib_messages.SUCCESS,
                                     _('Your message was sent!'))
        return HttpResponseRedirect(reverse('messages.inbox'))

    return render(request, template, {'form': form})
Exemplo n.º 15
0
def _format_row_with_out_of_dateness(readout_locale, eng_slug, eng_title, slug,
                                     title, visits, significance,
                                     needs_review):
    """Format a row for a readout that has the traffic-light-style
    categorization of how seriously out of date a translation is."""
    if slug:  # A translation exists but may not be approved.
        locale = readout_locale
        status, view_name, status_class = SIGNIFICANCE_STATUSES.get(
            significance, REVIEW_STATUSES[needs_review])
        status_url = (reverse(view_name, args=[slug], locale=locale)
                      if view_name else '')
    else:
        slug = eng_slug
        title = eng_title
        locale = settings.WIKI_DEFAULT_LANGUAGE
        status = _(u'Translation Needed')
        # When calling the translate view, specify locale to translate to:
        status_url = reverse('wiki.translate', args=[slug],
                             locale=readout_locale)
        status_class = 'untranslated'

    return dict(title=title,
                url=reverse('wiki.document', args=[slug],
                            locale=locale),
                visits=visits,
                status=status,
                status_class=status_class,
                status_url=status_url)
Exemplo n.º 16
0
    def test_locale_filter(self):
        """Test filtering results by locale."""
        today = date.today()

        # Create 3 wikimetrics for es:
        for i in range(3):
            wikimetric(
                locale='es',
                date=today - timedelta(days=i),
                save=True)

        # Create 1 for fr:
        wikimetric(locale='fr', save=True)

        # Call and verify the API for locale=es.
        response = self.client.get(
            urlparams(reverse('api.wikimetric_list'), format='json',
                      locale='es'))
        eq_(200, response.status_code)

        results = json.loads(response.content)['results']
        eq_(3, len(results))

        # Call and verify the API for locale=fr.
        response = self.client.get(
            urlparams(reverse('api.wikimetric_list'), format='json',
                      locale='fr'))
        eq_(200, response.status_code)

        results = json.loads(response.content)['results']
        eq_(1, len(results))
Exemplo n.º 17
0
def delete_post(request, forum_slug, thread_id, post_id):
    """Delete a post."""
    forum = get_object_or_404(Forum, slug=forum_slug)
    thread = get_object_or_404(Thread, pk=thread_id, forum=forum)
    post = get_object_or_404(Post, pk=post_id, thread=thread)

    if request.method == 'GET':
        # Render the confirmation page
        return render(request, 'forums/confirm_post_delete.html', {
            'forum': forum, 'thread': thread, 'post': post})

    # Handle confirm delete form POST
    log.warning("User %s is deleting post with id=%s" %
                (request.user, post.id))
    post.delete()

    statsd.incr('forums.delete_post')

    try:
        Thread.objects.get(pk=thread_id)
        goto = reverse('forums.posts', args=[forum_slug, thread_id])
    except Thread.DoesNotExist:
        # The thread was deleted, go to the threads list page
        goto = reverse('forums.threads', args=[forum_slug])

    return HttpResponseRedirect(goto)
Exemplo n.º 18
0
def _get_wiki_link(title, locale):
    """Checks the page exists, and returns its URL or the URL to create it.

    Return value is a dict: {'found': boolean, 'url': string}.
    found is False if the document does not exist.

    """
    # Prevent circular import. sumo is conceptually a utils apps and
    # shouldn't have import-time (or really, any, but that's not going
    # to happen) dependencies on client apps.
    from kitsune.wiki.models import Document

    d = get_object_fallback(Document, locale=locale, title=title, is_template=False)
    if d:
        # If the article redirects use its destination article
        while d.redirect_document():
            d = d.redirect_document()

        # The locale in the link urls should always match the current
        # document's locale even if the document/slug being linked to
        # is in the default locale.
        url = reverse("wiki.document", locale=locale, args=[d.slug])
        return {"found": True, "url": url, "text": d.title}

    # To avoid circular imports, wiki.models imports wiki_to_html
    from kitsune.sumo.helpers import urlparams

    return {"found": False, "text": title, "url": urlparams(reverse("wiki.new_document", locale=locale), title=title)}
Exemplo n.º 19
0
    def test_code_filter(self):
        """Test filtering results by code."""
        today = date.today()

        # Create 3 wikimetrics for active_contributors:
        for i in range(3):
            wikimetric(
                code=METRIC_CODE_CHOICES[0][0],
                date=today - timedelta(days=i),
                save=True)

        # Create 1 for percent_localized_all:
        wikimetric(code=METRIC_CODE_CHOICES[1][0], save=True)

        # Call and verify the API for code=METRIC_CODE_CHOICES[0].
        response = self.client.get(
            urlparams(reverse('api.wikimetric_list'), format='json',
                      code=METRIC_CODE_CHOICES[0][0]))
        eq_(200, response.status_code)

        results = json.loads(response.content)['results']
        eq_(3, len(results))

        # Call and verify the API for code=METRIC_CODE_CHOICES[1].
        response = self.client.get(
            urlparams(reverse('api.wikimetric_list'), format='json',
                      code=METRIC_CODE_CHOICES[1][0]))
        eq_(200, response.status_code)

        results = json.loads(response.content)['results']
        eq_(1, len(results))
Exemplo n.º 20
0
    def test_advanced_search_questions_num_votes(self):
        """Tests advanced search for questions num_votes filter"""
        q = question(title=u"tags tags tags", save=True)

        # Add two question votes
        questionvote(question=q, save=True)
        questionvote(question=q, save=True)

        self.refresh()

        # Advanced search for questions with num_votes > 5. The above
        # question should be not in this set.
        response = self.client.get(
            reverse("search"),
            {"q": "", "tags": "desktop", "w": "2", "a": "1", "num_voted": 2, "num_votes": 5, "format": "json"},
        )

        eq_(200, response.status_code)

        content = json.loads(response.content)
        eq_(content["total"], 0)

        # Advanced search for questions with num_votes < 1. The above
        # question should be not in this set.
        response = self.client.get(
            reverse("search"),
            {"q": "", "tags": "desktop", "w": "2", "a": "1", "num_voted": 1, "num_votes": 1, "format": "json"},
        )

        eq_(200, response.status_code)

        content = json.loads(response.content)
        eq_(content["total"], 0)
Exemplo n.º 21
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])
Exemplo n.º 22
0
def delete_post(request, document_slug, thread_id, post_id):
    """Delete a post."""
    doc = get_document(document_slug, request)
    thread = get_object_or_404(Thread, pk=thread_id, document=doc)
    post = get_object_or_404(Post, pk=post_id, thread=thread)

    if request.method == 'GET':
        # Render the confirmation page
        return render(request, 'kbforums/confirm_post_delete.html', {
            'document': doc, 'thread': thread, 'post': post})

    # Handle confirm delete form POST
    log.warning("User {0!s} is deleting KB post with id={1!s}".format(request.user, post.id))
    post.delete()

    statsd.incr('kbforums.delete_post')

    try:
        Thread.objects.get(pk=thread_id)
        goto = reverse('wiki.discuss.posts',
                       args=[document_slug, thread_id])
    except Thread.DoesNotExist:
        # The thread was deleted, go to the threads list page
        goto = reverse('wiki.discuss.threads', args=[document_slug])

    return HttpResponseRedirect(goto)
Exemplo n.º 23
0
    def test_top_contributors(self):
        # There should be no top contributors since there are no answers.
        response = self.client.get(reverse('questions.list', args=['all']))
        eq_(200, response.status_code)
        doc = pq(response.content)
        eq_(0, len(doc('#top-contributors ol li')))

        # Add an answer, we now have a top conributor.
        a = answer(save=True)
        profile(user=a.creator)
        self.refresh()
        response = self.client.get(reverse('questions.list', args=['all']))
        eq_(200, response.status_code)
        doc = pq(response.content)
        lis = doc('#top-contributors ol li')
        eq_(1, len(lis))
        eq_(Profile.objects.get(user=a.creator).display_name, lis[0].text)

        # Make answer 91 days old. There should no be top contributors.
        a.created = datetime.now() - timedelta(days=91)
        a.save()
        self.refresh()
        response = self.client.get(reverse('questions.list', args=['all']))
        eq_(200, response.status_code)
        doc = pq(response.content)
        eq_(0, len(doc('#top-contributors ol li')))
Exemplo n.º 24
0
    def test_sortby_documents_helpful(self):
        """Tests advanced search with a sortby_documents by helpful"""
        r1 = RevisionFactory(is_approved=True)
        r2 = RevisionFactory(is_approved=True)
        HelpfulVoteFactory(revision=r2, helpful=True)

        # Note: We have to wipe and rebuild the index because new
        # helpful_votes don't update the index data.
        self.setup_indexes()
        self.reindex_and_refresh()

        # r2.document should come first with 1 vote.
        response = self.client.get(
            reverse("search.advanced"), {"w": "1", "a": "1", "sortby_documents": "helpful", "format": "json"}
        )
        eq_(200, response.status_code)

        content = json.loads(response.content)
        eq_(r2.document.title, content["results"][0]["title"])

        # Vote twice on r1, now it should come first.
        HelpfulVoteFactory(revision=r1, helpful=True)
        HelpfulVoteFactory(revision=r1, helpful=True)

        self.setup_indexes()
        self.reindex_and_refresh()

        response = self.client.get(
            reverse("search.advanced"), {"w": "1", "a": "1", "sortby_documents": "helpful", "format": "json"}
        )
        eq_(200, response.status_code)

        content = json.loads(response.content)
        eq_(r1.document.title, content["results"][0]["title"])
Exemplo n.º 25
0
Arquivo: views.py Projeto: jdm/kitsune
def new_message(request, template):
    """Send a new private message."""
    to = request.GET.get("to")
    if to:
        try:
            User.objects.get(username=to)
        except User.DoesNotExist:
            contrib_messages.add_message(
                request, contrib_messages.ERROR, _("Invalid username provided. Enter a new username below.")
            )
            return HttpResponseRedirect(reverse("messages.new"))

    form = MessageForm(request.POST or None, initial={"to": to})

    if (
        request.method == "POST"
        and form.is_valid()
        and not is_ratelimited(request, increment=True, rate="50/d", ip=False, keys=user_or_ip("private-message-day"))
    ):
        send_message(form.cleaned_data["to"], form.cleaned_data["message"], request.user)
        if form.cleaned_data["in_reply_to"]:
            irt = form.cleaned_data["in_reply_to"]
            try:
                m = InboxMessage.objects.get(pk=irt, to=request.user)
                m.update(replied=True)
            except InboxMessage.DoesNotExist:
                pass
        contrib_messages.add_message(request, contrib_messages.SUCCESS, _("Your message was sent!"))
        return HttpResponseRedirect(reverse("messages.inbox"))

    return render(request, template, {"form": form})
Exemplo n.º 26
0
    def test_filter_by_doctype(self):
        desktop = ProductFactory(slug=u'desktop')
        ques = QuestionFactory(title=u'audio', product=desktop)
        ans = AnswerFactory(question=ques, content=u'volume')
        AnswerVoteFactory(answer=ans, helpful=True)

        doc = DocumentFactory(title=u'audio', locale=u'en-US', category=10, products=[desktop])
        RevisionFactory(document=doc, is_approved=True)

        doc = DocumentFactory(title=u'audio too', locale=u'en-US', category=10, products=[desktop])
        RevisionFactory(document=doc, is_approved=True)

        self.refresh()

        # There should be 2 results for kb (w=1) and 1 for questions (w=2).
        response = self.client.get(reverse('search'), {
            'q': 'audio', 'format': 'json', 'w': '1'})
        eq_(200, response.status_code)
        content = json.loads(response.content)
        eq_(content['total'], 2)

        response = self.client.get(reverse('search'), {
            'q': 'audio', 'format': 'json', 'w': '2'})
        eq_(200, response.status_code)
        content = json.loads(response.content)
        eq_(content['total'], 1)
Exemplo n.º 27
0
    def test_product_filter(self):
        """Test filtering results by product."""
        today = date.today()

        # Create products and associated wiki metrics.
        p1 = ProductFactory()
        p2 = ProductFactory()

        # Create 3 for each product:
        for i in range(3):
            for p in [p1, p2]:
                WikiMetricFactory(date=today - timedelta(days=i), product=p)
        # Create one more for p2.
        WikiMetricFactory(date=today - timedelta(days=4), product=p2)

        # Call and verify the API for product=p1.
        response = self.client.get(
            urlparams(reverse('api.wikimetric_list'), format='json',
                      product=p1.slug))
        eq_(200, response.status_code)

        results = json.loads(response.content)['results']
        eq_(3, len(results))

        # Call and verify the API for product=p1.
        response = self.client.get(
            urlparams(reverse('api.wikimetric_list'), format='json',
                      product=p2.slug))
        eq_(200, response.status_code)

        results = json.loads(response.content)['results']
        eq_(4, len(results))
Exemplo n.º 28
0
    def test_filter_by_doctype(self):
        desktop = product(slug=u'desktop', save=True)
        ques = question(title=u'audio', product=desktop, save=True)
        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(desktop)
        revision(document=doc, is_approved=True, save=True)

        doc = document(
            title=u'audio too', locale=u'en-US', category=10, save=True)
        doc.products.add(desktop)
        revision(document=doc, is_approved=True, save=True)

        self.refresh()

        # There should be 2 results for kb (w=1) and 1 for questions (w=2).
        response = self.client.get(reverse('search'), {
            'q': 'audio', 'format': 'json', 'w': '1'})
        eq_(200, response.status_code)
        content = json.loads(response.content)
        eq_(content['total'], 2)

        response = self.client.get(reverse('search'), {
            'q': 'audio', 'format': 'json', 'w': '2'})
        eq_(200, response.status_code)
        content = json.loads(response.content)
        eq_(content['total'], 1)
Exemplo n.º 29
0
    def test_filter_by_product(self):
        desktop = ProductFactory(slug=u'desktop')
        mobile = ProductFactory(slug=u'mobile')
        ques = QuestionFactory(title=u'audio', product=desktop)
        ans = AnswerFactory(question=ques, content=u'volume')
        AnswerVoteFactory(answer=ans, helpful=True)

        doc = DocumentFactory(title=u'audio', locale=u'en-US', category=10)
        doc.products.add(desktop)
        doc.products.add(mobile)
        RevisionFactory(document=doc, is_approved=True)

        self.refresh()

        # There should be 2 results for desktop and 1 for mobile.
        response = self.client.get(reverse('search'), {
            'q': 'audio', 'format': 'json', 'product': 'desktop'})
        eq_(200, response.status_code)
        content = json.loads(response.content)
        eq_(content['total'], 2)

        response = self.client.get(reverse('search'), {
            'q': 'audio', 'format': 'json', 'product': 'mobile'})
        eq_(200, response.status_code)
        content = json.loads(response.content)
        eq_(content['total'], 1)
Exemplo n.º 30
0
    def test_weekly_solutions(self):
        eight_days_ago = datetime.now() - timedelta(days=8)
        # First one is a solution, but it is too old.
        # second answer is not a solution.
        SolutionAnswerFactory(created=eight_days_ago)
        AnswerFactory()
        res = self.client.get(reverse('user-weekly-solutions'))
        eq_(res.status_code, 200)
        eq_(len(res.data), 0)

        # Check that the data about the contributors is showing currectly
        user_info_list = []  # Info list with username and their number of solutions
        top_answer_number = 15
        for i in range(12):
            user = UserFactory()
            SolutionAnswerFactory.create_batch(top_answer_number, creator=user)
            user_info_list.append((user.username, top_answer_number))
            top_answer_number -= 1

        res = self.client.get(reverse('user-weekly-solutions'))
        eq_(res.status_code, 200)
        # Check only 10 users information is present there
        eq_(len(res.data), 10)
        # Create a list of the data with only the ``username`` and ``weekly_solutions``
        data_list = [(data['username'], data['weekly_solutions']) for data in res.data]

        # Check only top 10 contributor information is in the API
        top_ten = user_info_list[:10]
        eq_(sorted(top_ten), sorted(data_list))
Exemplo n.º 31
0
 def get_absolute_url(self):
     # Note: If this function changes, we need to change it in
     # extract_document, too.
     return reverse('questions.answers', kwargs={'question_id': self.id})
Exemplo n.º 32
0
 def get_absolute_url(self):
     return reverse('wiki.document', locale=self.locale, args=[self.slug])
Exemplo n.º 33
0
 def get_absolute_url(self):
     return reverse('wiki.locale_details', args=[self.locale])
Exemplo n.º 34
0
 def get_absolute_url(self):
     return reverse('wiki.revision',
                    locale=self.document.locale,
                    args=[self.document.slug, self.id])
Exemplo n.º 35
0
 def setUp(self):
     url = reverse('forums.threads', args=[u'test-forum'])
     self.context = {'request': RequestFactory().get(url)}
Exemplo n.º 36
0
 def get_absolute_url(self):
     return reverse("users.profile", args=[self.pk])
Exemplo n.º 37
0
    def extract_document(cls, obj_id, obj=None):
        """Extracts indexable attributes from a Question and its answers."""
        fields = [
            'id', 'title', 'content', 'num_answers', 'solution_id',
            'is_locked', 'created', 'updated', 'num_votes_past_week', 'locale'
        ]
        composed_fields = ['creator__username']
        all_fields = fields + composed_fields

        if obj is None:
            # Note: Need to keep this in sync with
            # tasks.update_question_vote_chunk.
            model = cls.get_model()
            obj = model.uncached.values(*all_fields).get(pk=obj_id)
        else:
            fixed_obj = dict([(field, getattr(obj, field))
                              for field in fields])
            fixed_obj['creator__username'] = obj.creator.username
            obj = fixed_obj

        d = {}
        d['id'] = obj['id']
        d['model'] = cls.get_mapping_type_name()

        # We do this because get_absolute_url is an instance method
        # and we don't want to create an instance because it's a DB
        # hit and expensive. So we do it by hand. get_absolute_url
        # doesn't change much, so this is probably ok.
        d['url'] = reverse('questions.answers',
                           kwargs={'question_id': obj['id']})

        d['indexed_on'] = int(time.time())

        d['created'] = int(time.mktime(obj['created'].timetuple()))
        d['updated'] = int(time.mktime(obj['updated'].timetuple()))

        topics = Topic.uncached.filter(question__id=obj['id'])
        products = Product.uncached.filter(question__id=obj['id'])
        d['topic'] = [t.slug for t in topics]
        d['product'] = [p.slug for p in products]

        d['question_title'] = obj['title']
        d['question_content'] = obj['content']
        d['question_num_answers'] = obj['num_answers']
        d['question_is_solved'] = bool(obj['solution_id'])
        d['question_is_locked'] = obj['is_locked']
        d['question_has_answers'] = bool(obj['num_answers'])

        d['question_creator'] = obj['creator__username']
        d['question_num_votes'] = (QuestionVote.objects.filter(
            question=obj['id']).count())
        d['question_num_votes_past_week'] = obj['num_votes_past_week']

        d['question_tag'] = list(
            TaggedItem.tags_for(Question,
                                Question(pk=obj_id)).values_list('name',
                                                                 flat=True))

        d['question_locale'] = obj['locale']

        answer_values = list(
            Answer.objects.filter(question=obj_id).values_list(
                'content', 'creator__username'))

        d['question_answer_content'] = [a[0] for a in answer_values]
        d['question_answer_creator'] = list(set(a[1] for a in answer_values))

        if not answer_values:
            d['question_has_helpful'] = False
        else:
            d['question_has_helpful'] = Answer.objects.filter(
                question=obj_id).filter(votes__helpful=True).exists()

        return d
Exemplo n.º 38
0
 def test_xframe_options_deny_not_minimal(self):
     url = reverse('wiki.document', args=[self.doc.slug], locale='en-US')
     res = self.client.get(url)
     eq_(res['X-Frame-Options'], 'DENY')
Exemplo n.º 39
0
 def test_only_if_mobile(self):
     url = reverse('wiki.document', args=[self.doc.slug], locale='en-US')
     url += '?minimal=1'
     res = self.client.get(url)
     self.assertTemplateUsed(res, 'wiki/document.html')
Exemplo n.º 40
0
 def test_it_works(self):
     url = reverse('wiki.document', args=[self.doc.slug], locale='en-US')
     res = self.client.get(url)
     eq_(res.status_code, 200)
     self.assertTemplateUsed(res, 'wiki/mobile/document.html')
Exemplo n.º 41
0
 def test_doc_lock_workflow(self):
     """End to end test of locking on an english document."""
     doc, rev = doc_rev()
     url = reverse('wiki.edit_document', args=[doc.slug], locale='en-US')
     self._lock_workflow(doc, url)
Exemplo n.º 42
0
 def test_xframe_options(self):
     url = reverse('wiki.document', args=[self.doc.slug], locale='en-US')
     url += '?minimal=1&mobile=1'
     res = self.client.get(url)
     # If it is not set to "DENY", then it is allowed.
     eq_(res.get('X-Frame-Options', 'ALLOW').lower(), 'allow')
Exemplo n.º 43
0
 def test_helpful_vote_no_id(self):
     """Throw helpful_vote a POST without an ID and see if it 400s."""
     response = self.client.post(reverse('wiki.document_vote', args=['hi']),
                                 {})
     eq_(400, response.status_code)
Exemplo n.º 44
0
 def test_it_works(self):
     url = reverse('wiki.document', args=[self.doc.slug], locale='en-US')
     url += '?minimal=1&mobile=1'
     res = self.client.get(url)
     self.assertTemplateUsed(res, 'wiki/mobile/document-minimal.html')
Exemplo n.º 45
0
 def test_while_there_is_no_parent_slug(self):
     doc = DocumentFactory(locale=settings.WIKI_DEFAULT_LANGUAGE)
     invalid_slug = doc.slug + 'invalid_slug'
     url = reverse('wiki.edit_document', args=[invalid_slug], locale='bn-BD')
     response = self.client.get(url)
     eq_(response.status_code, 404)
Exemplo n.º 46
0
 def test_fallback_with_query_params(self):
     """The query parameters should be passed along to the redirect."""
     en_doc, de_doc = self._create_en_and_de_docs()
     url = reverse('wiki.document', args=[en_doc.slug], locale='de')
     response = self.client.get(url + '?x=y&x=z', follow=True)
     self.assertRedirects(response, de_doc.get_absolute_url() + '?x=y&x=z')
Exemplo n.º 47
0
 def test_GET(self):
     r = self.client.get(reverse('users.edit_watch_list'))
     eq_(200, r.status_code)
     assert u'question: ' + self.question.title in r.content.decode('utf8')
Exemplo n.º 48
0
 def test_helpful_vote_bad_id(self):
     """Throw helpful_vote a bad ID, and see if it crashes."""
     response = self.client.post(reverse('wiki.document_vote', args=['hi']),
                                 {'revision_id': 'x'})
     eq_(404, response.status_code)
Exemplo n.º 49
0
 def setUp(self):
     super(PasswordChangeTests, self).setUp()
     self.u = UserFactory()
     self.url = reverse('users.pw_change')
     self.new_pw = 'fjdka387fvstrongpassword!'
     self.client.login(username=self.u.username, password='******')
Exemplo n.º 50
0
 def test_json_view_404(self):
     """Searching for something that doesn't exist should 404."""
     url = reverse('wiki.json', force_locale=True)
     resp = self.client.get(url, {'title': 'an article title ok.'})
     eq_(404, resp.status_code)
Exemplo n.º 51
0
 def test_bad_email(self):
     r = self.client.post(reverse('users.pw_reset'),
                          {'email': '*****@*****.**'})
     eq_(302, r.status_code)
     eq_('http://testserver/en-US/users/pwresetsent', r['location'])
     eq_(0, len(mail.outbox))
Exemplo n.º 52
0
 def test_GET(self):
     r = self.client.get(reverse('users.forgot_username'))
     eq_(200, r.status_code)
Exemplo n.º 53
0
 def test_no_signature(self):
     response = self.client.get(reverse('postcrash.api'))
     eq_(400, response.status_code)
     eq_(b'', response.content)
     eq_('text/plain', response['content-type'])
Exemplo n.º 54
0
 def _get_reset_url(self):
     return reverse('users.pw_reset_confirm',
                    args=[self.uidb36, self.token])
Exemplo n.º 55
0
 def test_search_type_param(self):
     """Ensure that invalid values for search type (a=)
     does not cause errors"""
     response = self.client.get(reverse('search'), {'a': 'dontdie'})
     eq_('text/html; charset=utf-8', response['Content-Type'])
     eq_(200, response.status_code)
Exemplo n.º 56
0
 def test_login_mobile_csrf(self):
     """The mobile registration view should have a CSRF token."""
     response = self.client.get(reverse('users.register'), {'mobile': 1})
     eq_(200, response.status_code)
     doc = pq(response.content)
     assert doc('#content form input[name="csrfmiddlewaretoken"]')
Exemplo n.º 57
0
 def test_content(self):
     """Ensure template is rendered with no errors for a common search"""
     response = self.client.get(reverse('search'), {'q': 'audio'})
     eq_('text/html; charset=utf-8', response['Content-Type'])
     eq_(200, response.status_code)
Exemplo n.º 58
0
 def test_unknown_signature(self):
     url = urlparams(reverse('postcrash.api'), s='foo')
     response = self.client.get(url)
     eq_(404, response.status_code)
     eq_(b'', response.content)
     eq_('text/plain', response['content-type'])
Exemplo n.º 59
0
 def setUp(self):
     super(LoginTests, self).setUp()
     self.u = UserFactory()
     self.profile_url = reverse('users.profile',
                                args=[self.u.username],
                                locale=settings.LANGUAGE_CODE) + '?fpa=1'
Exemplo n.º 60
0
 def test_content_mobile(self):
     """Ensure mobile template is rendered."""
     self.client.cookies[settings.MOBILE_COOKIE] = 'on'
     response = self.client.get(reverse('search'), {'q': 'audio'})
     eq_('text/html; charset=utf-8', response['Content-Type'])
     eq_(200, response.status_code)