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 = ThreadFactory() old = PostFactory(thread=t) last = PostFactory(thread=t) old.content = 'updated content' old.save() eq_(last.id, t.forum.last_post_id)
def test_delete_post_removes_flag(self): """Deleting a post also removes the flags on that post.""" p = PostFactory() u = UserFactory() FlaggedObject.objects.create(status=0, content_object=p, reason="language", creator_id=u.id) eq_(1, FlaggedObject.objects.count()) p.delete() eq_(0, FlaggedObject.objects.count())
def test_save_old_post_no_timestamps(self): """Saving an existing post should update the updated date.""" created = datetime(2010, 5, 4, 14, 4, 22) updated = datetime(2010, 5, 4, 14, 4, 31) p = PostFactory(thread=self.thread, created=created, updated=updated) eq_(updated, p.updated) p.content = 'baz' p.updated_by = self.user p.save() now = datetime.now() self.assertDateTimeAlmostEqual(now, p.updated, self.delta) eq_(created, p.created)
def test_last_post_updated(self): # Adding/Deleting the last post in a thread and forum should # update the last_post field orig_post = PostFactory(created=YESTERDAY) t = orig_post.thread # add a new post, then check that last_post is updated new_post = PostFactory(thread=t, content='test') f = Forum.objects.get(id=t.forum_id) t = Thread.objects.get(id=t.id) eq_(f.last_post.id, new_post.id) eq_(t.last_post.id, new_post.id) # delete the new post, then check that last_post is updated new_post.delete() f = Forum.objects.get(id=f.id) t = Thread.objects.get(id=t.id) eq_(f.last_post.id, orig_post.id) eq_(t.last_post.id, orig_post.id)
def test_post_page(self): t = ThreadFactory() # Fill out the first page with posts from yesterday. page1 = PostFactory.create_batch(POSTS_PER_PAGE, thread=t, created=YESTERDAY) # Second page post from today. p2 = PostFactory(thread=t) for p in page1: eq_(1, p.page) eq_(2, p2.page)
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 = ForumFactory() t1 = ThreadFactory(forum=old_forum, posts=[]) p1 = PostFactory(thread=t1, created=YESTERDAY) t2 = ThreadFactory(forum=old_forum, posts=[]) p2 = PostFactory(thread=t2) # Newest post of all. # Setup forum to move latest thread to. new_forum = ForumFactory() t3 = ThreadFactory(forum=new_forum, posts=[]) p3 = PostFactory(thread=t3, created=YESTERDAY) # 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())
def test_update_post_does_not_update_thread(self): # Updating/saving an old post in a thread should _not_ update # the last_post key in that thread. t = ThreadFactory() old = PostFactory(thread=t) last = PostFactory(thread=t) old.content = 'updated content' old.save() eq_(last.id, old.thread.last_post_id)
def test_edit_post_errors(self): """Changing post content works.""" p = PostFactory() 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_forums_filter_updated(self): """Filter for updated date.""" post_updated_ds = datetime(2010, 5, 3, 12, 00) thread1 = ThreadFactory(title=u't1 audio') PostFactory(thread=thread1, created=post_updated_ds) thread2 = ThreadFactory(title=u't2 audio') PostFactory(thread=thread2, created=(post_updated_ds + timedelta(days=2))) 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.advanced'), 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.advanced'), qs) results = json.loads(response.content)['results'] eq_([thread2.get_absolute_url()], [r['url'] for r in results])
def test_only_show_wiki_and_questions(self): """Tests that the simple 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 = ProductFactory(slug=u'desktop') ques = QuestionFactory(title=u'audio', product=p) 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(p) RevisionFactory(document=doc, is_approved=True) thread1 = ThreadFactory(title=u'audio') PostFactory(thread=thread1) 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) # Archive the article and question. They should no longer appear # in simple search results. ques.is_archived = True ques.save() doc.is_archived = True doc.save() 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'], 0)
def test_updated_invalid(self): """Invalid updated_date is ignored.""" thread1 = ThreadFactory() PostFactory(thread=thread1) self.refresh() qs = { 'a': 1, 'w': 4, 'format': 'json', 'updated': 1, 'updated_date': 'invalid' } response = self.client.get(reverse('search.advanced'), qs) eq_(1, json.loads(response.content)['total'])
def test_edit_post(self): """Changing post content works.""" p = PostFactory() 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_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 = ThreadFactory() f = t.forum PostFactory(thread=t) watcher = UserFactory() 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_updated_invalid(self): """Invalid updated_date is ignored.""" thread1 = ThreadFactory() PostFactory(thread=thread1) self.refresh() qs = { "a": 1, "w": 4, "format": "json", "updated": 1, "updated_date": "invalid" } response = self.client.get(reverse("search.advanced"), qs) eq_(1, json.loads(response.content)["total"])
def test_watch_forum(self): """Watch then unwatch a forum.""" f = ForumFactory() PostFactory(thread__forum=f) u = UserFactory() 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_edit_post_errors(self): """Changing post content works.""" p = PostFactory() 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_forum(self): """Watch then unwatch a forum.""" f = ForumFactory() PostFactory(thread__forum=f) u = UserFactory() 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_post_absolute_url(self): t = ThreadFactory(posts=[]) # Fill out the first page with posts from yesterday. p1 = PostFactory(thread=t, created=YESTERDAY) PostFactory.create_batch(POSTS_PER_PAGE - 1, created=YESTERDAY, thread=t) # Second page post from today. p2 = PostFactory(thread=t) 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())
def test_forums_search(self): """This tests whether forum posts show up in searches""" thread1 = ThreadFactory(title=u'crash') PostFactory(thread=thread1) self.refresh() response = self.client.get(reverse('search.advanced'), { '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)
def test_added(self): # Nothing exists before the test starts eq_(ThreadMappingType.search().count(), 0) # Creating a new Thread does create a new document in the index. new_thread = ThreadFactory() self.refresh() eq_(ThreadMappingType.search().count(), 1) # 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. PostFactory(thread=new_thread) self.refresh() eq_(ThreadMappingType.search().count(), 1)
def test_delete_thread_with_last_forum_post(self): # Deleting the thread with a forum's last post should update # the last_post field on the forum t = ThreadFactory() f = t.forum last_post = f.last_post # add a new thread and post, verify last_post updated t = ThreadFactory(title='test', forum=f, posts=[]) p = PostFactory(thread=t, content='test', author=t.creator) f = Forum.objects.get(id=f.id) eq_(f.last_post.id, p.id) # delete the post, verify last_post updated t.delete() f = Forum.objects.get(id=f.id) eq_(f.last_post.id, last_post.id) eq_(Thread.objects.filter(pk=t.id).count(), 0)
def test_edit_post_belongs_to_thread_and_forum(self): # Edit post action - post belongs to thread and thread belongs # to forum. f = ForumFactory() t = ThreadFactory(forum=f) # Post belongs to a different forum and thread. p = PostFactory() 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)
def test_post_absolute_url(self): t = ThreadFactory(posts=[]) # Fill out the first page with posts from yesterday. p1 = PostFactory(thread=t, created=YESTERDAY) PostFactory.create_batch(POSTS_PER_PAGE - 1, created=YESTERDAY, thread=t) # Second page post from today. p2 = PostFactory(thread=t) 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())
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 = UserFactory(username=name) for i in range(number): thread1 = ThreadFactory(title=u'audio') PostFactory(thread=thread1, author=u) 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.advanced'), qs) eq_(total, json.loads(response.content)['total'])
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 = UserFactory(username=name) for i in range(number): thread1 = ThreadFactory(title="audio") PostFactory(thread=thread1, author=u) 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.advanced"), qs) eq_(total, json.loads(response.content)["total"])
def test_edit_post_moderator(self): """Editing post as a moderator works.""" p = PostFactory() t = p.thread f = t.forum # Create the moderator group, give it the edit permission # and add a moderator. moderator_group = GroupFactory() ct = ContentType.objects.get_for_model(f) PermissionFactory(codename='forums_forum.post_edit_forum', content_type=ct, object_id=f.id, group=moderator_group) moderator = UserFactory() 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.objects.get(pk=p.pk) eq_('More new content', edited_p.content)
def test_delete_post_belongs_to_thread_and_forum(self): # Delete post action - post belongs to thread and thread # belongs to forum. f = ForumFactory() t = ThreadFactory(forum=f) # Post belongs to a different forum and thread. p = PostFactory() u = p.author # Give the user the permission to delete posts. g = GroupFactory() ct = ContentType.objects.get_for_model(f) PermissionFactory( codename="forums_forum.post_delete_forum", content_type=ct, object_id=p.thread.forum_id, group=g, ) PermissionFactory(codename="forums_forum.post_delete_forum", content_type=ct, object_id=f.id, group=g) 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_forums_search_authorized_forums_specifying_forums(self): """Only authorized people can search certain forums they specified""" # Create two threads: one in a restricted forum and one not. forum1 = ForumFactory(name=u'ou812forum') thread1 = ThreadFactory(forum=forum1) PostFactory(thread=thread1, content=u'audio') forum2 = RestrictedForumFactory(name=u'restrictedkeepout') thread2 = ThreadFactory(forum=forum2) PostFactory(thread=thread2, content=u'audio restricted') self.refresh() # Do a search as an anonymous user and specify both # forums. Should only see the post from the unrestricted # forum. response = self.client.get(reverse('search.advanced'), { 'author': '', 'created': '0', 'created_date': '', 'updated': '0', 'updated_date': '', 'sortby': '0', 'forum': [forum1.id, forum2.id], 'a': '1', 'w': '4', 'q': 'audio', 'format': 'json' }) eq_(200, response.status_code) content = json.loads(response.content) eq_(content['total'], 1) # Do a search as an authorized user and specify both # forums. Should see both posts. u = UserFactory() g = GroupFactory() g.user_set.add(u) ct = ContentType.objects.get_for_model(forum2) PermissionFactory( codename='forums_forum.view_in_forum', content_type=ct, object_id=forum2.id, group=g) self.client.login(username=u.username, password='******') response = self.client.get(reverse('search.advanced'), { 'author': '', 'created': '0', 'created_date': '', 'updated': '0', 'updated_date': '', 'sortby': '0', 'forum': [forum1.id, forum2.id], 'a': '1', 'w': '4', 'q': 'audio', 'format': 'json' }) # Sees both results eq_(200, response.status_code) content = json.loads(response.content) eq_(content['total'], 2)
def test_forums_thread_created(self): """Tests created/created_date filtering for forums""" post_created_ds = datetime(2010, 1, 1, 12, 00) thread1 = ThreadFactory(title="crash", created=post_created_ds) PostFactory(thread=thread1, created=(post_created_ds + timedelta(hours=1))) self.refresh() # The thread/post should not show up in results for items # created AFTER 1/12/2010. response = self.client.get( reverse("search.advanced"), { "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.advanced"), { "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.advanced"), { "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.advanced"), { "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)
def test_forums_search_authorized_forums_specifying_forums(self): """Only authorized people can search certain forums they specified""" # Create two threads: one in a restricted forum and one not. forum1 = ForumFactory(name="ou812forum") thread1 = ThreadFactory(forum=forum1) PostFactory(thread=thread1, content="audio") forum2 = RestrictedForumFactory(name="restrictedkeepout") thread2 = ThreadFactory(forum=forum2) PostFactory(thread=thread2, content="audio restricted") self.refresh() # Do a search as an anonymous user and specify both # forums. Should only see the post from the unrestricted # forum. response = self.client.get( reverse("search.advanced"), { "author": "", "created": "0", "created_date": "", "updated": "0", "updated_date": "", "sortby": "0", "forum": [forum1.id, forum2.id], "a": "1", "w": "4", "q": "audio", "format": "json", }, ) eq_(200, response.status_code) content = json.loads(response.content) eq_(content["total"], 1) # Do a search as an authorized user and specify both # forums. Should see both posts. u = UserFactory() g = GroupFactory() g.user_set.add(u) ct = ContentType.objects.get_for_model(forum2) PermissionFactory(codename="forums_forum.view_in_forum", content_type=ct, object_id=forum2.id, group=g) self.client.login(username=u.username, password="******") response = self.client.get( reverse("search.advanced"), { "author": "", "created": "0", "created_date": "", "updated": "0", "updated_date": "", "sortby": "0", "forum": [forum1.id, forum2.id], "a": "1", "w": "4", "q": "audio", "format": "json", }, ) # Sees both results eq_(200, response.status_code) content = json.loads(response.content) eq_(content["total"], 2)
def test_forums_thread_created(self): """Tests created/created_date filtering for forums""" post_created_ds = datetime(2010, 1, 1, 12, 00) thread1 = ThreadFactory(title=u'crash', created=post_created_ds) PostFactory(thread=thread1, created=(post_created_ds + timedelta(hours=1))) self.refresh() # The thread/post should not show up in results for items # created AFTER 1/12/2010. response = self.client.get(reverse('search.advanced'), { '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.advanced'), { '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.advanced'), { '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.advanced'), { '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)
def setUp(self): self.post = PostFactory() self.post_id = self.post.id
def test_content_parsed_sanity(self): """The content_parsed field is populated.""" p = PostFactory(thread=self.thread, content='yet another post') eq_('<p>yet another post\n</p>', p.content_parsed)