def test_links_nofollow(self): """Links posted should have rel=nofollow.""" u = UserFactory() t = ThreadFactory() t.new_post(creator=u, content="linking http://test.org") response = get(self.client, "wiki.discuss.posts", args=[t.document.slug, t.pk]) doc = pq(response.content) eq_("nofollow", doc("ol.posts div.content a")[0].attrib["rel"])
def test_posts_sort(self): """Ensure that posts are being sorted properly by date/time.""" t = ThreadFactory() t.new_post(creator=t.creator, content='foo') time.sleep(1) p2 = t.new_post(creator=t.creator, content='foo') given_ = PostsFeed().items(t)[0].id eq_(p2.id, given_)
def test_links_nofollow(self): """Links posted should have rel=nofollow.""" u = UserFactory() t = ThreadFactory() t.new_post(creator=u, content='linking http://test.org') response = get(self.client, 'wiki.discuss.posts', args=[t.document.slug, t.pk]) doc = pq(response.content) eq_('nofollow', doc('ol.posts div.content a')[0].attrib['rel'])
def test_threads_sort(self): """Ensure that threads are being sorted properly by date/time.""" d = DocumentFactory() t = ThreadFactory(document=d) t.new_post(creator=t.creator, content='foo') time.sleep(1) t2 = ThreadFactory(document=d) t2.new_post(creator=t2.creator, content='foo') given_ = ThreadsFeed().items(d)[0].id eq_(t2.id, given_)
def test_last_thread_post_link_has_post_id(self): """Make sure the last post url links to the last post (#post-<id>).""" u = UserFactory() t = ThreadFactory() t.new_post(creator=u, content="foo") p2 = t.new_post(creator=u, content="bar") response = get(self.client, "wiki.discuss.threads", args=[t.document.slug]) doc = pq(response.content) last_post_link = doc("tr.threads td.last-post a:not(.username)")[0] href = last_post_link.attrib["href"] eq_(href.split("#")[1], "post-%d" % p2.id)
def test_last_thread_post_link_has_post_id(self): """Make sure the last post url links to the last post (#post-<id>).""" u = UserFactory() t = ThreadFactory() t.new_post(creator=u, content='foo') p2 = t.new_post(creator=u, content='bar') response = get(self.client, 'wiki.discuss.threads', args=[t.document.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-%d' % p2.id)
def test_delete_last_and_only_post_in_thread(self): """Deleting the only post in a thread should delete the thread""" t = ThreadFactory(title="test") p = t.new_post(creator=t.creator, content="test") eq_(1, t.post_set.count()) p.delete() eq_(0, Thread.objects.filter(pk=t.id).count())
def test_post_absolute_url(self): t = ThreadFactory() p = t.new_post(creator=t.creator, content='foo') url_ = reverse('wiki.discuss.posts', locale=p.thread.document.locale, args=[p.thread.document.slug, p.thread.id]) exp_ = urlparams(url_, hash='post-%s' % p.id) eq_(exp_, p.get_absolute_url())
def test_post_absolute_url(self): t = ThreadFactory() p = t.new_post(creator=t.creator, content="foo") url_ = reverse( "wiki.discuss.posts", locale=p.thread.document.locale, args=[p.thread.document.slug, p.thread.id] ) exp_ = urlparams(url_, hash="post-%s" % p.id) eq_(exp_, p.get_absolute_url())
def test_edit_thread_template(self): """The edit-post template should render.""" u = UserFactory() self.client.login(username=u.username, password='******') t = ThreadFactory(creator=u, is_locked=False) p = t.new_post(creator=u, content='foo') res = get(self.client, 'wiki.discuss.edit_post', args=[p.thread.document.slug, p.thread.id, p.id]) doc = pq(res.content) eq_(len(doc('form.edit-post')), 1)
def test_edit_post(self): """Changing post content works.""" u = UserFactory() self.client.login(username=u.username, password='******') d = DocumentFactory() t = ThreadFactory(document=d) p = t.new_post(creator=u, content='foo') post(self.client, 'wiki.discuss.edit_post', {'content': 'Some new content'}, args=[d.slug, t.id, p.id]) edited_p = t.post_set.get(pk=p.id) eq_('Some new content', edited_p.content)
def test_last_post_updated(self): """Adding/Deleting the last post in a thread should update the last_post field """ t = ThreadFactory() u = UserFactory() # add a new post, then check that last_post is updated new_post = t.new_post(creator=u, content="test") eq_(t.last_post.id, new_post.id) # delete the new post, then check that last_post is updated new_post.delete() self.assertIsNone(t.last_post.id)
def test_flag_kbforum_post(self): u = UserFactory() t = ThreadFactory() p = t.new_post(creator=u, content="foo") f = FlaggedObject(content_object=p, reason="spam", creator_id=u.id) f.save() # Make sure flagit queue page works u2 = UserFactory() add_permission(u2, FlaggedObject, "can_moderate") self.client.login(username=u2.username, password="******") response = get(self.client, "flagit.queue") eq_(200, response.status_code) doc = pq(response.content) eq_(1, len(doc("#flagged-queue li")))
def test_flag_kbforum_post(self): u = UserFactory() t = ThreadFactory() p = t.new_post(creator=u, content='foo') f = FlaggedObject(content_object=p, reason='spam', creator_id=u.id) f.save() # Make sure flagit queue page works u2 = UserFactory() add_permission(u2, FlaggedObject, 'can_moderate') self.client.login(username=u2.username, password='******') response = get(self.client, 'flagit.queue') eq_(200, response.status_code) doc = pq(response.content) eq_(1, len(doc('#flagged-queue li')))
def test_watch_forum(self): """Watch then unwatch a forum.""" u = UserFactory() self.client.login(username=u.username, password='******') d = DocumentFactory() post(self.client, 'wiki.discuss.watch_forum', {'watch': 'yes'}, args=[d.slug]) assert NewThreadEvent.is_notifying(u, d) # NewPostEvent is not notifying. t = ThreadFactory(document=d) p = t.new_post(creator=t.creator, content='test') assert not NewPostEvent.is_notifying(u, p) post(self.client, 'wiki.discuss.watch_forum', {'watch': 'no'}, args=[d.slug]) assert not NewThreadEvent.is_notifying(u, d)
def test_edit_post_errors(self): """Changing post content works.""" u = UserFactory() self.client.login(username=u.username, password='******') t = ThreadFactory(creator=u, is_locked=False) p = t.new_post(creator=u, content='foo') response = post(self.client, 'wiki.discuss.edit_post', {'content': 'wha?'}, args=[t.document.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_edit_post_errors(self): """Changing post content works.""" u = UserFactory() self.client.login(username=u.username, password='******') t = ThreadFactory(creator=u, is_locked=False) p = t.new_post(creator=u, content='foo') response = post(self.client, 'wiki.discuss.edit_post', {'content': 'wha?'}, args=[t.document.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_edit_post(self): """Changing post content works.""" u = UserFactory() self.client.login(username=u.username, password="******") d = DocumentFactory() t = ThreadFactory(document=d) p = t.new_post(creator=u, content="foo") post( self.client, "wiki.discuss.edit_post", {"content": "Some new content"}, args=[d.slug, t.id, p.id], ) edited_p = t.post_set.get(pk=p.id) eq_("Some new content", edited_p.content)
def test_edit_post_errors(self): """Changing post content works.""" u = UserFactory() self.client.login(username=u.username, password="******") t = ThreadFactory(creator=u, is_locked=False) p = t.new_post(creator=u, content="foo") response = post( self.client, "wiki.discuss.edit_post", {"content": "wha?"}, args=[t.document.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_locale_discussions_ignores_sticky(self): """Sticky flag is ignored in locale discussions view""" u = UserFactory() d = DocumentFactory() t = ThreadFactory(title="Sticky Thread", is_sticky=True, document=d) t.new_post(creator=u, content="foo") t2 = ThreadFactory(title="A thread with a very very long", is_sticky=False, document=d) t2.new_post(creator=u, content="bar") time.sleep(1) t2.new_post(creator=u, content="last") self.client.login(username=u.username, password="******") response = post(self.client, "wiki.locale_discussions") eq_(200, response.status_code) doc = pq(response.content) title = doc(".threads .title a:first").text() assert title.startswith("A thread with a very very long")
def test_locale_discussions_ignores_sticky(self): """Sticky flag is ignored in locale discussions view""" u = UserFactory() d = DocumentFactory() t = ThreadFactory(title='Sticky Thread', is_sticky=True, document=d) t.new_post(creator=u, content='foo') t2 = ThreadFactory(title='A thread with a very very long', is_sticky=False, document=d) t2.new_post(creator=u, content='bar') time.sleep(1) t2.new_post(creator=u, content='last') self.client.login(username=u.username, password='******') response = post(self.client, 'wiki.locale_discussions') eq_(200, response.status_code) doc = pq(response.content) title = doc('ol.threads li div.title a:first').text() assert title.startswith('A thread with a very very long')
class KBBelongsTestCase(KBForumTestCase): """ Mixing and matching thread, forum, and post data in URLs should fail. """ def setUp(self): super(KBBelongsTestCase, self).setUp() u = UserFactory() self.doc = DocumentFactory(title='spam') self.doc_2 = DocumentFactory(title='eggs') self.thread = ThreadFactory(creator=u, document=self.doc, is_locked=False) self.thread_2 = ThreadFactory(creator=u, document=self.doc_2, is_locked=False) permissions = ('sticky_thread', 'lock_thread', 'delete_thread', 'delete_post') for permission in permissions: add_permission(u, self.thread, permission) self.post = self.thread.new_post(creator=self.thread.creator, content='foo') self.client.login(username=u.username, password='******') def test_posts_thread_belongs_to_document(self): """Posts view - thread belongs to document.""" r = get(self.client, 'wiki.discuss.posts', args=[self.doc_2.slug, self.thread.id]) eq_(404, r.status_code) def test_reply_thread_belongs_to_document(self): """Reply action - thread belongs to document.""" r = post(self.client, 'wiki.discuss.reply', {}, args=[self.doc_2.slug, self.thread.id]) eq_(404, r.status_code) def test_locked_thread_belongs_to_document(self): """Lock action - thread belongs to document.""" r = post(self.client, 'wiki.discuss.lock_thread', {}, args=[self.doc_2.slug, self.thread.id]) eq_(404, r.status_code) def test_sticky_thread_belongs_to_document(self): """Sticky action - thread belongs to document.""" r = post(self.client, 'wiki.discuss.sticky_thread', {}, args=[self.doc_2.slug, self.thread.id]) eq_(404, r.status_code) def test_edit_thread_belongs_to_document(self): """Edit thread action - thread belongs to document.""" r = get(self.client, 'wiki.discuss.edit_thread', args=[self.doc_2.slug, self.thread.id]) eq_(404, r.status_code) def test_delete_thread_belongs_to_document(self): """Delete thread action - thread belongs to document.""" r = get(self.client, 'wiki.discuss.delete_thread', args=[self.doc_2.slug, self.thread.id]) eq_(404, r.status_code) def test_edit_post_belongs_to_thread_and_document(self): """ Edit post action - post belongs to thread and thread belongs to forum. """ r = get(self.client, 'wiki.discuss.edit_post', args=[self.doc_2.slug, self.thread.id, self.post.id]) eq_(404, r.status_code) r = get(self.client, 'wiki.discuss.edit_post', args=[self.doc.slug, self.thread_2.id, self.post.id]) eq_(404, r.status_code) def test_delete_post_belongs_to_thread_and_document(self): """ Delete post action - post belongs to thread and thread belongs to forum. """ r = get(self.client, 'wiki.discuss.delete_post', args=[self.doc_2.slug, self.thread.id, self.post.id]) eq_(404, r.status_code) r = get(self.client, 'wiki.discuss.delete_post', args=[self.doc.slug, self.thread_2.id, self.post.id]) eq_(404, r.status_code)
class ThreadPermissionsTests(KBForumTestCase): def setUp(self): super(ThreadPermissionsTests, self).setUp() self.doc = DocumentFactory() self.u = UserFactory() self.thread = ThreadFactory(document=self.doc, creator=self.u) self.post = self.thread.new_post(creator=self.thread.creator, content='foo') # Login for testing 403s u2 = UserFactory() self.client.login(username=u2.username, password='******') def tearDown(self): self.client.logout() super(ThreadPermissionsTests, self).tearDown() def test_edit_thread_403(self): """Editing a thread without permissions returns 403.""" response = get(self.client, 'wiki.discuss.edit_thread', args=[self.doc.slug, self.thread.id]) eq_(403, response.status_code) def test_edit_locked_thread_403(self): """Editing a locked thread returns 403.""" t = ThreadFactory(document=self.doc, creator=self.u, is_locked=True) response = get(self.client, 'wiki.discuss.edit_thread', args=[self.doc.slug, t.id]) eq_(403, response.status_code) def test_delete_thread_403(self): """Deleting a thread without permissions returns 403.""" response = get(self.client, 'wiki.discuss.delete_thread', args=[self.doc.slug, self.thread.id]) eq_(403, response.status_code) def test_sticky_thread_405(self): """Marking a thread sticky with a HTTP GET returns 405.""" response = get(self.client, 'wiki.discuss.sticky_thread', args=[self.doc.slug, self.thread.id]) eq_(405, response.status_code) def test_sticky_thread_403(self): """Marking a thread sticky without permissions returns 403.""" response = post(self.client, 'wiki.discuss.sticky_thread', args=[self.doc.slug, self.thread.id]) eq_(403, response.status_code) def test_locked_thread_403(self): """Marking a thread locked without permissions returns 403.""" response = post(self.client, 'wiki.discuss.lock_thread', args=[self.doc.slug, self.thread.id]) eq_(403, response.status_code) def test_locked_thread_405(self): """Marking a thread locked via a GET instead of a POST request.""" response = get(self.client, 'wiki.discuss.lock_thread', args=[self.doc.slug, self.thread.id]) eq_(405, response.status_code) def test_post_edit_403(self): """Editing a post without permissions returns 403.""" response = get(self.client, 'wiki.discuss.edit_post', args=[self.doc.slug, self.thread.id, self.post.id]) eq_(403, response.status_code) def test_post_delete_403(self): """Deleting a post without permissions returns 403.""" response = get(self.client, 'wiki.discuss.delete_post', args=[self.doc.slug, self.thread.id, self.post.id]) eq_(403, response.status_code)
class KBSaveDateTestCase(KBForumTestCase): """ Test that Thread and Post save methods correctly handle created and updated dates. """ delta = datetime.timedelta(milliseconds=3000) def setUp(self): super(KBSaveDateTestCase, self).setUp() self.user = UserFactory() self.doc = DocumentFactory() self.thread = ThreadFactory( created=datetime.datetime(2010, 1, 12, 9, 48, 23)) def assertDateTimeAlmostEqual(self, a, b, delta, msg=None): """ Assert that two datetime objects are within `range` (a timedelta). """ diff = abs(a - b) assert diff < abs(delta), msg or "%s ~= %s" % (a, b) def test_save_thread_no_created(self): """Saving a new thread should behave as if auto_add_now was set.""" t = self.doc.thread_set.create(title="foo", creator=self.user) t.save() now = datetime.datetime.now() self.assertDateTimeAlmostEqual(now, t.created, self.delta) def test_save_thread_created(self): """ Saving a new thread that already has a created date should respect that created date. """ created = datetime.datetime(1992, 1, 12, 9, 48, 23) t = self.doc.thread_set.create(title="foo", creator=self.user, created=created) t.save() eq_(created, t.created) def test_save_old_thread_created(self): """Saving an old thread should not change its created date.""" t = ThreadFactory() created = t.created t.save() eq_(created, t.created) def test_save_new_post_no_timestamps(self): """ Saving a new post should behave as if auto_add_now was set on created and auto_now set on updated. """ p = self.thread.new_post(creator=self.user, content="bar") now = datetime.datetime.now() self.assertDateTimeAlmostEqual(now, p.created, self.delta) self.assertDateTimeAlmostEqual(now, p.updated, self.delta) def test_save_old_post_no_timestamps(self): """ Saving an existing post should update the updated date. """ now = datetime.datetime.now() p = self.thread.new_post(creator=self.user, content="bar") self.assertDateTimeAlmostEqual(now, p.updated, self.delta) p.content = "baz" p.updated_by = self.user p.save() self.assertDateTimeAlmostEqual(now, p.updated, self.delta) def test_save_new_post_timestamps(self): """ Saving a new post should not allow you to override auto_add_now- and auto_now-like functionality. """ created_ = datetime.datetime(1992, 1, 12, 10, 12, 32) p = PostFactory(thread=self.thread, creator=self.user, created=created_, updated=created_) now = datetime.datetime.now() self.assertDateTimeAlmostEqual(now, p.created, self.delta) self.assertDateTimeAlmostEqual(now, p.updated, self.delta) def test_content_parsed_sanity(self): """The content_parsed field is populated.""" p = PostFactory(content="yet another post") eq_("<p>yet another post\n</p>", p.content_parsed)
class KBBelongsTestCase(KBForumTestCase): """ Mixing and matching thread, forum, and post data in URLs should fail. """ def setUp(self): super(KBBelongsTestCase, self).setUp() u = UserFactory() self.doc = DocumentFactory(title="spam") self.doc_2 = DocumentFactory(title="eggs") self.thread = ThreadFactory(creator=u, document=self.doc, is_locked=False) self.thread_2 = ThreadFactory(creator=u, document=self.doc_2, is_locked=False) permissions = ("sticky_thread", "lock_thread", "delete_thread", "delete_post") for permission in permissions: add_permission(u, self.thread, permission) self.post = self.thread.new_post(creator=self.thread.creator, content="foo") self.client.login(username=u.username, password="******") def test_posts_thread_belongs_to_document(self): """Posts view - thread belongs to document.""" r = get(self.client, "wiki.discuss.posts", args=[self.doc_2.slug, self.thread.id]) eq_(404, r.status_code) def test_reply_thread_belongs_to_document(self): """Reply action - thread belongs to document.""" r = post(self.client, "wiki.discuss.reply", {}, args=[self.doc_2.slug, self.thread.id]) eq_(404, r.status_code) def test_locked_thread_belongs_to_document(self): """Lock action - thread belongs to document.""" r = post(self.client, "wiki.discuss.lock_thread", {}, args=[self.doc_2.slug, self.thread.id]) eq_(404, r.status_code) def test_sticky_thread_belongs_to_document(self): """Sticky action - thread belongs to document.""" r = post(self.client, "wiki.discuss.sticky_thread", {}, args=[self.doc_2.slug, self.thread.id]) eq_(404, r.status_code) def test_edit_thread_belongs_to_document(self): """Edit thread action - thread belongs to document.""" r = get(self.client, "wiki.discuss.edit_thread", args=[self.doc_2.slug, self.thread.id]) eq_(404, r.status_code) def test_delete_thread_belongs_to_document(self): """Delete thread action - thread belongs to document.""" r = get(self.client, "wiki.discuss.delete_thread", args=[self.doc_2.slug, self.thread.id]) eq_(404, r.status_code) def test_edit_post_belongs_to_thread_and_document(self): """ Edit post action - post belongs to thread and thread belongs to forum. """ r = get( self.client, "wiki.discuss.edit_post", args=[self.doc_2.slug, self.thread.id, self.post.id], ) eq_(404, r.status_code) r = get( self.client, "wiki.discuss.edit_post", args=[self.doc.slug, self.thread_2.id, self.post.id], ) eq_(404, r.status_code) def test_delete_post_belongs_to_thread_and_document(self): """ Delete post action - post belongs to thread and thread belongs to forum. """ r = get( self.client, "wiki.discuss.delete_post", args=[self.doc_2.slug, self.thread.id, self.post.id], ) eq_(404, r.status_code) r = get( self.client, "wiki.discuss.delete_post", args=[self.doc.slug, self.thread_2.id, self.post.id], ) eq_(404, r.status_code)
class KBSaveDateTestCase(KBForumTestCase): """ Test that Thread and Post save methods correctly handle created and updated dates. """ delta = datetime.timedelta(milliseconds=3000) def setUp(self): super(KBSaveDateTestCase, self).setUp() self.user = UserFactory() self.doc = DocumentFactory() self.thread = ThreadFactory(created=datetime.datetime(2010, 1, 12, 9, 48, 23)) def assertDateTimeAlmostEqual(self, a, b, delta, msg=None): """ Assert that two datetime objects are within `range` (a timedelta). """ diff = abs(a - b) assert diff < abs(delta), msg or "%s ~= %s" % (a, b) def test_save_thread_no_created(self): """Saving a new thread should behave as if auto_add_now was set.""" t = self.doc.thread_set.create(title="foo", creator=self.user) t.save() now = datetime.datetime.now() self.assertDateTimeAlmostEqual(now, t.created, self.delta) def test_save_thread_created(self): """ Saving a new thread that already has a created date should respect that created date. """ created = datetime.datetime(1992, 1, 12, 9, 48, 23) t = self.doc.thread_set.create(title="foo", creator=self.user, created=created) t.save() eq_(created, t.created) def test_save_old_thread_created(self): """Saving an old thread should not change its created date.""" t = ThreadFactory() created = t.created t.save() eq_(created, t.created) def test_save_new_post_no_timestamps(self): """ Saving a new post should behave as if auto_add_now was set on created and auto_now set on updated. """ p = self.thread.new_post(creator=self.user, content="bar") now = datetime.datetime.now() self.assertDateTimeAlmostEqual(now, p.created, self.delta) self.assertDateTimeAlmostEqual(now, p.updated, self.delta) def test_save_old_post_no_timestamps(self): """ Saving an existing post should update the updated date. """ now = datetime.datetime.now() p = self.thread.new_post(creator=self.user, content="bar") self.assertDateTimeAlmostEqual(now, p.updated, self.delta) p.content = "baz" p.updated_by = self.user p.save() self.assertDateTimeAlmostEqual(now, p.updated, self.delta) def test_save_new_post_timestamps(self): """ Saving a new post should not allow you to override auto_add_now- and auto_now-like functionality. """ created_ = datetime.datetime(1992, 1, 12, 10, 12, 32) p = PostFactory(thread=self.thread, creator=self.user, created=created_, updated=created_) now = datetime.datetime.now() self.assertDateTimeAlmostEqual(now, p.created, self.delta) self.assertDateTimeAlmostEqual(now, p.updated, self.delta) def test_content_parsed_sanity(self): """The content_parsed field is populated.""" p = PostFactory(content="yet another post") eq_("<p>yet another post\n</p>", p.content_parsed)