def test_create_post(self): """Tests creating and getting a post """ # Create a user to test creating post user1 = create_account('user1', '*****@*****.**', 'Password') # Create post post1 = create_post(user1, 'user1', 'Test post') # Check the post actually exists self.assertIsNotNone(post1) # Check that all the hash members are what we expect post = get_post(post1) self.assertIsNotNone(post) self.assertEqual(post.get('_id'), post1) self.assertEqual(post.get('user_id'), user1) self.assertEqual(post.get('body'), 'Test post') self.assertEqual(post.get('score'), 0) self.assertEqual(post.get('comment_count'), 0) # Check the memebers we don't know the answer to self.assertIsNotNone(post.get('created')) self.assertNotIn('upload', post) # Ensure this post is the users feed (populate_feed) self.assertIn(post1, r.zrange(K.USER_FEED.format(user1), 0, -1)) # Testing getting post with invalid arguments # Test getting a post that does not exist self.assertIsNone(get_post(K.NIL_VALUE)) # Create a post with an image image = io.BytesIO(open('tests/upload_test_files/otter.jpg').read()) post2 = create_post(user1, 'user1', 'Test post #2', upload=image) self.assertIsNotNone(post2) post = get_post(post2) self.assertIn('upload', post) self.assertIsNotNone(post.get('upload')) image = io.BytesIO(open('tests/upload_test_files/otter.gif').read()) post3 = create_post(user1, 'user1', 'Test post #2', upload=image) self.assertIsNotNone(post3) post = get_post(post3) self.assertIn('upload', post) self.assertIn('upload_animated', post) self.assertIsNotNone(post.get('upload')) self.assertIsNotNone(post.get('upload_animated')) # Create a post with a broken image, ensure it's handled correctly image = io.BytesIO() post4 = create_post(user1, 'user1', 'Test post #3', upload=image) self.assertIsNone(post4) post4 = get_post(post4) self.assertIsNone(post4)
def test_create_reply(self): """Test that a reply can be made on a post """ user1 = create_account('user1', '*****@*****.**', 'Password') # Create a second test user to test commenting on someone else post user2 = create_account('user2', '*****@*****.**', 'Password') # Create post post1 = create_post(user1, 'user1', 'Test post') # Create comment reply1 = create_post(user1, 'user1', 'Test comment', post1) # Check the comment was created self.assertIsNotNone(get_post(reply1)) # Create a comment by the second user reply2 = create_post(user2, 'user1', 'Test comment', post1) # Check the comment was created self.assertIsNotNone(get_post(reply2)) # Check the comment hash has the data we expect, we will do this with # comment1 comment = get_post(reply1) self.assertIsNotNone(comment) self.assertEqual(comment.get('_id'), reply1) self.assertEqual(comment.get('user_id'), user1) self.assertEqual(comment.get('reply_to'), post1) self.assertEqual(comment.get('body'), 'Test comment') self.assertEqual(comment.get('score'), 0) self.assertIsNotNone(comment.get('created')) self.assertNotIn('upload', comment) # Create a post with an image image = io.BytesIO(open('tests/upload_test_files/otter.jpg').read()) reply1 = create_post(user1, 'user1', 'Test post #2', reply_to=post1, upload=image) self.assertIsNotNone(reply1) comment = get_post(reply1) self.assertIn('upload', comment) self.assertIsNotNone(comment.get('upload')) # Create a post with a broken image, ensure it's handled correctly image = io.BytesIO() reply2 = create_post(user1, 'user1', 'Test post #3', reply_to=post1, upload=image) self.assertIsNone(reply2) comment = get_post(reply2) self.assertIsNone(comment)
def test_get_upload(self): """Tests the simple wrapper around ``lib.uploads.get_upload`` """ user1 = create_account('user1', '*****@*****.**', 'Password') activate(user1) # Create the post with an upload to get image = io.BytesIO(open('tests/upload_test_files/otter.jpg').read()) post1 = create_post(user1, 'user1', 'Test post', upload=image) self.assertIsNotNone(post1) post = get_post(post1) # Try and get the post and ensure we are redirected because we are not # logged in resp = self.client.get(url_for('posts.get_upload', filename=post.get('upload'))) self.assertEqual(resp.status_code, 302) # Log in as user1 and get the upload resp = self.client.post(url_for('auth.signin'), data={ 'username': '******', 'password': '******' }, follow_redirects=True) self.assertEqual(resp.status_code, 200) resp = self.client.get(url_for('posts.get_upload', filename=post.get('upload'))) self.assertEqual(resp.status_code, 200) self.assertEqual(resp.headers['Content-Type'], 'image/png')
def get_stats(): """Provides post level statistics. """ total_posts = m.db.posts.count() total_uploads = m.db.posts.find( {'upload': {'$exists': True}}).count() last_post = m.db.posts.find().sort( [('created', pymongo.DESCENDING)]).limit(1) try: last_post_time = timeify_filter(last_post[0].get('created')) except IndexError: last_post_time = None # Get the 10 highest flagged posts if there is any flagged_posts_cur = m.db.posts.find( {'flags': {'$gt': 0}}).sort('flags', pymongo.DESCENDING).limit(10) flagged_posts = [] for flagged_post in flagged_posts_cur: s = '{0} - <a href="{1}">{2}</a>: <a href="{3}">{4}</a>' + \ ' [<a href="{5}">Unflag</a>]' if flagged_post.get('reply_to') is not None: reply_to = get_post(flagged_post.get('reply_to')) username = reply_to.get('username') post_id = reply_to.get('_id') else: username = flagged_post.get('username') post_id = flagged_post.get('_id') link = s.format( flagged_post.get('flags'), url_for('users.profile', username=flagged_post.get('username')), flagged_post.get('username'), url_for('posts.view_post', username=username, post_id=post_id), flagged_post.get('_id'), url_for('posts.unflag_post', post_id=flagged_post.get('_id')) ) # Highligh comments if flagged_post.get('reply_to') is not None: link = link + ' (comment)' flagged_posts.append(link) if len(flagged_posts) == 0: flagged_posts.append('Empty') return [ ('Total posts', total_posts), ('Total uploads', total_uploads), ('Last post', last_post_time), ('Flagged posts', flagged_posts) ]
def test_permission_setting(self): """Test that a post can have correct permissions set""" user1 = create_account('user1', '*****@*****.**', 'Password') # Create post with each permission post1 = create_post(user1, 'user1', 'Test post', permission=0) post2 = create_post(user1, 'user1', 'Test post', permission=1) post3 = create_post(user1, 'user1', 'Test post', permission=2) post = get_post(post1) self.assertEqual(post.get('permission'), 0) post = get_post(post2) self.assertEqual(post.get('permission'), 1) post = get_post(post3) self.assertEqual(post.get('permission'), 2)
def test_create_post(self): """Tests creating and getting a post """ # Create a user to test creating post user1 = create_account('user1', '*****@*****.**', 'Password') # Create post post1 = create_post(user1, 'user1', 'Test post') # Check the post actually exists self.assertIsNotNone(post1) # Check that all the hash members are what we expect post = get_post(post1) self.assertIsNotNone(post) self.assertEqual(post.get('_id'), post1) self.assertEqual(post.get('user_id'), user1) self.assertEqual(post.get('body'), 'Test post') self.assertEqual(post.get('score'), 0) self.assertEqual(post.get('comment_count'), 0) # Check the memebers we don't know the answer to self.assertIsNotNone(post.get('created')) self.assertNotIn('upload', post) # Ensure this post is the users feed (populate_feed) self.assertIn(post1, r.zrange(K.USER_FEED.format(user1), 0, -1)) # Testing getting post with invalid arguments # Test getting a post that does not exist self.assertIsNone(get_post(K.NIL_VALUE)) # Create a post with an image image = io.BytesIO(open('tests/upload_test_files/otter.jpg').read()) post2 = create_post(user1, 'user1', 'Test post #2', upload=image) self.assertIsNotNone(post2) post = get_post(post2) self.assertIn('upload', post) self.assertIsNotNone(post.get('upload')) # Create a post with a broken image, ensure it's handled correctly image = io.BytesIO() post3 = create_post(user1, 'user1', 'Test post #3', upload=image) self.assertIsNone(post3) post3 = get_post(post3) self.assertIsNone(post3)
def get_stats(): """Provides post level statistics. """ total_posts = m.db.posts.count() total_uploads = m.db.posts.find({"upload": {"$exists": True}}).count() last_post = m.db.posts.find().sort([("created", pymongo.DESCENDING)]).limit(1) try: last_post_time = timeify_filter(last_post[0].get("created")) except IndexError: last_post_time = None # Get the 10 highest flagged posts if there is any flagged_posts_cur = m.db.posts.find({"flags": {"$gt": 0}}).sort("flags", pymongo.DESCENDING).limit(10) flagged_posts = [] for flagged_post in flagged_posts_cur: s = '{0} - <a href="{1}">{2}</a>: <a href="{3}">{4}</a>' + ' [<a href="{5}">Unflag</a>]' if flagged_post.get("reply_to") is not None: reply_to = get_post(flagged_post.get("reply_to")) username = reply_to.get("username") post_id = reply_to.get("_id") else: username = flagged_post.get("username") post_id = flagged_post.get("_id") link = s.format( flagged_post.get("flags"), url_for("users.profile", username=flagged_post.get("username")), flagged_post.get("username"), url_for("posts.view_post", username=username, post_id=post_id), flagged_post.get("_id"), url_for("posts.unflag_post", post_id=flagged_post.get("_id")), ) # Highligh comments if flagged_post.get("reply_to") is not None: link = link + " (comment)" flagged_posts.append(link) if len(flagged_posts) == 0: flagged_posts.append("Empty") return [ ("Total posts", total_posts), ("Total uploads", total_uploads), ("Last post", last_post_time), ("Flagged posts", flagged_posts), ]
def view_post(username, pid): """ Displays a post along with its comments paginated. I am not sure if this should be here or in the 'posts' app. """ if not check_post(get_uid(username), pid): return abort(404) # Pagination page = handle_page(request) # Get post post = get_post(pid) # Get comments pagination = get_comments(pid, page) post_form = PostForm() return render_template('view_post.html', post=post, pagination=pagination, post_form=post_form)
def get_feed(user_id, page=1): """Returns a users feed as a pagination object. .. note: The feed is stored inside Redis still as this requires fan-out to update all the users who are following you. """ per_page = app.config.get('FEED_ITEMS_PER_PAGE') total = r.zcard(k.USER_FEED.format(user_id)) pids = r.zrevrange(k.USER_FEED.format(user_id), (page - 1) * per_page, (page * per_page) - 1) posts = [] for pid in pids: # Get the post post = get_post(pid) if post: posts.append(post) else: # Self cleaning lists r.zrem(k.USER_FEED.format(user_id), pid) total = r.zcard(k.USER_FEED.format(user_id)) return Pagination(posts, total, page, per_page)
def test_delete(self): """ Tests delete_post() does what it should. This will in turn test delete_comments() as this will be triggered when a post is deleted. """ # Create three test users user1 = create_account('user1', '*****@*****.**', 'Password') user2 = create_account('user2', '*****@*****.**', 'Password') # Create a post post1 = create_post(user1, 'user1', 'Test post') # Create multiple comments reply1 = create_post(user1, 'user1', 'Test comment 1', post1) reply2 = create_post(user2, 'user2', 'Test comment 2', post1) reply3 = create_post(user1, 'user1', 'Test comment 3', post1) reply4 = create_post(user2, 'user2', 'Test comment 4', post1) # Check the comment count on post1 is correct self.assertEqual(get_post(post1).get('comment_count'), 4) # Test deleting one comment # This function does not actually test to see if the user has the # the rights to delete the post. This should be tested in the frontend # Check a comment can be deleted self.assertIsNone(delete_post(reply4)) # Check that getting the comment returns None self.assertIsNone(get_post(reply4)) # Ensure the comment count on post1 is correct self.assertEqual(get_post(post1).get('comment_count'), 3) # Delete the post. This should delete all the comments, we will check self.assertIsNone(delete_post(post1)) # Check that the post does not exist self.assertIsNone(get_post(post1)) # Check that non of the comments exist self.assertIsNone(get_post(reply1)) self.assertIsNone(get_post(reply2)) self.assertIsNone(get_post(reply3)) # Test deleting posts with uploads # Ensuring that the images are gone. # The actual deleting is tested in 'test_uploads.py' image = io.BytesIO(open('tests/upload_test_files/otter.jpg').read()) post1 = create_post(user1, 'user1', 'Test post #2', upload=image) self.assertIsNotNone(post1) post1_filename = get_post(post1).get('upload') # Reset the file position in the image image.seek(0) reply1 = create_post(user1, 'user1', 'Test comment 1', post1, upload=image) self.assertIsNotNone(reply1) reply1_filename = get_post(reply1).get('upload') image.seek(0) reply2 = create_post(user2, 'user2', 'Test comment 2', post1, upload=image) self.assertIsNotNone(reply2) reply2_filename = get_post(reply2).get('upload') # Create GridFS file checker grid = gridfs.GridFS(m.db, 'uploads') # Check that each file exists self.assertTrue(grid.exists({'filename': post1_filename})) self.assertTrue(grid.exists({'filename': reply1_filename})) self.assertTrue(grid.exists({'filename': reply2_filename})) self.assertIsNone(delete_post(post1)) # Check that all the files no longer exist self.assertFalse(grid.exists({'filename': post1_filename})) self.assertFalse(grid.exists({'filename': reply1_filename})) self.assertFalse(grid.exists({'filename': reply2_filename}))
def test_votes(self): """ Test that the voting mechanism will adjust the relevant score counters on users, posts and comments, etc... """ # Create three test users user1 = create_account('user1', '*****@*****.**', 'Password') user2 = create_account('user2', '*****@*****.**', 'Password') user3 = create_account('user3', '*****@*****.**', 'Password') # Create a post by user 1 post1 = create_post(user1, 'user1', 'Test post') # Get user 3 to downvote, this will test that the user can not go # negative yet the post can self.assertIsNone(vote_post(user3, post1, amount=-1)) # Ensure post score has been adjusted self.assertEqual(get_post(post1).get('score'), -1) # Ensure user score has NOT been adjusted self.assertEqual(get_user(user1).get('score'), 0) # Get user 2 to upvote self.assertIsNone(vote_post(user2, post1)) # Ensure post score has been adjusted self.assertEqual(get_post(post1).get('score'), 0) # Ensure user score has been adjusted self.assertEqual(get_user(user1).get('score'), 1) # Ensure user 1 can not vote on there own post self.assertRaises(CantVoteOnOwn, lambda: vote_post(user1, post1)) # Ensure the scores have not been adjusted self.assertEqual(get_post(post1).get('score'), 0) self.assertEqual(get_user(user1).get('score'), 1) # Check to see if a user can vote twice on a post self.assertRaises(AlreadyVoted, lambda: vote_post(user2, post1)) # Ensure the scores have not been adjusted self.assertEqual(get_post(post1).get('score'), 0) self.assertEqual(get_user(user1).get('score'), 1) # Repeat the same tests on a comment # Create a comment by user 1 comment1 = create_post(user1, 'user1', 'Test comment', post1) # Let's cheat and set user1's score back to 0 so we can check it will # not be lowered in the user3 downvote m.db.users.update({'_id': user1}, {'$set': {'score': 0}}) # Get user 3 to downvote self.assertIsNone(vote_post(user3, comment1, amount=-1)) # Ensure post score has been adjusted self.assertEqual(get_post(comment1)['score'], -1) # Ensure user score has NOT been adjusted self.assertEqual(get_user(user1)['score'], 0) # Get user 2 to upvote self.assertIsNone(vote_post(user2, comment1)) # Ensure post score has been adjusted self.assertEqual(get_post(comment1).get('score'), 0) # Ensure user score has been adjusted self.assertEqual(get_user(user1).get('score'), 1) # Ensure user 1 can not vote on there own comment self.assertRaises(CantVoteOnOwn, lambda: vote_post(user1, comment1)) # Ensure post score has been adjusted self.assertEqual(get_post(comment1).get('score'), 0) # Ensure user score has been adjusted self.assertEqual(get_user(user1).get('score'), 1) # Check to see if a user can vote twice on a comment self.assertRaises(AlreadyVoted, lambda: vote_post(user2, comment1)) # Ensure post score has been adjusted self.assertEqual(get_post(comment1).get('score'), 0) # Ensure user score has been adjusted self.assertEqual(get_user(user1).get('score'), 1)
def test_votes(self): """ Test that the voting mechanism will adjust the relevant score counters on users, posts and comments, etc... """ # Create three test users user1 = create_account('user1', '*****@*****.**', 'Password') user2 = create_account('user2', '*****@*****.**', 'Password') user3 = create_account('user3', '*****@*****.**', 'Password') # Create a post by user 1 post1 = create_post(user1, 'user1', 'Test post') # Get user 3 to downvote self.assertEqual(vote_post(user3, post1, amount=-1), -1) # Ensure post score has been adjusted self.assertEqual(get_post(post1).get('score'), -1) # Ensure user score has been adjusted self.assertEqual(get_user(user1).get('score'), -1) # Check that a user can reverse their vote within TIMEOUT self.assertEqual(vote_post(user3, post1, amount=-1), 0) self.assertEqual(get_post(post1).get('score'), 0) self.assertEqual(get_user(user1).get('score'), 0) # Get user 2 to upvote self.assertEqual(vote_post(user2, post1), 1) # Ensure post score has been adjusted self.assertEqual(get_post(post1).get('score'), 1) # Ensure user score has been adjusted self.assertEqual(get_user(user1).get('score'), 1) # Ensure user 1 can not vote on there own post self.assertRaises(CantVoteOnOwn, lambda: vote_post(user1, post1)) # Ensure the scores have not been adjusted self.assertEqual(get_post(post1).get('score'), 1) self.assertEqual(get_user(user1).get('score'), 1) # Ensure the user has voted self.assertTrue(has_voted(user2, post1)) # Check that a user can reverse their vote within TIMEOUT self.assertEqual(vote_post(user2, post1), 0) self.assertEqual(get_post(post1).get('score'), 0) self.assertEqual(get_user(user1).get('score'), 0) # Ensure the user has voted self.assertFalse(has_voted(user2, post1)) # Check that the score reflects an opposite vote within TIMEOUT self.assertEqual(vote_post(user2, post1, 1), 1) self.assertEqual(get_post(post1).get('score'), 1) self.assertEqual(get_user(user1).get('score'), 1) self.assertTrue(has_voted(user2, post1)) self.assertEqual(vote_post(user2, post1, -1), -1) self.assertEqual(get_post(post1).get('score'), -1) self.assertEqual(get_user(user1).get('score'), -1) self.assertTrue(has_voted(user2, post1)) # Check that a user can not reverse there vote after the TIMEOUT self.assertRaises(AlreadyVoted, lambda: vote_post(user2, post1, -1, timestamp() + K.VOTE_TIMEOUT + 1)) self.assertRaises(AlreadyVoted, lambda: vote_post(user2, post1, 1, timestamp() + K.VOTE_TIMEOUT + 1)) # Repeat the same tests on a comment # Create a comment by user 1 comment1 = create_post(user1, 'user1', 'Test comment', post1) # Let's cheat and set user1's score back to 0 m.db.users.update({'_id': user1}, {'$set': {'score': 0}}) # Get user 3 to downvote self.assertEqual(vote_post(user3, comment1, amount=-1), -1) # Ensure post score has been adjusted self.assertEqual(get_post(comment1).get('score'), -1) self.assertEqual(get_user(user1).get('score'), -1) # Reverse user3's vote just so it's not confusing self.assertEqual(vote_post(user3, comment1, amount=-1), 0) self.assertEqual(get_post(comment1).get('score'), 0) self.assertEqual(get_user(user1).get('score'), 0) # Ensure user 1 can not vote on there own comment self.assertRaises(CantVoteOnOwn, lambda: vote_post(user1, comment1)) # Ensure post score has been adjusted self.assertEqual(get_post(comment1).get('score'), 0) # Ensure user score has been adjusted self.assertEqual(get_user(user1).get('score'), 0) # Get user 2 to upvote self.assertEqual(vote_post(user2, comment1), 1) # Ensure post score has been adjusted self.assertEqual(get_post(comment1).get('score'), 1) # Ensure user score has been adjusted self.assertEqual(get_user(user1).get('score'), 1) self.assertTrue(has_voted(user2, comment1)) # Check that a user can reverse their vote within TIMEOUT self.assertEqual(vote_post(user2, comment1), 0) self.assertEqual(get_post(comment1).get('score'), 0) self.assertEqual(get_user(user1).get('score'), 0) self.assertFalse(has_voted(user2, comment1)) # Check that the score reflects an opposite vote within TIMEOUT self.assertEqual(vote_post(user2, comment1, -1), -1) self.assertEqual(get_post(comment1).get('score'), -1) self.assertEqual(get_user(user1).get('score'), -1) self.assertTrue(has_voted(user2, comment1)) self.assertEqual(vote_post(user2, comment1, 1), 1) self.assertEqual(get_post(comment1).get('score'), 1) self.assertEqual(get_user(user1).get('score'), 1) self.assertTrue(has_voted(user2, comment1)) # Check that a user can not reverse there vote after the TIMEOUT self.assertRaises(AlreadyVoted, lambda: vote_post(user2, comment1, -1, timestamp() + K.VOTE_TIMEOUT + 1)) self.assertRaises(AlreadyVoted, lambda: vote_post(user2, comment1, 1, timestamp() + K.VOTE_TIMEOUT + 1))
def test_post(self): """ Test that we can post too Pjuu. """ # Lets ensure we can't GET the /post endpoint # You should not be able to GET this resouce but you will not see this # until you are signed in. This should simply redirect us to login resp = self.client.get(url_for('posts.post')) self.assertEqual(resp.status_code, 302) # Lets ensure we can't POST to /post when logged out # As above we should simply be redirected resp = self.client.post(url_for('posts.post'), data={ 'body': 'Test post' }) self.assertEqual(resp.status_code, 302) # Let's create a user an login user1 = create_account('user1', '*****@*****.**', 'Password') # Activate the account self.assertTrue(activate(user1)) # Log the user in resp = self.client.post(url_for('auth.signin'), data={ 'username': '******', 'password': '******' }, follow_redirects=True) self.assertEqual(resp.status_code, 200) # We are now logged in :) Let's ensure we can't GET the /post endpoint resp = self.client.get(url_for('posts.post')) self.assertEqual(resp.status_code, 405) # Lets post a test post # Because we are not passing a next query param we will be redirected # to /test (users profile) after this post resp = self.client.post(url_for('posts.post'), data={ 'body': 'Test post' }, follow_redirects=True) self.assertEqual(resp.status_code, 200) # Let's ensure our new post appears in the output self.assertIn('Test post', resp.data) # We should be on the posts view as we did not pass a next qs self.assertIn('<!-- author post -->', resp.data) # Let's post again but this time lets redirect ourselves back to feed. # We will ensure both posts exist in the feed resp = self.client.post(url_for('posts.post', next=url_for('users.feed')), data={ 'body': 'Second test post' }, follow_redirects=True) self.assertEqual(resp.status_code, 200) # Let's ensure both posts are their self.assertIn('Test post', resp.data) self.assertIn('Second test post', resp.data) # The post endpoint also handles populating followers feeds. We will # create a couple of users (in the backend, we will not test the # frontend here). user2 = create_account('user2', '*****@*****.**', 'Password') activate(user2) follow_user(user2, user1) user3 = create_account('user3', '*****@*****.**', 'Password') activate(user3) follow_user(user3, user1) # Create a post as user 1, we will then log out and ensure these posts # appear in the other users lists resp = self.client.post(url_for('posts.post', next=url_for('users.feed')), data={ 'body': 'Hello followers' }, follow_redirects=True) self.assertEqual(resp.status_code, 200) # Let's ensure all posts are their self.assertIn('Test post', resp.data) self.assertIn('Second test post', resp.data) self.assertIn('Hello followers', resp.data) # Let's ensure the post form is their self.assertIn('<!-- author post -->', resp.data) # We are using the test client so lets log out properly self.client.get(url_for('auth.signout')) # Log in as test2 and ensure the post is in their feed resp = self.client.post(url_for('auth.signin'), data={ 'username': '******', 'password': '******' }, follow_redirects=True) self.assertEqual(resp.status_code, 200) self.assertIn('Hello followers', resp.data) # Log out self.client.get(url_for('auth.signout')) # Log in as test3 and ensure the post in their feed resp = self.client.post(url_for('auth.signin'), data={ 'username': '******', 'password': '******' }, follow_redirects=True) self.assertEqual(resp.status_code, 200) self.assertIn('Hello followers', resp.data) # Log out self.client.get(url_for('auth.signout')) # Sign back in as user1 so that we can keep testing resp = self.client.post(url_for('auth.signin'), data={ 'username': '******', 'password': '******' }, follow_redirects=True) self.assertEqual(resp.status_code, 200) # Back to testing. Let's ensure that users can post unicode text # I copied this Chinese text from a header file on my Mac. I do not # know what it means, I just need the characters resp = self.client.post(url_for('posts.post', next=url_for('users.feed')), data={ 'body': '光铸钥匙' }, follow_redirects=True) self.assertEqual(resp.status_code, 200) # Let's ensure all posts are their self.assertIn('Test post', resp.data) self.assertIn('Second test post', resp.data) self.assertIn('Hello followers', resp.data) self.assertIn('光铸钥匙', resp.data) # Check that a muted user can not create a post # Mute out user mute(user1) resp = self.client.post(url_for('posts.post', next=url_for('users.feed')), data={ 'body': 'Muting test' }, follow_redirects=True) self.assertEqual(resp.status_code, 200) # Let's ensure the warning is there self.assertIn('You have been silenced!', resp.data) self.assertNotIn('Muting test', resp.data) # Un-mute the user and try and post the same thing self.assertTrue(mute(user1, False)) resp = self.client.post(url_for('posts.post', next=url_for('users.feed')), data={ 'body': 'Muting test' }, follow_redirects=True) self.assertEqual(resp.status_code, 200) # Let's ensure the warning is there self.assertNotIn('You have been silenced!', resp.data) self.assertIn('Muting test', resp.data) # Try and post to many characters resp = self.client.post(url_for('posts.post', next=url_for('users.feed')), data={ 'body': ('P' * (MAX_POST_LENGTH + 1)) }, follow_redirects=True) self.assertIn('Posts can not be larger than ' '{0} characters'.format(MAX_POST_LENGTH), resp.data) # Test that we can post 500 unicode characters resp = self.client.post(url_for('posts.post', next=url_for('users.feed')), data={ 'body': ('光' * (MAX_POST_LENGTH)) }, follow_redirects=True) self.assertNotIn('Posts can not be larger than ' '{0} characters'.format(MAX_POST_LENGTH), resp.data) # Test that we can not post more than MAX_POST_LENGTH unicode # characters resp = self.client.post(url_for('posts.post', next=url_for('users.feed')), data={ 'body': ('光' * (MAX_POST_LENGTH + 1)) }, follow_redirects=True) self.assertIn('Posts can not be larger than ' '{0} characters'.format(MAX_POST_LENGTH), resp.data) # Ensure that posting an image with no text still doesn't allow it image = io.BytesIO(open('tests/upload_test_files/otter.jpg').read()) resp = self.client.post( url_for('posts.post'), data={ 'body': '', 'upload': (image, 'otter.jpg') }, follow_redirects=True ) self.assertEqual(resp.status_code, 200) self.assertIn('A message is required.', resp.data) # Test posting with an image image = io.BytesIO(open('tests/upload_test_files/otter.jpg').read()) resp = self.client.post( url_for('posts.post'), data={ 'body': 'Test upload', 'upload': (image, 'otter.jpg') }, follow_redirects=True ) self.assertEqual(resp.status_code, 200) # Goto the users feed an ensure the post is there resp = self.client.get(url_for('users.feed')) self.assertEqual(resp.status_code, 200) # So that we can check the data is in the templates, upload a post # in the backend and ensure it appears where it should image = io.BytesIO(open('tests/upload_test_files/otter.png').read()) post1 = create_post(user1, 'user1', 'Test post', upload=image) self.assertIsNotNone(post1) post = get_post(post1) resp = self.client.get(url_for('users.feed')) self.assertIn('<!-- upload:post:%s -->' % post1, resp.data) self.assertIn('<img src="%s"/>' % url_for('posts.get_upload', filename=post.get('upload')), resp.data) # Although the below belongs in `test_view_post` we are just going to # check it here for simplicity resp = self.client.get(url_for('posts.view_post', username='******', post_id=post1)) self.assertIn('<!-- upload:post:%s -->' % post1, resp.data) self.assertIn('<img src="%s"/>' % url_for('posts.get_upload', filename=post.get('upload')), resp.data)
def test_votes(self): """ Test that the voting mechanism will adjust the relevant score counters on users, posts and comments, etc... """ # Create three test users user1 = create_account('user1', '*****@*****.**', 'Password') user2 = create_account('user2', '*****@*****.**', 'Password') user3 = create_account('user3', '*****@*****.**', 'Password') # Create a post by user 1 post1 = create_post(user1, 'user1', 'Test post') # Get user 3 to downvote self.assertEqual(vote_post(user3, post1, amount=-1), -1) # Ensure post score has been adjusted self.assertEqual(get_post(post1).get('score'), -1) # Ensure user score has been adjusted self.assertEqual(get_user(user1).get('score'), -1) # Check that a user can reverse their vote within TIMEOUT self.assertEqual(vote_post(user3, post1, amount=-1), 0) self.assertEqual(get_post(post1).get('score'), 0) self.assertEqual(get_user(user1).get('score'), 0) # Get user 2 to upvote self.assertEqual(vote_post(user2, post1), 1) # Ensure post score has been adjusted self.assertEqual(get_post(post1).get('score'), 1) # Ensure user score has been adjusted self.assertEqual(get_user(user1).get('score'), 1) # Ensure user 1 can not vote on there own post self.assertRaises(CantVoteOnOwn, lambda: vote_post(user1, post1)) # Ensure the scores have not been adjusted self.assertEqual(get_post(post1).get('score'), 1) self.assertEqual(get_user(user1).get('score'), 1) # Ensure the user has voted self.assertTrue(has_voted(user2, post1)) # Check that a user can reverse their vote within TIMEOUT self.assertEqual(vote_post(user2, post1), 0) self.assertEqual(get_post(post1).get('score'), 0) self.assertEqual(get_user(user1).get('score'), 0) # Ensure the user has voted self.assertFalse(has_voted(user2, post1)) # Check that the score reflects an opposite vote within TIMEOUT self.assertEqual(vote_post(user2, post1, 1), 1) self.assertEqual(get_post(post1).get('score'), 1) self.assertEqual(get_user(user1).get('score'), 1) self.assertTrue(has_voted(user2, post1)) self.assertEqual(vote_post(user2, post1, -1), -1) self.assertEqual(get_post(post1).get('score'), -1) self.assertEqual(get_user(user1).get('score'), -1) self.assertTrue(has_voted(user2, post1)) # Check that a user can not reverse there vote after the TIMEOUT self.assertRaises( AlreadyVoted, lambda: vote_post(user2, post1, -1, timestamp() + K.VOTE_TIMEOUT + 1)) self.assertRaises( AlreadyVoted, lambda: vote_post(user2, post1, 1, timestamp() + K.VOTE_TIMEOUT + 1)) # Repeat the same tests on a comment # Create a comment by user 1 comment1 = create_post(user1, 'user1', 'Test comment', post1) # Let's cheat and set user1's score back to 0 m.db.users.update({'_id': user1}, {'$set': {'score': 0}}) # Get user 3 to downvote self.assertEqual(vote_post(user3, comment1, amount=-1), -1) # Ensure post score has been adjusted self.assertEqual(get_post(comment1).get('score'), -1) self.assertEqual(get_user(user1).get('score'), -1) # Reverse user3's vote just so it's not confusing self.assertEqual(vote_post(user3, comment1, amount=-1), 0) self.assertEqual(get_post(comment1).get('score'), 0) self.assertEqual(get_user(user1).get('score'), 0) # Ensure user 1 can not vote on there own comment self.assertRaises(CantVoteOnOwn, lambda: vote_post(user1, comment1)) # Ensure post score has been adjusted self.assertEqual(get_post(comment1).get('score'), 0) # Ensure user score has been adjusted self.assertEqual(get_user(user1).get('score'), 0) # Get user 2 to upvote self.assertEqual(vote_post(user2, comment1), 1) # Ensure post score has been adjusted self.assertEqual(get_post(comment1).get('score'), 1) # Ensure user score has been adjusted self.assertEqual(get_user(user1).get('score'), 1) self.assertTrue(has_voted(user2, comment1)) # Check that a user can reverse their vote within TIMEOUT self.assertEqual(vote_post(user2, comment1), 0) self.assertEqual(get_post(comment1).get('score'), 0) self.assertEqual(get_user(user1).get('score'), 0) self.assertFalse(has_voted(user2, comment1)) # Check that the score reflects an opposite vote within TIMEOUT self.assertEqual(vote_post(user2, comment1, -1), -1) self.assertEqual(get_post(comment1).get('score'), -1) self.assertEqual(get_user(user1).get('score'), -1) self.assertTrue(has_voted(user2, comment1)) self.assertEqual(vote_post(user2, comment1, 1), 1) self.assertEqual(get_post(comment1).get('score'), 1) self.assertEqual(get_user(user1).get('score'), 1) self.assertTrue(has_voted(user2, comment1)) # Check that a user can not reverse there vote after the TIMEOUT self.assertRaises( AlreadyVoted, lambda: vote_post(user2, comment1, -1, timestamp() + K.VOTE_TIMEOUT + 1)) self.assertRaises( AlreadyVoted, lambda: vote_post(user2, comment1, 1, timestamp() + K.VOTE_TIMEOUT + 1))
def test_replies(self): """ Test commenting on a post. This is a lot simpler than making a post """ # We can not test getting to a comment as we need a post and a user # for this too happen # Let's create a user and login user1 = create_account('user1', '*****@*****.**', 'Password') # Activate the account activate(user1) # Log the user in resp = self.client.post(url_for('auth.signin'), data={ 'username': '******', 'password': '******' }, follow_redirects=True) self.assertEqual(resp.status_code, 200) # Create a post to comment on we will do this in the backend to get # the pid post1 = create_post(user1, 'user1', 'Test post') # Lets attempt to GET to the comment view. Should fail we can only POST # like we can to /post resp = self.client.get(url_for('posts.post', username='******', post_id=post1)) # Method not allowed self.assertEqual(resp.status_code, 405) # Lets post a comment and follow the redirects this should take us to # the comment page resp = self.client.post(url_for('posts.post', username='******', post_id=post1), data={'body': 'Test comment'}, follow_redirects=True) # Lets check that we can see the comment self.assertEqual(resp.status_code, 200) self.assertIn('Test comment', resp.data) # Lets also make sure the form is visible on the page self.assertIn('<!-- author reply -->', resp.data) # Lets signout resp = self.client.get(url_for('auth.signout')) self.assertEqual(resp.status_code, 302) # Lets create another test user and ensure that they can see the # comment user2 = create_account('user2', '*****@*****.**', 'password') # Activate the account activate(user2) # Log the user in resp = self.client.post(url_for('auth.signin'), data={ 'username': '******', 'password': '******' }, follow_redirects=True) self.assertEqual(resp.status_code, 200) # Lets just check that we can see the comment if we go to the view_post # view resp = self.client.get(url_for('posts.view_post', username='******', post_id=post1)) self.assertEqual(resp.status_code, 200) self.assertIn('Test comment', resp.data) # Lets comment ourselves resp = self.client.post(url_for('posts.post', username='******', post_id=post1), data={'body': 'Test comment 2'}, follow_redirects=True) self.assertEqual(resp.status_code, 200) # Check that the 2 comments exist self.assertIn('Test comment', resp.data) self.assertIn('Test comment 2', resp.data) # Lets check we can not comment if we are muted mute(user2) resp = self.client.post(url_for('posts.post', username='******', post_id=post1), data={'body': 'Muting test'}, follow_redirects=True) self.assertEqual(resp.status_code, 200) # Check that the comment was never posted self.assertIn('You have been silenced!', resp.data) self.assertNotIn('Muting test', resp.data) # Reverse the muting and test again mute(user2, False) resp = self.client.post(url_for('posts.post', username='******', post_id=post1), data={'body': 'Muting test'}, follow_redirects=True) self.assertEqual(resp.status_code, 200) # Check that the comment was never posted self.assertNotIn('You have been silenced!', resp.data) self.assertIn('Muting test', resp.data) # Try and post to many characters resp = self.client.post(url_for('posts.post', username='******', post_id=post1), data={ 'body': ('P' * (MAX_POST_LENGTH + 1)) }, follow_redirects=True) self.assertIn('Posts can not be larger than ' '{0} characters'.format(MAX_POST_LENGTH), resp.data) # Test replies with an image image = io.BytesIO(open('tests/upload_test_files/otter.jpg').read()) resp = self.client.post( url_for('posts.post', username='******', post_id=post1), data={ 'body': 'Test upload', 'upload': (image, 'otter.jpg') }, follow_redirects=True ) self.assertEqual(resp.status_code, 200) # So that we can check the data is in the templates, upload a post # in the backend and ensure it appears where it should image = io.BytesIO(open('tests/upload_test_files/otter.png').read()) reply_img = create_post(user1, 'user1', 'Test post', reply_to=post1, upload=image) self.assertIsNotNone(reply_img) reply = get_post(reply_img) resp = self.client.get(url_for('posts.view_post', username='******', post_id=post1)) self.assertIn('<!-- upload:reply:%s -->' % reply_img, resp.data) self.assertIn('<img src="%s"/>' % url_for( 'posts.get_upload', filename=reply.get('upload')), resp.data) # Ensure that posting an image with no text still doesn't allow it image = io.BytesIO(open('tests/upload_test_files/otter.jpg').read()) resp = self.client.post( url_for('posts.post', username='******', post_id=post1), data={ 'body': '', 'upload': (image, 'otter.jpg') }, follow_redirects=True ) self.assertEqual(resp.status_code, 200) self.assertIn('A message is required.', resp.data) # Ensure that an invalid filename is stopped by the forms image = io.BytesIO(open('tests/upload_test_files/otter.jpg').read()) resp = self.client.post( url_for('posts.post', username='******', post_id=post1), data={ 'body': 'Test', 'upload': (image, 'otter.cheese') }, follow_redirects=True ) self.assertEqual(resp.status_code, 200) self.assertIn('Only "gif", "jpg", "jpeg" and "png" files are ' 'supported', resp.data)