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)
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=t.title, thread_id=t.id, post_id=p.id) starts_with(mail.outbox[0].body, body)
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_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('ol.breadcrumbs li:last-child') eq_(crumb.text(), 'A thread with a very very ...')
def test_edit_locked_thread_403(self): """Editing a locked thread returns 403.""" locked = thread(is_locked=True, save=True) u = locked.creator forum_post(thread=locked, author=u, save=True) self.client.login(username=u.username, password='******') response = get(self.client, 'forums.edit_thread', args=[locked.forum.slug, locked.id]) eq_(403, response.status_code)
def test_last_thread_post_link_has_post_id(self): """Make sure the last post url links to the last post (#post-<id>).""" t = forum_post(save=True).thread last = forum_post(thread=t, save=True) response = get(self.client, 'forums.threads', args=[t.forum.slug]) doc = pq(response.content) last_post_link = doc('ol.threads div.last-post a:not(.username)')[0] href = last_post_link.attrib['href'] eq_(href.split('#')[1], 'post-%s' % last.id)
def test_num_replies(self): """Verify the number of replies label.""" t = forum_post(save=True).thread response = get(self.client, 'forums.posts', args=[t.forum.slug, t.id]) eq_(200, response.status_code) assert '0 Replies' in response.content forum_post(thread=t, save=True) forum_post(thread=t, save=True) response = get(self.client, 'forums.posts', args=[t.forum.slug, t.id]) eq_(200, response.status_code) assert '2 Replies' in response.content
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
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)
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.'
def test_edit_post_moderator(self): """Editing post as a moderator works.""" p = forum_post(save=True) t = p.thread f = t.forum # Create the moderator group, give it the edit permission # and add a moderator. moderator_group = group(save=True) ct = ContentType.objects.get_for_model(f) permission(codename='forums_forum.post_edit_forum', content_type=ct, object_id=f.id, group=moderator_group, save=True) moderator = user(save=True) moderator_group.user_set.add(moderator) self.client.login(username=moderator.username, password='******') r = post(self.client, 'forums.edit_post', {'content': 'More new content'}, args=[f.slug, t.id, p.id]) eq_(200, r.status_code) edited_p = Post.uncached.get(pk=p.pk) eq_('More new content', edited_p.content)
def test_move_thread(self): """Move a thread.""" t = forum_post(save=True).thread f = forum(save=True) u = user(save=True) g = group(save=True) # Give the user permission to move threads between the two forums. ct = ContentType.objects.get_for_model(f) permission(codename='forums_forum.thread_move_forum', content_type=ct, object_id=f.id, group=g, save=True) permission(codename='forums_forum.thread_move_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='******') response = post(self.client, 'forums.move_thread', {'forum': f.id}, args=[t.forum.slug, t.id]) eq_(200, response.status_code) t = Thread.uncached.get(pk=t.pk) eq_(f.id, t.forum.id)
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_show_reply_fields(self): """Reply fields show if user has permission to post.""" t = forum_post(save=True).thread u = user(save=True) self.client.login(username=u.username, password='******') response = get(self.client, 'forums.posts', args=[t.forum.slug, t.pk]) self.assertContains(response, 'thread-reply')
def test_edit_thread_belongs_to_forum(self): """Edit thread action - thread belongs to forum.""" f = forum(save=True) t = forum_post(save=True).thread # Thread belongs to a different forum u = t.creator self.client.login(username=u.username, password='******') r = get(self.client, 'forums.edit_thread', args=[f.slug, t.id]) eq_(404, r.status_code)
def test_locked_thread_403(self): """Marking a thread locked without permissions returns 403.""" t = forum_post(save=True).thread u = user(save=True) self.client.login(username=u.username, password='******') response = post(self.client, 'forums.lock_thread', args=[t.forum.slug, t.id]) eq_(403, response.status_code)
def test_last_post_link_has_post_id(self): """Make sure the last post url links to the last post (#post-<id>).""" p = forum_post(save=True) response = get(self.client, "forums.forums") doc = pq(response.content) last_post_link = doc("ol.forums div.last-post a:not(.username)")[0] href = last_post_link.attrib["href"] eq_(href.split("#")[1], "post-%s" % p.id)
def test_posts_fr(self): """Posts render for [fr] locale.""" t = forum_post(save=True).thread response = get(self.client, 'forums.posts', args=[t.forum.slug, t.id], locale='fr') eq_(200, response.status_code) eq_('/forums/{f}/{t}'.format(f=t.forum.slug, t=t.id), pq(response.content)('link[rel="canonical"]')[0].attrib['href'])
def test_move_thread_405(self): """Moving a thread via a GET instead of a POST request.""" t = forum_post(save=True).thread u = user(save=True) self.client.login(username=u.username, password='******') response = get(self.client, 'forums.move_thread', args=[t.forum.slug, t.id]) eq_(405, response.status_code)
def test_links_nofollow(self): """Links posted should have rel=nofollow.""" p = forum_post(content='linking http://test.org', save=True) t = p.thread f = t.forum response = get(self.client, 'forums.posts', args=[f.slug, t.pk]) doc = pq(response.content) eq_('nofollow', doc('ol.posts div.content a')[0].attrib['rel'])
def test_last_post_link_has_post_id(self): """Make sure the last post url links to the last post (#post-<id>).""" p = forum_post(save=True) response = get(self.client, 'forums.forums') doc = pq(response.content) last_post_link = doc('ol.forums div.last-post a:not(.username)')[0] href = last_post_link.attrib['href'] eq_(href.split('#')[1], 'post-%s' % p.id)
def test_sticky_thread_405(self): """Marking a thread sticky with a HTTP GET returns 405.""" t = forum_post(save=True).thread u = user(save=True) self.client.login(username=u.username, password='******') response = get(self.client, 'forums.sticky_thread', args=[t.forum.slug, t.id]) eq_(405, response.status_code)
def test_links_nofollow(self): """Links posted should have rel=nofollow.""" p = forum_post(content="linking http://test.org", save=True) t = p.thread f = t.forum response = get(self.client, "forums.posts", args=[f.slug, t.pk]) doc = pq(response.content) eq_("nofollow", doc("ol.posts div.content a")[0].attrib["rel"])
def test_post_delete_403(self): """Deleting a post without permissions returns 403.""" p = forum_post(save=True) t = p.thread u = user(save=True) self.client.login(username=u.username, password='******') response = get(self.client, 'forums.delete_post', args=[t.forum.slug, t.id, p.id]) eq_(403, response.status_code)
def test_move_thread_403(self): """Moving a thread without permissions returns 403.""" t = forum_post(save=True).thread f = forum(save=True) u = user(save=True) self.client.login(username=u.username, password='******') response = post(self.client, 'forums.move_thread', {'forum': f.id}, args=[t.forum.slug, t.id]) eq_(403, response.status_code)
def test_edit_thread_creator(self): """Changing thread title as the thread creator works.""" t = forum_post(save=True).thread u = t.creator self.client.login(username=u.username, password='******') post(self.client, 'forums.edit_thread', {'title': 'A new title'}, args=[t.forum.slug, t.id]) edited_t = Thread.uncached.get(id=t.id) eq_('A new title', edited_t.title)
def test_edit_thread_template(self): """The edit-post template should render.""" p = forum_post(save=True) u = p.author self.client.login(username=u.username, password="******") res = get(self.client, "forums.edit_post", args=[p.thread.forum.slug, p.thread.id, p.id]) doc = pq(res.content) eq_(len(doc("form.edit-post")), 1)
def test_edit_thread_template(self): """The edit-thread template should render.""" t = forum_post(save=True).thread creator = t.creator self.client.login(username=creator.username, password="******") res = get(self.client, "forums.edit_thread", args=[t.forum.slug, t.id]) doc = pq(res.content) eq_(len(doc("form.edit-thread")), 1)
def test_edit_thread_template(self): """The edit-thread template should render.""" t = forum_post(save=True).thread creator = t.creator self.client.login(username=creator.username, password='******') res = get(self.client, 'forums.edit_thread', args=[t.forum.slug, t.id]) doc = pq(res.content) eq_(len(doc('form.edit-thread')), 1)
def test_edit_post(self): """Changing post content works.""" p = forum_post(save=True) t = p.thread u = p.author self.client.login(username=u.username, password="******") post(self.client, "forums.edit_post", {"content": "Some new content"}, args=[t.forum.slug, t.id, p.id]) edited_p = Post.objects.get(id=p.id) eq_("Some new content", edited_p.content)
def test_edit_thread_template(self): """The edit-post template should render.""" p = forum_post(save=True) u = p.author self.client.login(username=u.username, password='******') res = get(self.client, 'forums.edit_post', args=[p.thread.forum.slug, p.thread.id, p.id]) doc = pq(res.content) eq_(len(doc('form.edit-post')), 1)
def test_edit_thread_errors(self): """Editing thread with too short of a title shows errors.""" t = forum_post(save=True).thread creator = t.creator self.client.login(username=creator.username, password="******") response = post(self.client, "forums.edit_thread", {"title": "wha?"}, args=[t.forum.slug, t.id]) doc = pq(response.content) errors = doc("ul.errorlist li a") eq_(errors[0].text, "Your title is too short (4 characters). " + "It must be at least 5 characters.")
def test_empty_reply_errors(self): """Posting an empty reply shows errors.""" u = user(save=True) t = forum_post(save=True).thread self.client.login(username=u.username, password="******") response = post(self.client, "forums.reply", {"content": ""}, args=[t.forum.slug, t.id]) doc = pq(response.content) error_msg = doc("ul.errorlist li a")[0] eq_(error_msg.text, "Please provide a message.")
def test_edit_post(self): """Changing post content works.""" p = forum_post(save=True) t = p.thread u = p.author self.client.login(username=u.username, password='******') post(self.client, 'forums.edit_post', {'content': 'Some new content'}, args=[t.forum.slug, t.id, p.id]) edited_p = Post.objects.get(id=p.id) eq_('Some new content', edited_p.content)
def test_empty_reply_errors(self): """Posting an empty reply shows errors.""" u = user(save=True) t = forum_post(save=True).thread self.client.login(username=u.username, password='******') response = post(self.client, 'forums.reply', {'content': ''}, args=[t.forum.slug, t.id]) doc = pq(response.content) error_msg = doc('ul.errorlist li a')[0] eq_(error_msg.text, 'Please provide a message.')
def test_edit_post_errors(self): """Changing post content works.""" p = forum_post(save=True) t = p.thread u = p.author self.client.login(username=u.username, password="******") response = post(self.client, "forums.edit_post", {"content": "wha?"}, args=[t.forum.slug, t.id, p.id]) doc = pq(response.content) errors = doc("ul.errorlist li a") eq_(errors[0].text, "Your message is too short (4 characters). " + "It must be at least 5 characters.")
def test_watch_thread(self): """Watch and unwatch a thread.""" t = forum_post(save=True).thread u = user(save=True) self.client.login(username=u.username, password="******") response = post(self.client, "forums.watch_thread", {"watch": "yes"}, args=[t.forum.slug, t.id]) self.assertContains(response, "Watching") response = post(self.client, "forums.watch_thread", {"watch": "no"}, args=[t.forum.slug, t.id]) self.assertNotContains(response, "Watching")
def test_preview_reply(self): """Preview a reply.""" t = forum_post(save=True).thread u = t.creator content = 'Full of awesome.' self.client.login(username=u.username, password='******') response = post(self.client, 'forums.reply', {'content': content, 'preview': 'any string'}, args=[t.forum.slug, t.id]) eq_(200, response.status_code) doc = pq(response.content) eq_(content, doc('#post-preview div.content').text()) eq_(1, t.post_set.count())
def test_restricted_hide_reply(self): """Reply fields don't show if user has no permission to post.""" t = forum_post(save=True).thread f = t.forum ct = ContentType.objects.get_for_model(f) # If the forum has the permission and the user isn't assigned said # permission, then they can't post. permission(codename='forums_forum.post_in_forum', content_type=ct, object_id=f.id, save=True) u = user(save=True) self.client.login(username=u.username, password='******') response = get(self.client, 'forums.posts', args=[f.slug, t.pk]) self.assertNotContains(response, 'thread-reply')
def test_watch_thread(self): """Watch and unwatch a thread.""" t = forum_post(save=True).thread u = user(save=True) self.client.login(username=u.username, password='******') response = post(self.client, 'forums.watch_thread', {'watch': 'yes'}, args=[t.forum.slug, t.id]) self.assertContains(response, 'Stop watching this thread') response = post(self.client, 'forums.watch_thread', {'watch': 'no'}, args=[t.forum.slug, t.id]) self.assertNotContains(response, 'Stop watching this thread')
def test_edit_thread_errors(self): """Editing thread with too short of a title shows errors.""" t = forum_post(save=True).thread creator = t.creator self.client.login(username=creator.username, password='******') response = post(self.client, 'forums.edit_thread', {'title': 'wha?'}, args=[t.forum.slug, t.id]) doc = pq(response.content) errors = doc('ul.errorlist li a') eq_(errors[0].text, 'Your title is too short (4 characters). ' + 'It must be at least 5 characters.')
def test_edit_post_errors(self): """Changing post content works.""" p = forum_post(save=True) t = p.thread u = p.author self.client.login(username=u.username, password='******') response = post(self.client, 'forums.edit_post', {'content': 'wha?'}, args=[t.forum.slug, t.id, p.id]) doc = pq(response.content) errors = doc('ul.errorlist li a') eq_(errors[0].text, 'Your message is too short (4 characters). ' + 'It must be at least 5 characters.')