Exemple #1
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])
    def test_autowatch_reply(self, get_current):
        """Replying to a thread creates a watch."""
        get_current.return_value.domain = 'testserver'

        u = user(save=True)
        t1 = thread(save=True)
        t2 = thread(save=True)

        assert not NewPostEvent.is_notifying(u, t1)
        assert not NewPostEvent.is_notifying(u, t2)

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

        # If the poster has the forums_watch_after_reply setting set to True,
        # they will start watching threads they reply to.
        s = Setting.objects.create(user=u, name='forums_watch_after_reply',
                                   value='True')
        data = {'content': 'some content'}
        post(self.client, 'forums.reply', data, args=[t1.forum.slug, t1.pk])
        assert NewPostEvent.is_notifying(u, t1)

        # Setting forums_watch_after_reply back to False, now they shouldn't
        # start watching threads they reply to.
        s.value = 'False'
        s.save()
        post(self.client, 'forums.reply', data, args=[t2.forum.slug, t2.pk])
        assert not NewPostEvent.is_notifying(u, t2)
    def test_move_updates_last_posts(self):
        """Moving the thread containing a forum's last post to a new forum
        should update the last_post of both forums. Consequently, deleting
        the last post shouldn't delete the old forum. [bug 588994]"""
        # Setup forum to move latest thread from.
        old_forum = forum(save=True)
        t1 = thread(forum=old_forum, save=True)
        p1 = post(thread=t1, created=YESTERDAY, save=True)
        t2 = thread(forum=old_forum, save=True)
        p2 = post(thread=t2, save=True)  # Newest post of all.

        # Setup forum to move latest thread to.
        new_forum = forum(save=True)
        t3 = thread(forum=new_forum, save=True)
        p3 = post(thread=t3, created=YESTERDAY, save=True)

        # Verify the last_post's are correct.
        eq_(p2, Forum.objects.get(id=old_forum.id).last_post)
        eq_(p3, Forum.objects.get(id=new_forum.id).last_post)

        # Move the t2 thread.
        t2 = Thread.objects.get(id=t2.id)
        t2.forum = new_forum
        t2.save()

        # Old forum's last_post updated?
        eq_(p1.id, Forum.objects.get(id=old_forum.id).last_post_id)

        # New forum's last_post updated?
        eq_(p2.id, Forum.objects.get(id=new_forum.id).last_post_id)

        # Delete the post, and both forums should still exist:
        p2.delete()
        eq_(1, Forum.objects.filter(id=old_forum.id).count())
        eq_(1, Forum.objects.filter(id=new_forum.id).count())
Exemple #4
0
 def test_sorting_creator(self):
     """Sorting threads by creator."""
     thread(creator=user(username='******', save=True), save=True)
     thread(creator=user(username='******', save=True), save=True)
     threads = sort_threads(Thread.objects, 3, 1)
     self.assert_(threads[0].creator.username >=
                  threads[1].creator.username)
Exemple #5
0
    def test_discussion_filter_forum(self):
        """Filter by forum in discussion forums."""
        forum1 = forum(name=u'Forum 1', save=True)
        thread1 = thread(forum=forum1, title=u'audio 1', save=True)
        post(thread=thread1, save=True)

        forum2 = forum(name=u'Forum 2', save=True)
        thread2 = thread(forum=forum2, title=u'audio 2', save=True)
        post(thread=thread2, save=True)

        import search.forms
        reload(search.forms)
        import search.views
        import search.forms
        search.views.SearchForm = search.forms.SearchForm

        # Wait... reload? WTF is that about? What's going on here is
        # that SearchForm pulls the list of forums from the db **at
        # module load time**. Since we need it to include the two
        # forums we just created, we need to reload the module and
        # rebind it in search.views. Otherwise when we go to get
        # cleaned_data from it, it ditches the forum data we so
        # lovingly put in our querystring and then our filters are
        # wrong and then this test FAILS.

        self.refresh()

        qs = {'a': 1, 'w': 4, 'format': 'json'}

        for forum_id in (forum1.id, forum2.id):
            qs['forum'] = int(forum_id)
            response = self.client.get(reverse('search'), qs)
            eq_(json.loads(response.content)['total'], 1)
 def test_has_perm_or_owns_thread_edit(self):
     """Users can edit their own threads."""
     my_t = thread(save=True)
     me = my_t.creator
     other_t = thread(save=True)
     self.context['request'].user = me
     perm = 'forums_forum.thread_edit_forum'
     assert has_perm_or_owns(self.context, perm, my_t, self.forum_1)
     assert not has_perm_or_owns(self.context, perm, other_t, self.forum_1)
Exemple #7
0
    def test_locked_thread(self):
        """Trying to reply to a locked thread should raise an exception."""
        locked = thread(is_locked=True, save=True)
        unlocked = thread(save=True)
        user1 = user(save=True)
        fn = lambda: locked.new_post(author=user1, content='empty')
        self.assertRaises(ThreadLockedError, fn)

        # This should not raise an exception.
        unlocked.new_post(author=user1, content='empty')
Exemple #8
0
    def test_threads_sort(self):
        """Ensure that threads are being sorted properly by date/time."""
        # Threads are sorted descending by last post date.
        f = forum(save=True)
        t1 = thread(forum=f, created=YESTERDAY, save=True)
        post(thread=t1, created=YESTERDAY, save=True)
        t2 = thread(forum=f, save=True)
        post(thread=t2, save=True)

        eq_(t2.id, ThreadsFeed().items(f)[0].id)
Exemple #9
0
    def test_new_thread_without_view_permission(self):
        """Making a new thread without view permission should 404."""
        restricted_forum = _restricted_forum()
        thread(forum=restricted_forum, save=True)
        u = user(save=True)

        self.client.login(username=u.username, password='******')
        response = post(self.client, 'forums.new_thread',
                        {'title': 'Blahs', 'content': 'Blahs'},
                        args=[restricted_forum.slug])
        eq_(404, response.status_code)
    def test_watch_other_thread_then_reply(self):
        """Watching a different thread than the one we're replying to shouldn't
        notify."""
        t1 = thread(save=True)
        t2 = thread(save=True)
        poster = user(save=True)
        watcher = user(save=True)

        self._toggle_watch_thread_as(t1, watcher, turn_on=True)
        self.client.login(username=poster.username, password='******')
        post(self.client, 'forums.reply', {'content': 'a post'},
             args=[t2.forum.slug, t2.id])

        assert not mail.outbox
Exemple #11
0
    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_watch_both_then_new_post(self, get_current):
        """Watching both forum and thread.

        Replying to a thread should send ONE email."""
        get_current.return_value.domain = 'testserver'

        t = thread(save=True)
        f = t.forum
        forum_post(thread=t, save=True)
        poster = user(save=True)
        watcher = user(save=True)

        self._toggle_watch_forum_as(f, watcher, turn_on=True)
        self._toggle_watch_thread_as(t, watcher, turn_on=True)
        self.client.login(username=poster.username, password='******')
        post(self.client, 'forums.reply', {'content': 'a post'},
             args=[f.slug, t.id])

        eq_(1, len(mail.outbox))
        p = Post.objects.all().order_by('-id')[0]
        attrs_eq(mail.outbox[0], to=[watcher.email],
                 subject='Re: {f} - {t}'.format(f=f, t=t))
        body = REPLY_EMAIL.format(
            username=poster.username,
            forum_slug=f.slug,
            thread_title=t.title,
            thread_id=t.id,
            post_id=p.id)
        starts_with(mail.outbox[0].body, body)
Exemple #13
0
    def test_front_page_only_shows_wiki_and_questions(self):
        """Tests that the front page 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

        """
        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)

        doc = document(title=u"audio", locale=u"en-US", category=10, save=True)
        doc.products.add(product(slug=u"desktop", save=True))
        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_tags": "desktop", "product": "desktop", "q": "audio", "format": "json"}
        )

        eq_(200, response.status_code)

        content = json.loads(response.content)
        eq_(content["total"], 2)
Exemple #14
0
    def test_forums_search(self):
        """This tests whether forum posts show up in searches"""
        thread1 = thread(title=u"crash", save=True)
        post(thread=thread1, save=True)

        self.refresh()

        response = self.client.get(
            reverse("search"),
            {
                "author": "",
                "created": "0",
                "created_date": "",
                "updated": "0",
                "updated_date": "",
                "sortby": "0",
                "a": "1",
                "w": "4",
                "q": "crash",
                "format": "json",
            },
        )

        eq_(200, response.status_code)

        content = json.loads(response.content)
        eq_(content["total"], 1)
Exemple #15
0
    def test_delete_post_belongs_to_thread_and_forum(self):
        """
        Delete post action - post belongs to thread and thread belongs to
        forum.
        """
        f = forum(save=True)
        t = thread(forum=f, save=True)
        # Post belongs to a different forum and thread.
        p = forum_post(save=True)
        u = p.author

        # Give the user the permission to delete posts.
        g = group(save=True)
        ct = ContentType.objects.get_for_model(f)
        permission(codename='forums_forum.post_delete_forum',
                   content_type=ct, object_id=p.thread.forum_id, group=g,
                   save=True)
        permission(codename='forums_forum.post_delete_forum',
                   content_type=ct, object_id=f.id, group=g, save=True)
        g.user_set.add(u)

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

        # Post isn't in the passed forum:
        r = get(self.client, 'forums.delete_post',
                args=[f.slug, p.thread.id, p.id])
        eq_(404, r.status_code)

        # Post isn't in the passed thread:
        r = get(self.client, 'forums.delete_post',
                args=[p.thread.forum.slug, t.id, p.id])
        eq_(404, r.status_code)
Exemple #16
0
 def test_save_thread_no_created(self):
     """Saving a new thread should behave as if auto_add_now was set."""
     t = thread(forum=self.forum, title='foo', creator=self.user,
                save=True)
     t.save()
     now = datetime.now()
     self.assertDateTimeAlmostEqual(now, t.created, self.delta)
Exemple #17
0
    def test_read_without_permission(self):
        """Listing posts without the view_in_forum permission should 404."""
        restricted_forum = _restricted_forum()
        t = thread(forum=restricted_forum, save=True)

        response = get(self.client, 'forums.posts', args=[t.forum.slug, t.id])
        eq_(404, response.status_code)
Exemple #18
0
 def test_save_thread_created(self):
     # Saving a new thread that already has a created date should
     # respect that created date.
     created = datetime(1992, 1, 12, 9, 48, 23)
     t = thread(forum=self.forum, title='foo', creator=self.user,
                created=created, save=True)
     t.save()
     eq_(created, t.created)
Exemple #19
0
    def test_delete_last_and_only_post_in_thread(self):
        """Deleting the only post in a thread should delete the thread"""
        t = thread(save=True)
        post(thread=t, save=True)

        eq_(1, t.post_set.count())
        t.delete()
        eq_(0, Thread.uncached.filter(pk=t.id).count())
Exemple #20
0
 def test_update_forum_does_not_update_thread(self):
     """Updating/saving an old post in a forum should _not_ update the
     last_post key in that forum."""
     t = thread(save=True)
     old = post(thread=t, save=True)
     last = post(thread=t, save=True)
     old.content = 'updated content'
     old.save()
     eq_(last.id, t.forum.last_post_id)
Exemple #21
0
 def test_new_post_updates_forum(self):
     """Saving a new post should update the last_post key in the forum to
     point to the new post."""
     t = thread(save=True)
     post(thread=t, save=True)
     p = t.new_post(author=t.creator, content='another update')
     p.save()
     f = Forum.objects.get(id=t.forum_id)
     eq_(p.id, f.last_post_id)
Exemple #22
0
 def test_new_post_updates_thread(self):
     """Saving a new post in a thread should update the last_post key in
     that thread to point to the new post."""
     t = thread(save=True)
     post(thread=t, save=True)
     p = t.new_post(author=t.creator, content='an update')
     p.save()
     t = Thread.objects.get(id=t.id)
     eq_(p.id, t.last_post_id)
Exemple #23
0
 def test_sorting_replies(self):
     """Sorting threads by replies."""
     t = thread(save=True)
     post(thread=t, save=True)
     post(thread=t, save=True)
     post(thread=t, save=True)
     post(save=True)
     threads = sort_threads(Thread.objects, 4)
     self.assert_(threads[0].replies <= threads[1].replies)
Exemple #24
0
    def test_sticky_threads_first(self):
        """Sticky threads should come before non-sticky threads."""
        t = post(save=True).thread
        sticky = thread(forum=t.forum, is_sticky=True, save=True)
        yesterday = datetime.now() - timedelta(days=1)
        post(thread=sticky, created=yesterday, save=True)

        # The older sticky thread shows up first.
        eq_(sticky.id, Thread.objects.all()[0].id)
Exemple #25
0
    def test_reply_thread_405(self):
        """Replying to a thread via a GET instead of a POST request."""
        t = thread(save=True)
        u = user(save=True)

        self.client.login(username=u.username, password='******')
        response = get(self.client, 'forums.reply',
                       args=[t.forum.slug, t.id])
        eq_(405, response.status_code)
Exemple #26
0
    def test_posts_sort(self):
        """Ensure that posts are being sorted properly by date/time."""
        t = thread(save=True)
        post(thread=t, created=YESTERDAY, save=True)
        post(thread=t, created=YESTERDAY, save=True)
        p = post(thread=t, save=True)

        # The newest post should be the first one listed.
        eq_(p.id, PostsFeed().items(t)[0].id)
Exemple #27
0
    def test_posts_thread_belongs_to_forum(self):
        """Posts view - redirect if thread does not belong to forum."""
        f = forum(save=True)
        t = thread(save=True)  # Thread belongs to a different forum

        r = get(self.client, 'forums.posts', args=[f.slug, t.id])
        eq_(200, r.status_code)
        u = r.redirect_chain[0][0]
        assert u.endswith(t.get_absolute_url())
Exemple #28
0
    def test_reply_thread_belongs_to_forum(self):
        """Reply action - thread belongs to forum."""
        f = forum(save=True)
        t = thread(save=True)  # Thread belongs to a different forum
        u = user(save=True)

        self.client.login(username=u.username, password='******')
        r = post(self.client, 'forums.reply', {}, args=[f.slug, t.id])
        eq_(404, r.status_code)
Exemple #29
0
    def test_long_title_truncated_in_crumbs(self):
        """A very long thread title gets truncated in the breadcrumbs"""
        t = thread(title='A thread with a very very long title', save=True)
        forum_post(thread=t, save=True)

        response = get(self.client, 'forums.posts', args=[t.forum.slug, t.id])
        doc = pq(response.content)
        crumb = doc('#breadcrumbs li:last-child')
        eq_(crumb.text(), 'A thread with a very very ...')
 def test_fire_on_reply(self, fire):
     """The event fires when there is a reply."""
     u = user(save=True)
     t = thread(save=True)
     self.client.login(username=u.username, password='******')
     post(self.client, 'forums.reply', {'content': 'a post'},
          args=[t.forum.slug, t.id])
     # NewPostEvent.fire() is called.
     assert fire.called
Exemple #31
0
    def test_watch_thread_without_permission(self):
        """Watching threads without the view_in_forum permission should 404."""
        restricted_forum = _restricted_forum()
        t = thread(forum=restricted_forum, save=True)
        u = user(save=True)

        self.client.login(username=u.username, password='******')
        response = self.client.post(reverse('forums.watch_thread',
                                            args=[t.forum.slug, t.id]),
                                    {'watch': 'yes'},
                                    follow=False)
        eq_(404, response.status_code)
Exemple #32
0
    def test_created_date_invalid(self):
        """Invalid created_date is ignored."""
        thread1 = thread(save=True)
        post(thread=thread1, save=True)

        self.refresh()

        qs = {'a': 1, 'w': 4, 'format': 'json',
              'created': constants.INTERVAL_AFTER,
              'created_date': 'invalid'}
        response = self.client.get(reverse('search'), qs)
        eq_(1, json.loads(response.content)['total'])
Exemple #33
0
    def test_thread_sorting(self):
        """After the sticky threads, threads should be sorted by the created
        date of the last post."""
        # Make sure the datetimes are different.
        post(created=datetime.now() - timedelta(days=1), save=True)
        post(save=True)
        t = thread(is_sticky=True, save=True)
        post(thread=t, save=True)

        threads = Thread.objects.filter(is_sticky=False)
        self.assert_(
            threads[0].last_post.created > threads[1].last_post.created)
Exemple #34
0
    def test_discussion_filter_locked(self):
        """Filter for locked threads."""
        thread1 = thread(title=u'audio', is_locked=True,
                         save=True)
        post(thread=thread1, save=True)

        self.refresh()

        qs = {'a': 1, 'w': 4, 'format': 'json', 'thread_type': 2}
        response = self.client.get(reverse('search'), qs)
        results = json.loads(response.content)['results']
        eq_(len(results), 1)
Exemple #35
0
    def test_save_old_thread_created(self):
        """Saving an old thread should not change its created date."""
        t = thread(created=YESTERDAY, save=True)
        t = Thread.objects.get(id=t.id)
        created = t.created

        # Now make an update to the thread and resave. Created shouldn't
        # change.
        t.title = 'new title'
        t.save()
        t = Thread.objects.get(id=t.id)
        eq_(created, t.created)
Exemple #36
0
    def test_discussion_filter_sticky_locked(self):
        """Filter for locked and sticky threads."""
        thread1 = thread(title=u'audio', is_locked=True, is_sticky=True,
                         save=True)
        post(thread=thread1, save=True)

        self.refresh()

        qs = {'a': 1, 'w': 4, 'format': 'json', 'thread_type': (1, 2)}
        response = self.client.get(reverse('search'), qs)
        result = json.loads(response.content)['results'][0]
        eq_(thread1.get_absolute_url(), result['url'])
Exemple #37
0
    def test_post_page(self):
        t = thread(save=True)
        # Fill out the first page with posts from yesterday.
        page1 = []
        for i in range(POSTS_PER_PAGE):
            page1.append(post(thread=t, created=YESTERDAY, save=True))
        # Second page post from today.
        p2 = post(thread=t, save=True)

        for p in page1:
            eq_(1, p.page)
        eq_(2, p2.page)
Exemple #38
0
 def test_save_thread_created(self):
     """
     Saving a new thread that already has a created date should respect
     that created date.
     """
     created = datetime(1992, 1, 12, 9, 48, 23)
     t = thread(forum=self.forum,
                title='foo',
                creator=self.user,
                created=created,
                save=True)
     t.save()
     eq_(created, t.created)
Exemple #39
0
    def test_reply_redirect(self):
        """Posting a reply should redirect."""
        t = thread(save=True)
        u = user(save=True)

        self.client.login(username=u.username, password='******')
        url = reverse('forums.reply', args=[t.forum.slug, t.id])
        data = {'content': 'some content'}
        r = self.client.post(url, data, follow=False)
        eq_(302, r.status_code)
        assert t.forum.slug in r['location']
        assert str(t.id) in r['location']
        assert 'last=' in r['location']
Exemple #40
0
    def test_reply_without_post_permission(self):
        """Posting without post_in_forum permission should 403."""
        restricted_forum = _restricted_forum(
            permission_code='forums_forum.post_in_forum')
        t = thread(forum=restricted_forum, save=True)
        u = user(save=True)

        self.client.login(username=u.username, password='******')
        with patch.object(Forum, 'allows_viewing_by', Mock(return_value=True)):
            response = post(self.client,
                            'forums.reply', {'content': 'Blahs'},
                            args=[t.forum.slug, t.id])
        eq_(403, response.status_code)
Exemple #41
0
    def test_move_updates_last_posts(self):
        # Moving the thread containing a forum's last post to a new
        # forum should update the last_post of both
        # forums. Consequently, deleting the last post shouldn't
        # delete the old forum. [bug 588994]

        # Setup forum to move latest thread from.
        old_forum = forum(save=True)
        t1 = thread(forum=old_forum, save=True)
        p1 = post(thread=t1, created=YESTERDAY, save=True)
        t2 = thread(forum=old_forum, save=True)
        p2 = post(thread=t2, save=True)  # Newest post of all.

        # Setup forum to move latest thread to.
        new_forum = forum(save=True)
        t3 = thread(forum=new_forum, save=True)
        p3 = post(thread=t3, created=YESTERDAY, save=True)

        # Verify the last_post's are correct.
        eq_(p2, Forum.objects.get(id=old_forum.id).last_post)
        eq_(p3, Forum.objects.get(id=new_forum.id).last_post)

        # Move the t2 thread.
        t2 = Thread.objects.get(id=t2.id)
        t2.forum = new_forum
        t2.save()

        # Old forum's last_post updated?
        eq_(p1.id, Forum.objects.get(id=old_forum.id).last_post_id)

        # New forum's last_post updated?
        eq_(p2.id, Forum.objects.get(id=new_forum.id).last_post_id)

        # Delete the post, and both forums should still exist:
        p2.delete()
        eq_(1, Forum.objects.filter(id=old_forum.id).count())
        eq_(1, Forum.objects.filter(id=new_forum.id).count())
Exemple #42
0
    def test_watch_forum_then_new_post_as_self(self, get_current):
        """Watching a forum and replying as myself should not send email."""
        get_current.return_value.domain = 'testserver'

        t = thread(save=True)
        f = t.forum
        forum_post(thread=t, save=True)
        watcher = user(save=True)

        self._toggle_watch_forum_as(f, watcher, turn_on=True)
        self.client.login(username=watcher.username, password='******')
        post(self.client, 'forums.reply', {'content': 'a post'},
             args=[f.slug, t.id])
        # Assert no email is sent.
        assert not mail.outbox
Exemple #43
0
    def test_watch_thread(self):
        """Watch then unwatch a thread."""
        t = thread(save=True)
        u = user(save=True)

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

        post(self.client, 'forums.watch_thread', {'watch': 'yes'},
             args=[t.forum.slug, t.id])
        assert NewPostEvent.is_notifying(u, t)
        # NewThreadEvent is not notifying.
        assert not NewThreadEvent.is_notifying(u, t.forum)

        post(self.client, 'forums.watch_thread', {'watch': 'no'},
             args=[t.forum.slug, t.id])
        assert not NewPostEvent.is_notifying(u, t)
Exemple #44
0
    def test_activity_logged(self):
        assert not Action.uncached.exists(), 'Actions start empty.'
        orig = user(save=True)
        replier = user(save=True)
        t = thread(creator=orig, title='foo', save=True)
        forum_post(author=orig, content='foo', thread=t, save=True)
        assert not Action.uncached.exists(), 'No actions were logged.'

        self.client.login(username=replier.username, password='******')
        post(self.client,
             'forums.reply', {'content': 'foo bar'},
             args=[t.forum.slug, t.id])
        eq_(1, Action.uncached.count(), 'One action was logged.')

        a = Action.uncached.all()[0]
        assert orig in a.users.all(), 'The original poster was notified.'
        assert not replier in a.users.all(), 'The replier was not notified.'
Exemple #45
0
    def test_watch_forum(self):
        """Watch then unwatch a forum."""
        f = forum(save=True)
        forum_post(thread=thread(forum=f, save=True), save=True)
        u = user(save=True)

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

        post(self.client, 'forums.watch_forum', {'watch': 'yes'},
             args=[f.slug])
        assert NewThreadEvent.is_notifying(u, f)
        # NewPostEvent is not notifying.
        assert not NewPostEvent.is_notifying(u, f.last_post)

        post(self.client, 'forums.watch_forum', {'watch': 'no'},
             args=[f.slug])
        assert not NewThreadEvent.is_notifying(u, f)
    def test_admin_delete_user_with_watched_thread(self, get_current):
        """Test the admin delete view for a user with a watched thread."""
        get_current.return_value.domain = 'testserver'

        t = thread(save=True)
        u = t.creator
        watcher = user(save=True)
        admin_user = user(is_staff=True, is_superuser=True, save=True)

        self.client.login(username=admin_user.username, password='******')
        self._toggle_watch_thread_as(t, watcher, turn_on=True)
        url = reverse('admin:auth_user_delete', args=[u.id])
        request = test_utils.RequestFactory().get(url)
        request.user = admin_user
        request.session = self.client.session
        # The following blows up without our monkeypatch.
        ModelAdmin(User, admin.site).delete_view(request, str(u.id))
Exemple #47
0
    def test_forums_search(self):
        """This tests whether forum posts show up in searches"""
        thread1 = thread(title=u'crash', save=True)
        post(thread=thread1, save=True)

        self.refresh()

        response = self.client.get(reverse('search'), {
            'author': '', 'created': '0', 'created_date': '',
            'updated': '0', 'updated_date': '', 'sortby': '0',
            'a': '1', 'w': '4', 'q': 'crash',
            'format': 'json'
        })

        eq_(200, response.status_code)

        content = json.loads(response.content)
        eq_(content['total'], 1)
Exemple #48
0
    def test_deleted(self):
        new_thread = thread()
        eq_(elasticutils.S(Thread).count(), 0)

        # Saving a new Thread does create a new document in the
        # index.
        new_thread.save()
        self.refresh()
        eq_(elasticutils.S(Thread).count(), 1)

        new_post = post(thread=new_thread)
        eq_(elasticutils.S(Thread).count(), 1)

        new_post.save()
        self.refresh()
        eq_(elasticutils.S(Thread).count(), 1)

        new_thread.delete()
        self.refresh()
        eq_(elasticutils.S(Thread).count(), 0)
Exemple #49
0
    def test_post_absolute_url(self):
        t = thread(save=True)

        # Fill out the first page with posts from yesterday.
        p1 = post(thread=t, created=YESTERDAY, save=True)
        for i in range(POSTS_PER_PAGE - 1):
            post(thread=t, created=YESTERDAY, save=True)
        # Second page post from today.
        p2 = post(thread=t, save=True)

        url = reverse('forums.posts',
                      kwargs={'forum_slug': p1.thread.forum.slug,
                              'thread_id': p1.thread.id})
        eq_(urlparams(url, hash='post-%s' % p1.id), p1.get_absolute_url())

        url = reverse('forums.posts',
                      kwargs={'forum_slug': p2.thread.forum.slug,
                              'thread_id': p2.thread.id})
        exp_ = urlparams(url, hash='post-%s' % p2.id, page=2)
        eq_(exp_, p2.get_absolute_url())
Exemple #50
0
    def test_deleted(self):
        new_thread = thread()
        eq_(ThreadMappingType.search().count(), 0)

        # Saving a new Thread does create a new document in the
        # index.
        new_thread.save()
        self.refresh()
        eq_(ThreadMappingType.search().count(), 1)

        new_post = post(thread=new_thread)
        eq_(ThreadMappingType.search().count(), 1)

        new_post.save()
        self.refresh()
        eq_(ThreadMappingType.search().count(), 1)

        new_thread.delete()
        self.refresh()
        eq_(ThreadMappingType.search().count(), 0)
Exemple #51
0
    def test_edit_post_belongs_to_thread_and_forum(self):
        # Edit post action - post belongs to thread and thread belongs
        # to forum.
        f = forum(save=True)
        t = thread(forum=f, save=True)
        # Post belongs to a different forum and thread.
        p = forum_post(save=True)
        u = p.author

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

        # Post isn't in the passed forum:
        r = get(self.client,
                'forums.edit_post',
                args=[f.slug, p.thread.id, p.id])
        eq_(404, r.status_code)

        # Post isn't in the passed thread:
        r = get(self.client,
                'forums.edit_post',
                args=[p.thread.forum.slug, t.id, p.id])
        eq_(404, r.status_code)
Exemple #52
0
    def test_delete_post_belongs_to_thread_and_forum(self):
        """
        Delete post action - post belongs to thread and thread belongs to
        forum.
        """
        f = forum(save=True)
        t = thread(forum=f, save=True)
        # Post belongs to a different forum and thread.
        p = forum_post(save=True)
        u = p.author

        # Give the user the permission to delete posts.
        g = group(save=True)
        ct = ContentType.objects.get_for_model(f)
        permission(codename='forums_forum.post_delete_forum',
                   content_type=ct,
                   object_id=p.thread.forum_id,
                   group=g,
                   save=True)
        permission(codename='forums_forum.post_delete_forum',
                   content_type=ct,
                   object_id=f.id,
                   group=g,
                   save=True)
        g.user_set.add(u)

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

        # Post isn't in the passed forum:
        r = get(self.client,
                'forums.delete_post',
                args=[f.slug, p.thread.id, p.id])
        eq_(404, r.status_code)

        # Post isn't in the passed thread:
        r = get(self.client,
                'forums.delete_post',
                args=[p.thread.forum.slug, t.id, p.id])
        eq_(404, r.status_code)
Exemple #53
0
    def test_discussion_filter_author(self):
        """Filter by author in discussion forums."""
        author_vals = (
            ('DoesNotExist', 0),
            ('admin', 1),
            ('jsocol', 4),
        )

        for name, number in author_vals:
            u = user(username=name, save=True)
            for i in range(number):
                thread1 = thread(title=u'audio', save=True)
                post(thread=thread1, author=u, save=True)

        self.refresh()

        qs = {'a': 1, 'w': 4, 'format': 'json'}

        for author, total in author_vals:
            qs.update({'author': author})
            response = self.client.get(reverse('search'), qs)
            eq_(total, json.loads(response.content)['total'])
Exemple #54
0
    def test_added(self):
        new_thread = thread()
        eq_(ThreadMappingType.search().count(), 0)

        # Saving a new Thread does create a new document in the
        # index.
        new_thread.save()
        self.refresh()
        eq_(ThreadMappingType.search().count(), 1)

        new_post = post(thread=new_thread)
        eq_(ThreadMappingType.search().count(), 1)

        new_post.save()
        self.refresh()

        # Saving a new post in a thread doesn't create a new
        # document in the index.  Therefore, the count remains 1.
        #
        # TODO: This is ambiguous: it's not clear whether we correctly
        # updated the document in the index or whether the post_save
        # hook didn't kick off.  Need a better test.
        eq_(ThreadMappingType.search().count(), 1)
Exemple #55
0
    def test_watch_thread_then_reply(self, get_current):
        """The event fires and sends emails when watching a thread."""
        get_current.return_value.domain = 'testserver'

        t = thread(save=True)
        f = t.forum
        poster = user(save=True)
        watcher = user(save=True)

        self._toggle_watch_thread_as(t, watcher, turn_on=True)
        self.client.login(username=poster.username, password='******')
        post(self.client, 'forums.reply', {'content': 'a post'},
             args=[t.forum.slug, t.id])

        p = Post.objects.all().order_by('-id')[0]
        attrs_eq(mail.outbox[0], to=[watcher.email],
                 subject='Re: {f} - {t}'.format(f=f, t=t))
        body = REPLY_EMAIL.format(
            username=poster.username,
            forum_slug=f.slug,
            thread_title=t.title,
            thread_id=t.id,
            post_id=p.id)
        starts_with(mail.outbox[0].body, body)
Exemple #56
0
    def test_delete_thread_belongs_to_forum(self):
        """Delete thread action - thread belongs to forum."""
        f = forum(save=True)
        t = thread(save=True)  # Thread belongs to a different forum
        u = user(save=True)

        # Give the user the permission to delete threads.
        g = group(save=True)
        ct = ContentType.objects.get_for_model(f)
        permission(codename='forums_forum.thread_delete_forum',
                   content_type=ct,
                   object_id=f.id,
                   group=g,
                   save=True)
        permission(codename='forums_forum.thread_delete_forum',
                   content_type=ct,
                   object_id=t.forum.id,
                   group=g,
                   save=True)
        g.user_set.add(u)

        self.client.login(username=u.username, password='******')
        r = get(self.client, 'forums.delete_thread', args=[f.slug, t.id])
        eq_(404, r.status_code)
Exemple #57
0
    def setUp(self):
        super(SaveDateTestCase, self).setUp()

        self.user = user(save=True)
        self.thread = thread(save=True)
        self.forum = self.thread.forum
Exemple #58
0
    def test_thread_absolute_url(self):
        t = thread(save=True)

        eq_('/forums/%s/%s' % (t.forum.slug, t.id), t.get_absolute_url())
Exemple #59
0
 def test_save_thread_no_created(self):
     """Saving a new thread should behave as if auto_add_now was set."""
     t = thread(forum=self.forum, title='foo', creator=self.user, save=True)
     t.save()
     now = datetime.now()
     self.assertDateTimeAlmostEqual(now, t.created, self.delta)
Exemple #60
0
    def test_forums_thread_created(self):
        """Tests created/created_date filtering for forums"""
        post_created_ds = datetime(2010, 1, 1, 12, 00)
        thread1 = thread(title=u'crash', created=post_created_ds, save=True)
        post(thread=thread1,
             created=(post_created_ds + timedelta(hours=1)),
             save=True)

        self.refresh()

        # The thread/post should not show up in results for items
        # created AFTER 1/12/2010.
        response = self.client.get(
            reverse('search'), {
                'author': '',
                'created': '2',
                'created_date': '01/12/2010',
                'updated': '0',
                'updated_date': '',
                'sortby': '0',
                'a': '1',
                'w': '4',
                'q': 'crash',
                'format': 'json'
            })

        eq_(200, response.status_code)

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

        # The thread/post should show up in results for items created
        # AFTER 1/1/2010.
        response = self.client.get(
            reverse('search'), {
                'author': '',
                'created': '2',
                'created_date': '01/01/2010',
                'updated': '0',
                'updated_date': '',
                'sortby': '0',
                'a': '1',
                'w': '4',
                'q': 'crash',
                'format': 'json'
            })

        eq_(200, response.status_code)

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

        # The thread/post should show up in results for items created
        # BEFORE 1/12/2010.
        response = self.client.get(
            reverse('search'), {
                'author': '',
                'created': '1',
                'created_date': '01/12/2010',
                'updated': '0',
                'updated_date': '',
                'sortby': '0',
                'a': '1',
                'w': '4',
                'q': 'crash',
                'format': 'json'
            })

        eq_(200, response.status_code)

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

        # The thread/post should NOT show up in results for items
        # created BEFORE 12/31/2009.
        response = self.client.get(
            reverse('search'), {
                'author': '',
                'created': '1',
                'created_date': '12/31/2009',
                'updated': '0',
                'updated_date': '',
                'sortby': '0',
                'a': '1',
                'w': '4',
                'q': 'crash',
                'format': 'json'
            })

        eq_(200, response.status_code)

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