def test_check_post(self): """ Will test that check_post returns the correct value with various combinations. Note: Bare with this one it is quite tedious. """ # Create two test users user1 = create_account('user1', '*****@*****.**', 'Password') user2 = create_account('user2', '*****@*****.**', 'Password') # Create a post post1 = create_post(user1, 'user1', 'Test post') # check_post should be True when user 1 creates post 1 self.assertTrue(check_post(user1, post1)) # check_post should be false, user 2 didn't create post 1 self.assertFalse(check_post(user2, post1)) # Create a couple of comments comment1 = create_post(user1, 'user1', 'Test comment', post1) comment2 = create_post(user2, 'user2', 'Test comment', post1) # Ensure the check_post is fine for all self.assertTrue(check_post(user1, post1, comment1)) # This does not look correct but is. See backend.py@check_post self.assertTrue(check_post(user1, post1, comment1)) # Ensure the function isn't broken on comments self.assertFalse(check_post(user2, post1, comment1)) self.assertFalse(check_post(user1, K.NIL_VALUE, comment1)) self.assertFalse(check_post(user2, K.NIL_VALUE, comment2))
def test_get_posts(self): """ Test users post list works correctly """ # Create test user user1 = create_account('user1', '*****@*****.**', 'Password') # Ensure the users post list is empty self.assertEqual(len(get_posts(user1).items), 0) # Create a few test posts, ensure they appears in the users list post1 = create_post(user1, 'user1', 'Test post 1') post2 = create_post(user1, 'user1', 'Test post 2') create_post(user1, 'user1', 'Test post 3') self.assertEqual(len(get_posts(user1).items), 3) self.assertEqual(get_posts(user1).total, 3) # Delete one of the posts and ensure that it does not appear in the # list. delete_post(post1) # Ensure the above is now correct with post1 missing self.assertEqual(len(get_posts(user1).items), 2) self.assertEqual(get_posts(user1).total, 2) # Delete a post from MongoDB with the driver m.db.posts.remove({'_id': post2}) # Ensure the above is now correct with post2 missing self.assertEqual(len(get_posts(user1).items), 1) self.assertEqual(get_posts(user1).total, 1)
def test_get_feed(self): """ Attempt to get a users feed under certain circumstances. """ # Get test user user1 = create_account('user1', '*****@*****.**', 'Password') # Ensure an empty feed is returned. Remember these are paginations self.assertEqual(len(get_feed(user1).items), 0) # Ensure a users own post is added to thier feed post1 = create_post(user1, 'user1', 'Test post') # Ensure the list is the correct length self.assertEqual(len(get_feed(user1).items), 1) self.assertEqual(get_feed(user1).total, 1) # Ensure the item is in Redis self.assertIn(post1, r.zrange(K.USER_FEED.format(user1), 0, -1)) # Create a second user, make 1 follow them, make then post and ensure # that the new users post appears in user 1s feed user2 = create_account('user2', '*****@*****.**', 'Password') follow_user(user1, user2) post2 = create_post(user2, 'user2', 'Test post') # Check user 1's feed for the next item self.assertEqual(len(get_feed(user1).items), 2) self.assertEqual(get_feed(user1).total, 2) # Ensure the item is in Redis self.assertIn(post2, r.zrange(K.USER_FEED.format(user1), 0, -1)) # Delete user 2 and ensure user 1's feed cleans itself delete_account(user2) self.assertEqual(len(get_feed(user1).items), 1) self.assertEqual(get_feed(user1).total, 1) # Ensure the item is not in Redis self.assertNotIn(post2, r.zrange(K.USER_FEED.format(user1), 0, -1))
def test_search(self): """Make sure users can actually find things on the site.""" # Create test user user1 = create_account('user1', '*****@*****.**', 'Password') # Ensure that the user can be found self.assertEqual(len(search('user1').items), 1) self.assertEqual(search('user1').total, 1) # Ensure partial match self.assertEqual(len(search('use').items), 1) self.assertEqual(search('use').total, 1) # Ensure nothing return if no user self.assertEqual(len(search('user2').items), 0) self.assertEqual(search('user2').total, 0) # Ensure no partial if incorrect self.assertEqual(len(search('bob').items), 0) self.assertEqual(search('bob').total, 0) # Create a second test user and a post with a hashtag and # ensure both show in the results. user2 = create_account('user2', '*****@*****.**', 'Password') # Create the post as user1 as we are going to delete user2 create_post(user1, 'user1', '#user2') # Ensure the new user can be found self.assertEqual(len(search('user2').items), 2) self.assertEqual(search('user2').total, 2) # Ensure partial match returns both test1/2 users self.assertEqual(len(search('use').items), 3) self.assertEqual(search('use').total, 3) # Delete the account user2 and try searching again # Only the hashtag should show delete_account(user2) self.assertEqual(search('user2').total, 1)
def test_dump_account(self): """ Test dump_account. We will create some posts and comments and check all this data appears in the dumps Remember that ALL data coming out of Redis is a string. We are not going to convert each type. EVERYTHING IS A STRING """ user1 = create_user('user1', '*****@*****.**', 'Password') # Dump the account so that we can test :D data = dump_account(user1) # Check we got some data self.assertIsNotNone(data) # Ensure that we can see the data in the 'user' key self.assertEqual('user1', data['user']['username']) self.assertEqual('0', data['user']['active']) # Check that uid and password have been scrubbed self.assertEqual('<UID>', data['user']['uid']) self.assertEqual('<PASSWORD HASH>', data['user']['password']) # Ensure posts and comments are None self.assertEqual([], data['posts']) self.assertEqual([], data['comments']) # Create some posts as the user and check they are in the dumps post1 = create_post(user1, 'Post 1') post2 = create_post(user1, 'Post 2') post3 = create_post(user1, 'Post 3') data = dump_account(user1) self.assertIsNotNone(data) # Ensure that the posts are there self.assertNotEqual([], data['posts']) self.assertEqual('Post 1', data['posts'][2]['body']) self.assertEqual('Post 2', data['posts'][1]['body']) self.assertEqual('Post 3', data['posts'][0]['body']) # Ensure there is no a uid in the post self.assertEqual('<UID>', data['posts'][0]['uid']) # Create some comments on the above posts and re-dump comment1 = create_comment(user1, post1, 'Comment 1') comment2 = create_comment(user1, post1, 'Comment 2') comment3 = create_comment(user1, post2, 'Comment 3') comment4 = create_comment(user1, post3, 'Comment 4') # Re-dump the database data = dump_account(user1) self.assertNotEqual([], data['comments']) # Check that all 4 comments have been dumped self.assertEqual('Comment 1', data['comments'][3]['body']) self.assertEqual('Comment 2', data['comments'][2]['body']) self.assertEqual('Comment 3', data['comments'][1]['body']) self.assertEqual('Comment 4', data['comments'][0]['body']) # Testing running dump account with a non-existant user self.assertIsNone(dump_account(K.NIL_VALUE))
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_delete_account_posts_replies(self): """Do all posts and replies get removed on deletion of account? """ user1 = create_account('user1', '*****@*****.**', 'Password') user2 = create_account('user2', '*****@*****.**', 'Password') post1 = create_post(user1, 'user1', 'Test post') post2 = create_post(user2, 'user2', 'Test post') # Create multiple comments on both posts comment1 = create_post(user1, 'user1', "Test comment", post1) create_post(user1, 'user1', "Test comment", post1) create_post(user1, 'user1', "Test comment", post1) create_post(user1, 'user1', "Test comment", post2) delete_account(user1) # All posts created by user1 and the replies on those post, gone? self.assertIsNone(m.db.posts.find_one({'_id': post1})) self.assertIsNone(m.db.posts.find_one({'reply_to': post1})) # Ensure the reply is gone self.assertIsNone(m.db.posts.find_one({'_id': comment1})) # Is feed empty? self.assertFalse(r.lrange(K.USER_FEED.format(user1), 0, -1))
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_flag_control(self): """Ensure flagged posts appear in the dashboard""" user1 = create_account('user1', '*****@*****.**', 'Password') user2 = create_account('user2', '*****@*****.**', 'Password') # Make user1 OP bite(user1) activate(user1) post1 = create_post(user2, 'user2', 'post1') post2 = create_post(user2, 'user2', 'post2') comment1 = create_post(user2, 'user2', 'comment1', post1) comment2 = create_post(user2, 'user2', 'comment2', post1) # Flag all the posts flag_post(user1, post1) flag_post(user1, post2) flag_post(user1, comment1) flag_post(user1, comment2) self.client.post(url_for('auth.signin'), data={ 'username': '******', 'password': '******' }) resp = self.client.get(url_for('dashboard.dashboard')) s = '{0} - <a href="{1}">{2}</a>: <a href="{3}">{4}</a> ' + \ '[<a href="{5}">Unflag</a>]' self.assertIn(s.format( 1, url_for('users.profile', username='******'), 'user2', url_for('posts.view_post', username='******', post_id=post1), post1, url_for('posts.unflag_post', post_id=post1) ), resp.data) self.assertIn(s.format( 1, url_for('users.profile', username='******'), 'user2', url_for('posts.view_post', username='******', post_id=post1), comment1, url_for('posts.unflag_post', post_id=comment1) ) + ' (comment)', resp.data)
def test_remove_from_feed(self): user1 = create_account('user1', '*****@*****.**', 'Password') user2 = create_account('user2', '*****@*****.**', 'Password') # Activate activate(user1) follow_user(user1, user2) post = create_post(user2, 'user2', 'User 2, is here') # Check that the post appears in the users feed resp = self.client.post(url_for('auth.signin'), data={ 'username': '******', 'password': '******' }, follow_redirects=True) self.assertIn('User 2, is here', resp.data) self.assertIn('remove:post:{}'.format(post), resp.data) # Hide the post resp = self.client.post(url_for('users.remove_from_feed', post_id=post), follow_redirects=True) self.assertNotIn('User 2, is here', resp.data) self.assertNotIn('remove:post:{}'.format(post), resp.data) self.assertIn('Message has been removed from feed', resp.data) # Can a user remove their own post? post = create_post(user1, 'user1', 'User 1, is here') # The user should not see a hide button though resp = self.client.get(url_for('users.feed')) self.assertIn('User 1, is here', resp.data) self.assertNotIn('remove:post:{}'.format(post), resp.data) # Ensure the URL hides the post resp = self.client.post(url_for('users.remove_from_feed', post_id=post), follow_redirects=True) self.assertNotIn('User 1, is here', resp.data) self.assertIn('Message has been removed from feed', resp.data) # Ensure removing a post that is not in your feed does not displau a # flash message resp = self.client.post(url_for('users.remove_from_feed', post_id=''), follow_redirects=True) self.assertNotIn('Message has been removed from feed', resp.data)
def test_get_posts_pagination_sizes(self): """Ensure get_posts works with various pagination sizes""" user1 = create_account('user1', '*****@*****.**', 'Password') # Create loads of posts for i in xrange(100): create_post(user1, 'user1', 'Test post {}'.format(i)) FEED_ITEMS_PER_PAGE = app.config.get('FEED_ITEMS_PER_PAGE') self.assertEqual(len(get_posts(user1).items), FEED_ITEMS_PER_PAGE) self.assertEqual(len(get_posts(user1, per_page=25).items), 25) self.assertEqual(len(get_posts(user1, per_page=50).items), 50) self.assertEqual(len(get_posts(user1, per_page=100).items), 100)
def test_approved_feed_population(self): """Ensure only approved users get approved posts but in there feed.""" # Create a user to test creating post user1 = create_account('user1', '*****@*****.**', 'Password') user2 = create_account('user2', '*****@*****.**', 'Password') user3 = create_account('user3', '*****@*****.**', 'Password') follow_user(user2, user1) follow_user(user3, user1) approve_user(user1, user2) create_post(user1, 'user1', 'Test post', permission=K.PERM_APPROVED) self.assertEqual(len(get_feed(user2).items), 1) self.assertEqual(len(get_feed(user3).items), 0)
def test_avatars_hashtag_search(self): """Ensure user avatars appear when searching for posts with a hashtag """ user1 = create_account('user1', '*****@*****.**', 'Password') # Activate it activate(user1) # Signin self.client.post(url_for('auth.signin'), data={ 'username': '******', 'password': '******' }) # Ensure user avatar appear in the search when searching for hashtags image = io.BytesIO(open('tests/upload_test_files/otter.jpg').read()) self.client.post(url_for('users.settings_profile'), data={ 'upload': (image, 'otter.png') }, follow_redirects=True) # Get the user so we can see if the avatar is appearing user = get_user(user1) # Create a post to search for post1 = create_post(user1, 'user1', 'Hello #pjuuie\'s') resp = self.client.get(url_for('users.search', query='#pjuuie')) self.assertIn('<!-- list:post:%s -->' % post1, resp.data) self.assertIn(url_for('posts.get_upload', filename=user.get('avatar')), resp.data)
def test_get_feed_pagination_sizes(self): """Ensure that getting the feed at different pagination sizes work""" user1 = create_account('user1', '*****@*****.**', 'Password') user2 = create_account('user2', '*****@*****.**', 'Password') follow_user(user1, user2) # Create lots of posts so they apear in user1's feed. for i in xrange(101): create_post(user2, 'user2', 'Post {}'.format(i)) FEED_ITEMS_PER_PAGE = app.config.get('FEED_ITEMS_PER_PAGE') self.assertEqual(len(get_feed(user1).items), FEED_ITEMS_PER_PAGE) self.assertEqual(len(get_feed(user1, per_page=25).items), 25) self.assertEqual(len(get_feed(user1, per_page=50).items), 50) self.assertEqual(len(get_feed(user1, per_page=100).items), 100)
def test_avatars_hashtag_search(self): """Ensure user avatars appear when searching for posts with a hashtag """ user1 = create_account('user1', '*****@*****.**', 'Password') # Activate it activate(user1) # Signin self.client.post(url_for('auth.signin'), data={ 'username': '******', 'password': '******' }) # Ensure user avatar appear in the search when searching for hashtags image = io.BytesIO(open('tests/upload_test_files/otter.jpg').read()) self.client.post(url_for('users.settings_profile'), data={'upload': (image, 'otter.png')}, follow_redirects=True) # Get the user so we can see if the avatar is appearing user = get_user(user1) # Create a post to search for post1 = create_post(user1, 'user1', 'Hello #pjuuie\'s') resp = self.client.get(url_for('users.search', query='#pjuuie')) self.assertIn('<!-- list:post:%s -->' % post1, resp.data) self.assertIn(url_for('posts.get_upload', filename=user.get('avatar')), resp.data)
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 test_get_comments(self): """ Ensure a posts comments are stored correctly in post:$pid:comments list """ # Create two test users user1 = create_user('user1', '*****@*****.**', 'Password') user2 = create_user('user2', '*****@*****.**', 'Password') # Ensure the comment lists are empty self.assertEqual(len(get_comments(user1).items), 0) self.assertEqual(len(get_comments(user2).items), 0) # Create a post for each user and a comment on each for both user post1 = create_post(user1, 'Test post') post2 = create_post(user2, 'Test post') comment1 = create_comment(user1, post1, 'Test comment') comment2 = create_comment(user1, post2, 'Test comment') comment3 = create_comment(user2, post1, 'Test comment') comment4 = create_comment(user2, post2, 'Test comment') # Ensure each comment appears in each users list self.assertEqual(len(get_comments(post1).items), 2) self.assertEqual(len(get_comments(post2).items), 2) # Ensure the totals are correct self.assertEqual(get_comments(post1).total, 2) self.assertEqual(get_comments(post2).total, 2) # Ensure the ids are in the Redis lists self.assertIn(comment1, r.lrange(K.POST_COMMENTS.format(post1), 0, -1)) self.assertIn(comment2, r.lrange(K.POST_COMMENTS.format(post2), 0, -1)) self.assertIn(comment3, r.lrange(K.POST_COMMENTS.format(post1), 0, -1)) self.assertIn(comment4, r.lrange(K.POST_COMMENTS.format(post2), 0, -1)) # Delete 1 comment from post1 and ensure it does not exist delete_comment(comment1) # Check that is has gone self.assertEqual(len(get_comments(post1).items), 1) self.assertEqual(get_comments(post1).total, 1) # Ensure it is missing from Redis self.assertNotIn(comment1, r.lrange(K.POST_COMMENTS.format(user1), 0, -1)) # Delete a comment from inside Redis. This will trigger the self # cleaning list feature. We call these orphaned cids. r.delete(K.COMMENT.format(comment2)) # Check that it has gone when get_comments is called self.assertEqual(len(get_comments(post2).items), 1) self.assertEqual(get_comments(post2).total, 1) # Ensure it is missing from Redis self.assertNotIn(comment2, r.lrange(K.POST_COMMENTS.format(user1), 0, -1))
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 test_get_posts(self): """ Test users post list works correctly """ # Create test user user1 = create_user('user1', '*****@*****.**', 'Password') # Ensure the users post list is empty self.assertEqual(len(get_posts(user1).items), 0) # Create a few test posts, ensure they appears in the users list post1 = create_post(user1, 'Test post 1') post2 = create_post(user1, 'Test post 2') post3 = create_post(user1, 'Test post 3') self.assertEqual(len(get_posts(user1).items), 3) self.assertEqual(get_posts(user1).total, 3) # Ensure the post ids are in the Redis list self.assertIn(post1, r.lrange(K.USER_POSTS.format(user1), 0, -1)) self.assertIn(post2, r.lrange(K.USER_POSTS.format(user1), 0, -1)) self.assertIn(post3, r.lrange(K.USER_POSTS.format(user1), 0, -1)) # Delete one of the posts and ensure that it does not appear in the # list. delete_post(post1) # Ensure the above is now correct with post1 missing self.assertEqual(len(get_posts(user1).items), 2) self.assertEqual(get_posts(user1).total, 2) # Ensure the post ids are in the Redis list and post1 is NOT self.assertNotIn(post1, r.lrange(K.USER_POSTS.format(user1), 0, -1)) self.assertIn(post2, r.lrange(K.USER_POSTS.format(user1), 0, -1)) self.assertIn(post3, r.lrange(K.USER_POSTS.format(user1), 0, -1)) # Delete a post from inside Redis. This will trigger the self cleaning # list feature. We call these orphaned pids r.delete(K.POST.format(post2)) # Ensure the above is now correct with post2 missing self.assertEqual(len(get_posts(user1).items), 1) self.assertEqual(get_posts(user1).total, 1) # Ensure the post ids are not in the Redis list and post1 is NOT self.assertNotIn(post1, r.lrange(K.USER_POSTS.format(user1), 0, -1)) self.assertNotIn(post2, r.lrange(K.USER_POSTS.format(user1), 0, -1)) self.assertIn(post3, r.lrange(K.USER_POSTS.format(user1), 0, -1))
def test_alerts(self): """ Unlike the test_alerts() definition in the users package this just tests that TaggingAlert and CommentingAlert are generated in the right situation """ # Create 3 test users user1 = create_account('user1', '*****@*****.**', 'Password') user2 = create_account('user2', '*****@*****.**', 'Password') user3 = create_account('user3', '*****@*****.**', 'Password') # No need to activate the accounts activate(user1) activate(user2) activate(user3) # User1 tag user2 in a post post1 = create_post(user1, 'user1', 'Hello @user2') # Get alerts for test2 and check that it is correct alert = get_alerts(user2).items[0] self.assertTrue(isinstance(alert, TaggingAlert)) self.assertEqual(alert.user['username'], 'user1') self.assertEqual(alert.user['email'], '*****@*****.**') self.assertIn('tagged you in a', alert.prettify()) # Have user2 comment on a the post and check that user1 has the alert create_post(user2, 'user2', 'Hello', post1) # User 1 should now have a commenting alert from user2 alert = get_alerts(user1).items[0] self.assertTrue(isinstance(alert, CommentingAlert)) self.assertEqual(alert.user['username'], 'user2') self.assertEqual(alert.user['email'], '*****@*****.**') # Please remember that prettify requires a uid to format it to self.assertIn('commented on a', alert.prettify(user1)) self.assertIn('you posted', alert.prettify(user1)) # Create a comment as user3 so they become subscribed create_post(user3, 'user3', 'Hello', post1) # Check that if user1 posts a comment user2 get a tagging alert create_post(user1, 'user1', 'Hello', post1) # Check alerts for user2 alert = get_alerts(user2).items[0] self.assertTrue(isinstance(alert, CommentingAlert)) self.assertIn('you were tagged in', alert.prettify(user2)) # Check alerts for user3 alert = get_alerts(user3).items[0] self.assertTrue(isinstance(alert, CommentingAlert)) self.assertIn('you commented on', alert.prettify(user3)) # To check that an invalid subscription reason returns the generic # reason. This should not happen on the site. # Manually change the score in Redis to a high number r.zincrby(K.POST_SUBSCRIBERS.format(post1), user3, 100) # Check the new prettify message alert = get_alerts(user3).items[0] self.assertTrue(isinstance(alert, CommentingAlert)) self.assertIn('you are subscribed to', alert.prettify(user3))
def test_flag_control(self): """Ensure flagged posts appear in the dashboard""" user1 = create_account('user1', '*****@*****.**', 'Password') user2 = create_account('user2', '*****@*****.**', 'Password') # Make user1 OP bite(user1) activate(user1) post1 = create_post(user2, 'user2', 'post1') post2 = create_post(user2, 'user2', 'post2') comment1 = create_post(user2, 'user2', 'comment1', post1) comment2 = create_post(user2, 'user2', 'comment2', post1) # Flag all the posts flag_post(user1, post1) flag_post(user1, post2) flag_post(user1, comment1) flag_post(user1, comment2) self.client.post(url_for('auth.signin'), data={ 'username': '******', 'password': '******' }) resp = self.client.get(url_for('dashboard.dashboard')) s = '{0} - <a href="{1}">{2}</a>: <a href="{3}">{4}</a> ' + \ '[<a href="{5}">Unflag</a>]' self.assertIn( s.format( 1, url_for('users.profile', username='******'), 'user2', url_for('posts.view_post', username='******', post_id=post1), post1, url_for('posts.unflag_post', post_id=post1)), resp.data) self.assertIn( s.format( 1, url_for('users.profile', username='******'), 'user2', url_for('posts.view_post', username='******', post_id=post1), comment1, url_for('posts.unflag_post', post_id=comment1)) + ' (comment)', resp.data)
def test_get_hashtagged_posts_pagination_sizes(self): """Ensure the correct number of hashtagged posts are returned when pagination sizes have been changed. """ user1 = create_account('user1', '*****@*****.**', 'Password') # Create loads of posts for i in xrange(100): create_post(user1, 'user1', 'Test post {} #test'.format(i)) FEED_ITEMS_PER_PAGE = app.config.get('FEED_ITEMS_PER_PAGE') self.assertEqual(len(get_hashtagged_posts('test').items), FEED_ITEMS_PER_PAGE) self.assertEqual(len(get_hashtagged_posts('test', per_page=25).items), 25) self.assertEqual(len(get_hashtagged_posts('test', per_page=50).items), 50) self.assertEqual(len(get_hashtagged_posts('test', per_page=100).items), 100)
def test_get_hashtagged_posts_pagination_sizes(self): """Ensure the correct number of hashtagged posts are returned when pagination sizes have been changed. """ user1 = create_account('user1', '*****@*****.**', 'Password') # Create loads of posts for i in xrange(100): create_post(user1, 'user1', 'Test post {} #test'.format(i)) FEED_ITEMS_PER_PAGE = app.config.get('FEED_ITEMS_PER_PAGE') self.assertEqual( len(get_hashtagged_posts('test').items), FEED_ITEMS_PER_PAGE) self.assertEqual( len(get_hashtagged_posts('test', per_page=25).items), 25) self.assertEqual( len(get_hashtagged_posts('test', per_page=50).items), 50) self.assertEqual( len(get_hashtagged_posts('test', per_page=100).items), 100)
def test_back_feed(self): """Test the back feed feature, once a user follows another user it places their latest 5 posts on their feed. They will be in chronologic order. I know that ``back_feed()`` is a posts feature but it is triggered on follow. """ user1 = create_account('user1', '*****@*****.**', 'Password') user2 = create_account('user2', '*****@*****.**', 'Password') # Create 6 test posts ('Test 1' shouldn't be back fed) post1 = create_post(user1, 'user1', 'Test 1') post2 = create_post(user1, 'user1', 'Test 2') post3 = create_post(user1, 'user1', 'Test 3') post4 = create_post(user1, 'user1', 'Test 4') post5 = create_post(user1, 'user1', 'Test 5') post6 = create_post(user1, 'user1', 'Test 6') follow_user(user2, user1) # Check that the posts are in the feed (we can do this in Redis) feed = r.zrevrange(k.USER_FEED.format(user2), 0, -1) self.assertNotIn(post1, feed) self.assertIn(post2, feed) self.assertIn(post3, feed) self.assertIn(post4, feed) self.assertIn(post5, feed) self.assertIn(post6, feed)
def test_advanced_search(self): """Cover using the `@` and `#` modifiers to limit the search type. """ user1 = create_account('user1', '*****@*****.**', 'Password') user2 = create_account('user2', '*****@*****.**', 'Password') create_post(user1, 'user1', '#pjuu #user2') create_post(user2, 'user2', '#pjuu #user1') for i in range(1, 101): create_post(user1, 'user1', '#pagination{}'.format(i)) # Try come basic search terms self.assertEqual(search('user').total, 4) self.assertEqual(search('user1').total, 2) self.assertEqual(search('user2').total, 2) self.assertEqual(search('pjuu').total, 2) # Users only self.assertEqual(search('@user').total, 2) self.assertEqual(search('@user1').total, 1) # erroneous spacing doesn't matter self.assertEqual(search('@ us').total, 2) # Posts only self.assertEqual(search('#user').total, 2) self.assertEqual(search('#user1').total, 1) self.assertEqual(search('#pjuu').total, 2) # Test pagination in search self.assertEqual(len(search('#pagination', 1, 50).items), 50) self.assertEqual(len(search('#pagination', 2, 50).items), 50)
def test_stats(self): """Ensure the ``pjuu.posts`` exposed stats are correct """ stats = dict(get_stats()) self.assertEqual(stats.get('Total posts'), 0) self.assertEqual(stats.get('Total uploads'), 0) self.assertIsNone(stats.get('Last post')) user1 = create_account('user1', '*****@*****.**', 'Password') post1 = create_post(user1, 'user1', 'Test post 1') create_post(user1, 'user1', 'Test reply 1', post1) image = io.BytesIO(open('tests/upload_test_files/otter.jpg').read()) create_post(user1, 'user1', 'Test post #2', upload=image) stats = dict(get_stats()) self.assertEqual(stats.get('Total posts'), 3) self.assertEqual(stats.get('Total uploads'), 1) self.assertIsNotNone(stats.get('Last post'))
def test_xhr_decorators(self): """Ensure we get a 403 if we XHR request something we need to logged in for. """ user1 = create_account("user1", "*****@*****.**", "Password") post1 = create_post(user1, "user1", "Test") activate(user1) resp = self.client.post( url_for("posts.upvote", username="******", post_id=post1), headers=[("X-Requested-With", "XMLHttpRequest")] ) self.assertEqual(resp.status_code, 403)
def test_delete_account_posts_comments(self): """ Test delete_account() Posts and comments: Ensure all posts and comments are gone. Note: This is not a full test of the posts system. See posts/test.py """ # Create test user user1 = create_user('user1', '*****@*****.**', 'Password') # Second user to test deletion from user:1:comments user2 = create_user('user2', '*****@*****.**', 'Password') # Create a post as both users post1 = create_post(user1, "Test post") post2 = create_post(user2, "Test post") # Create multiple comments on both posts # Post 1 comment1 = create_comment(user1, post1, "Test comment") comment2 = create_comment(user1, post1, "Test comment") # Post 2 comment3 = create_comment(user1, post2, "Test comment") comment4 = create_comment(user1, post2, "Test comment") # Delete the account delete_account(user1) # Ensure the Post, its comment list and votes has gone self.assertFalse(r.hgetall(K.POST.format(post1))) self.assertFalse(r.lrange(K.POST_COMMENTS.format(post1), 0, -1)) # Ensure the Comment is gone self.assertFalse(r.hgetall(K.COMMENT.format(comment1))) # Assert feed is empty self.assertFalse(r.lrange(K.USER_FEED.format(user1), 0, -1)) # Assert posts is empty self.assertFalse(r.lrange(K.USER_POSTS.format(user1), 0, -1)) # Assert comments is empty self.assertFalse(r.lrange(K.USER_COMMENTS.format(user1), 0, -1))
def test_get_replies(self): """Test getting all replies for a post """ # Create two test users user1 = create_account('user1', '*****@*****.**', 'Password') user2 = create_account('user2', '*****@*****.**', 'Password') # Create a post for each user and a comment on each for both user post1 = create_post(user1, 'user1', 'Test post') post2 = create_post(user2, 'user2', 'Test post') # Ensure the comment lists are empty self.assertEqual(len(get_replies(post1).items), 0) self.assertEqual(len(get_replies(post2).items), 0) reply1 = create_post(user1, 'user1', 'Test comment', post1) reply2 = create_post(user1, 'user1', 'Test comment', post2) reply3 = create_post(user2, 'user2', 'Test comment', post1) reply4 = create_post(user2, 'user2', 'Test comment', post2) # Ensure each comment appears in each users list self.assertEqual(len(get_replies(post1).items), 2) self.assertEqual(len(get_replies(post2).items), 2) # Ensure the totals are correct self.assertEqual(get_replies(post1).total, 2) self.assertEqual(get_replies(post2).total, 2) # Ensure comments are in MongoDB comment_ids = \ [doc['_id'] for doc in m.db.posts.find({'reply_to': post1})] self.assertIn(reply1, comment_ids) self.assertIn(reply3, comment_ids) comment_ids = \ [doc['_id'] for doc in m.db.posts.find({'reply_to': post2})] self.assertIn(reply2, comment_ids) self.assertIn(reply4, comment_ids) # Delete 1 comment from post1 and ensure it does not exist delete_post(reply1) # Check that is has gone self.assertEqual(len(get_replies(post1).items), 1) self.assertEqual(get_replies(post1).total, 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_subscriptions(self): """ Test the backend subscription system. This includes subscribe(), unsubscribe() and is_subscribed(). This will also test the correct subscriptions after a post, comment or tagging. """ # Create a couple of test accounts user1 = create_account('user1', '*****@*****.**', 'Password') user2 = create_account('user2', '*****@*****.**', 'Password') user3 = create_account('user3', '*****@*****.**', 'Password') activate(user1) activate(user2) activate(user3) # Post as user 1 and ensure user 1 exists in Redis post1 = create_post(user1, 'user1', 'Test post 1') self.assertIsNotNone(r.zrank(K.POST_SUBSCRIBERS.format(post1), user1)) # Even though it is exactly the same as the above ensure that # is_subscribed() returns True self.assertTrue(is_subscribed(user1, post1)) # Lets ensure this actually fails! And see if user2 is a subscriber self.assertFalse(is_subscribed(user2, post1)) # Ensure that the REASON (zset score) is set to the correct value self.assertEqual(r.zscore(K.POST_SUBSCRIBERS.format(post1), user1), SubscriptionReasons.POSTER) # Post a comment as user 1 and ensure the reason does NOT changes create_post(user1, 'user1', 'Test comment', post1) # Ensure our reason did not change # If we were not subscribed we would be given reason 2 (COMMENTER) self.assertNotEqual(r.zscore(K.POST_SUBSCRIBERS.format(post1), user1), SubscriptionReasons.COMMENTER) # Test unsubscribe self.assertTrue(unsubscribe(user1, post1)) # Ensure that is_subscribed shows correct self.assertFalse(is_subscribed(user1, post1)) # Test that if we unsubscribe again we get a False result self.assertFalse(unsubscribe(user1, post1)) # Check that unsubscribing some that was never subscribed returns false self.assertFalse(unsubscribe(user2, post1)) # Let's test that commenting subscribes us to the post with the correct # reason. Try tag yourself at the same time create_post(user1, 'user1', 'Test comment @user1', post1) # Ensure we are subscribed self.assertTrue(is_subscribed(user1, post1)) # Check that our reason HAS changed self.assertEqual(r.zscore(K.POST_SUBSCRIBERS.format(post1), user1), SubscriptionReasons.COMMENTER) # Create a comment as test2 and ensure this user becomes subscribed for # the same reason create_post(user2, 'user2', 'Test comment', post1) self.assertTrue(is_subscribed(user2, post1)) self.assertEqual(r.zscore(K.POST_SUBSCRIBERS.format(post1), user2), SubscriptionReasons.COMMENTER) # Create a new post as test1 and tag test2 and test3 in it # ensure all 3 are subscribed and test2 and test3 have the correct # reason. # Also try and tag ourselves this should have no affect # Try tagging someone that does not even exist post2 = create_post(user1, 'user1', 'Test post @user1 @user2 @user3 @user4') self.assertTrue(is_subscribed(user2, post2)) self.assertTrue(is_subscribed(user3, post2)) self.assertEqual(r.zscore(K.POST_SUBSCRIBERS.format(post2), user2), SubscriptionReasons.TAGEE) self.assertEqual(r.zscore(K.POST_SUBSCRIBERS.format(post2), user3), SubscriptionReasons.TAGEE) # Test tagging user 3 in a comment on post1. This ensures that tags # in comments do work. create_post(user2, 'user2', 'Test comment @user3', post1) self.assertTrue(is_subscribed(user3, post1)) self.assertEqual(r.zscore(K.POST_SUBSCRIBERS.format(post1), user3), SubscriptionReasons.TAGEE) # Unsubscribe user2 and user3 self.assertTrue(unsubscribe(user2, post2)) self.assertFalse(is_subscribed(user2, post2)) self.assertTrue(unsubscribe(user3, post2)) self.assertFalse(is_subscribed(user3, post2)) # Ensure that subscribe doe not happen when it is not a valid post self.assertFalse( subscribe(user1, K.NIL_VALUE, SubscriptionReasons.POSTER))
def test_feed_profile(self): """ Feed has been tested else where. This is just a formal test of this. We will post a lot of posts as 2 users so we can trigger pagination etc, etc. """ # Create 2 users and have them follow each other user1 = create_account('user1', '*****@*****.**', 'Password') user2 = create_account('user2', '*****@*****.**', 'Password') activate(user1) activate(user2) follow_user(user1, user2) follow_user(user2, user1) # Both users are now following each other. Let's create 30 posts as # each user this will trigger a couple of Pagination pages on the feeds # and also trigger a page on the profile # We need to store a list of the pids since UUIDs became available posts = [] for i in range(0, 51): posts.append(create_post(user1, 'user1', 'User 1, Post %d!' % i)) posts.append(create_post(user2, 'user1', 'User 2, Post %d!' % i)) # We now have 60 posts on each feed # Try and visit the feed when not logged in # There is no flash message to check. resp = self.client.get(url_for('users.feed')) self.assertEqual(resp.status_code, 302) # Log in as user 1 and check that they can see a couple of posts on the # first page resp = self.client.post(url_for('auth.signin'), data={ 'username': '******', 'password': '******' }, follow_redirects=True) # This sends us too / (feed) by defaults self.assertEqual(resp.status_code, 200) self.assertIn('User 1, Post 50!', resp.data) self.assertIn('User 2, Post 50!', resp.data) # Makre sure posts more than 25 ago (default pagination break) self.assertNotIn('User 1, Post 1!', resp.data) self.assertNotIn('User 2, Post 1!', resp.data) # Check the pagination button for next is there are not prev self.assertIn('<!-- pagination:older -->', resp.data) self.assertIn('<!-- pagination:oldest -->', resp.data) self.assertNotIn('<!-- pagination:newer -->', resp.data) self.assertNotIn('<!-- pagination:newerest -->', resp.data) # Let's go to page 2 in the pagination and check there are posts there resp = self.client.get(url_for('users.feed', page=2)) # Check some posts are there and are not there self.assertIn('User 1, Post 30!', resp.data) self.assertIn('User 2, Post 30!', resp.data) self.assertNotIn('User 1, Post 10!', resp.data) self.assertNotIn('User 2, Post 5!', resp.data) # Check that both pagination buttons are there self.assertIn('<!-- pagination:older -->', resp.data) self.assertIn('<!-- pagination:oldest -->', resp.data) self.assertIn('<!-- pagination:newer -->', resp.data) self.assertIn('<!-- pagination:newest -->', resp.data) # Let's go back to the first page resp = self.client.get(url_for('users.feed')) # We will delete one post and ensure that is goes missing self.assertIn('User 1, Post 50!', resp.data) # We won't check that the delete button belong to the above post # put we will check that there is at least one delete button self.assertIn('<!-- delete:post:', resp.data) # Delete the post resp = self.client.post(url_for('posts.delete_post', username='******', post_id=posts[100], next=url_for('users.feed')), follow_redirects=True) self.assertEqual(resp.status_code, 200) self.assertIn('User 1, Post 49!', resp.data) self.assertNotIn('User 1, Post 50!', resp.data) # Check you can not go to a profile for a non-existant user resp = self.client.get(url_for('users.profile', username='******')) self.assertEqual(resp.status_code, 404)
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_dump_account(self): """Can a user get their data? """ user1 = create_account('user1', '*****@*****.**', 'Password') activate(user1) data = dump_account(user1) self.assertIsNotNone(data) # Got data? self.assertEqual('user1', data['user']['username']) self.assertTrue(data['user']['active']) # Has sensitive data been removed? self.assertEqual('<UID>', data['user']['_id']) self.assertEqual('<PASSWORD HASH>', data['user']['password']) self.assertEqual([], data['posts']) # Can they dump posts? post1 = create_post(user1, 'user1', 'Post 1') post2 = create_post(user1, 'user1', 'Post 2') post3 = create_post(user1, 'user1', 'Post 3') data = dump_account(user1) self.assertIsNotNone(data) self.assertNotEqual([], data['posts']) self.assertEqual('Post 1', data['posts'][2]['body']) self.assertEqual('Post 2', data['posts'][1]['body']) self.assertEqual('Post 3', data['posts'][0]['body']) self.assertEqual('<UID>', data['posts'][0]['user_id']) # What about replies? create_post(user1, 'user1', 'Comment 1', post1) create_post(user1, 'user1', 'Comment 2', post1) create_post(user1, 'user1', 'Comment 3', post2) create_post(user1, 'user1', 'Comment 4', post3) data = dump_account(user1) self.assertNotEqual([], data['posts']) self.assertEqual('Comment 1', data['posts'][3]['body']) self.assertEqual('Comment 2', data['posts'][2]['body']) self.assertEqual('Comment 3', data['posts'][1]['body']) self.assertEqual('Comment 4', data['posts'][0]['body']) # Senstive data? self.assertEqual('<UID>', data['posts'][0]['user_id']) # Testing running dump account with a non-existent user self.assertIsNone(dump_account(K.NIL_VALUE)) # Test that user id's a hidden in mentions user2 = create_account('user2', '*****@*****.**', 'Password') activate(user2) user3 = create_account('user3', '*****@*****.**', 'Password') activate(user3) post1 = create_post(user1, 'user1', 'Hello @user2') post_json = json.dumps(dump_account(user1)) self.assertNotIn(user2, post_json) post2 = create_post(user1, 'user1', 'Hello @user2 and @user3') post_json = json.dumps(dump_account(user1)) self.assertNotIn(user2, post_json) self.assertNotIn(user3, post_json)
def test_subscriptions(self): """ Test the backend subscription system. This includes subscribe(), unsubscribe() and is_subscribed(). This will also test the correct subscriptions after a post, comment or tagging. """ # Create a couple of test accounts user1 = create_account('user1', '*****@*****.**', 'Password') user2 = create_account('user2', '*****@*****.**', 'Password') user3 = create_account('user3', '*****@*****.**', 'Password') # Post as user 1 and ensure user 1 exists in Redis post1 = create_post(user1, 'user1', 'Test post 1') self.assertIsNotNone(r.zrank(K.POST_SUBSCRIBERS.format(post1), user1)) # Even though it is exactly the same as the above ensure that # is_subscribed() returns True self.assertTrue(is_subscribed(user1, post1)) # Lets ensure this actually fails! And see if user2 is a subscriber self.assertFalse(is_subscribed(user2, post1)) # Ensure that the REASON (zset score) is set to the correct value self.assertEqual(r.zscore(K.POST_SUBSCRIBERS.format(post1), user1), SubscriptionReasons.POSTER) # Post a comment as user 1 and ensure the reason does NOT changes create_post(user1, 'user1', 'Test comment', post1) # Ensure our reason did not change # If we were not subscribed we would be given reason 2 (COMMENTER) self.assertNotEqual(r.zscore(K.POST_SUBSCRIBERS.format(post1), user1), SubscriptionReasons.COMMENTER) # Test unsubscribe self.assertTrue(unsubscribe(user1, post1)) # Ensure that is_subscribed shows correct self.assertFalse(is_subscribed(user1, post1)) # Test that if we unsubscribe again we get a False result self.assertFalse(unsubscribe(user1, post1)) # Check that unsubscribing some that was never subscribed returns false self.assertFalse(unsubscribe(user2, post1)) # Let's test that commenting subscribes us to the post with the correct # reason. Try tag yourself at the same time create_post(user1, 'user1', 'Test comment @user1', post1) # Ensure we are subscribed self.assertTrue(is_subscribed(user1, post1)) # Check that our reason HAS changed self.assertEqual(r.zscore(K.POST_SUBSCRIBERS.format(post1), user1), SubscriptionReasons.COMMENTER) # Create a comment as test2 and ensure this user becomes subscribed for # the same reason create_post(user2, 'user2', 'Test comment', post1) self.assertTrue(is_subscribed(user2, post1)) self.assertEqual(r.zscore(K.POST_SUBSCRIBERS.format(post1), user2), SubscriptionReasons.COMMENTER) # Create a new post as test1 and tag test2 and test3 in it # ensure all 3 are subscribed and test2 and test3 have the correct # reason. # Also try and tag ourselves this should have no affect # Try tagging someone that does not even exist post2 = create_post(user1, 'user1', 'Test post @user1 @user2 @user3 @user4') self.assertTrue(is_subscribed(user2, post2)) self.assertTrue(is_subscribed(user3, post2)) self.assertEqual(r.zscore(K.POST_SUBSCRIBERS.format(post2), user2), SubscriptionReasons.TAGEE) self.assertEqual(r.zscore(K.POST_SUBSCRIBERS.format(post2), user3), SubscriptionReasons.TAGEE) # Test tagging user 3 in a comment on post1. This ensures that tags # in comments do work. create_post(user2, 'user2', 'Test comment @user3', post1) self.assertTrue(is_subscribed(user3, post1)) self.assertEqual(r.zscore(K.POST_SUBSCRIBERS.format(post1), user3), SubscriptionReasons.TAGEE) # Unsubscribe user2 and user3 self.assertTrue(unsubscribe(user2, post2)) self.assertFalse(is_subscribed(user2, post2)) self.assertTrue(unsubscribe(user3, post2)) self.assertFalse(is_subscribed(user3, post2)) # Ensure that subscribe doe not happen when it is not a valid post self.assertFalse(subscribe(user1, K.NIL_VALUE, SubscriptionReasons.POSTER))
def test_feed_profile(self): """ Feed has been tested else where. This is just a formal test of this. We will post a lot of posts as 2 users so we can trigger pagination etc, etc. """ # Create 2 users and have them follow each other user1 = create_account('user1', '*****@*****.**', 'Password') user2 = create_account('user2', '*****@*****.**', 'Password') activate(user1) activate(user2) follow_user(user1, user2) follow_user(user2, user1) # Both users are now following each other. Let's create 30 posts as # each user this will trigger a couple of Pagination pages on the feeds # and also trigger a page on the profile # We need to store a list of the pids since UUIDs became available posts = [] for i in range(0, 51): posts.append(create_post(user1, 'user1', 'User 1, Post %d!' % i)) posts.append(create_post(user2, 'user1', 'User 2, Post %d!' % i)) # We now have 60 posts on each feed # Try and visit the feed when not logged in # There is no flash message to check. resp = self.client.get(url_for('users.feed')) self.assertEqual(resp.status_code, 302) # Log in as user 1 and check that they can see a couple of posts on the # first page resp = self.client.post(url_for('auth.signin'), data={ 'username': '******', 'password': '******' }, follow_redirects=True) # This sends us too / (feed) by defaults self.assertEqual(resp.status_code, 200) self.assertIn('User 1, Post 50!', resp.data) self.assertIn('User 2, Post 50!', resp.data) # Makre sure posts more than 25 ago (default pagination break) self.assertNotIn('User 1, Post 1!', resp.data) self.assertNotIn('User 2, Post 1!', resp.data) # Check the pagination button for next is there are not prev self.assertIn('<!-- pagination:older -->', resp.data) self.assertIn('<!-- pagination:oldest -->', resp.data) self.assertNotIn('<!-- pagination:newer -->', resp.data) self.assertNotIn('<!-- pagination:newerest -->', resp.data) # Let's go to page 2 in the pagination and check there are posts there resp = self.client.get(url_for('users.feed', page=2)) # Check some posts are there and are not there self.assertIn('User 1, Post 30!', resp.data) self.assertIn('User 2, Post 30!', resp.data) self.assertNotIn('User 1, Post 10!', resp.data) self.assertNotIn('User 2, Post 5!', resp.data) # Check that both pagination buttons are there self.assertIn('<!-- pagination:older -->', resp.data) self.assertIn('<!-- pagination:oldest -->', resp.data) self.assertIn('<!-- pagination:newer -->', resp.data) self.assertIn('<!-- pagination:newest -->', resp.data) # Let's go back to the first page resp = self.client.get(url_for('users.feed')) # We will delete one post and ensure that is goes missing self.assertIn('User 1, Post 50!', resp.data) # We won't check that the delete button belong to the above post # put we will check that there is at least one delete button self.assertIn('<!-- delete:post:', resp.data) # Delete the post resp = self.client.post(url_for('posts.delete_post', username='******', post_id=posts[100], next=url_for( 'users.feed')), follow_redirects=True) self.assertEqual(resp.status_code, 200) self.assertIn('User 1, Post 49!', resp.data) self.assertNotIn('User 1, Post 50!', resp.data) # Check you can not go to a profile for a non-existant user resp = self.client.get(url_for('users.profile', username='******')) self.assertEqual(resp.status_code, 404)
def test_permissions(self): """Ensure only users with the correct permissions can see posts""" user1 = create_account('user1', '*****@*****.**', 'Password') activate(user1) post1 = create_post(user1, 'user1', 'Test public', permission=0) post2 = create_post(user1, 'user1', 'Test pjuu', permission=1) post3 = create_post(user1, 'user1', 'Test approved', permission=2) resp = self.client.get(url_for('users.profile', username='******')) self.assertIn('Test public', resp.data) self.assertNotIn('Test pjuu', resp.data) self.assertNotIn('Test approved', resp.data) resp = self.client.get( url_for('posts.view_post', username='******', post_id=post1)) self.assertEqual(resp.status_code, 200) resp = self.client.get( url_for('posts.view_post', username='******', post_id=post2)) self.assertEqual(resp.status_code, 403) resp = self.client.get( url_for('posts.view_post', username='******', post_id=post3)) self.assertEqual(resp.status_code, 403) # Create a user and check we can see the Pjuu-wide post user2 = create_account('user2', '*****@*****.**', 'Password') activate(user2) self.client.post(url_for('auth.signin'), data={ 'username': '******', 'password': '******' }) resp = self.client.get(url_for('users.profile', username='******')) self.assertIn('Test public', resp.data) self.assertIn('Test pjuu', resp.data) self.assertNotIn('Test approved', resp.data) resp = self.client.get( url_for('posts.view_post', username='******', post_id=post1)) self.assertEqual(resp.status_code, 200) resp = self.client.get( url_for('posts.view_post', username='******', post_id=post2)) self.assertEqual(resp.status_code, 200) resp = self.client.get( url_for('posts.view_post', username='******', post_id=post3)) self.assertEqual(resp.status_code, 403) # Have user1 approve user2 and ensure he can see all posts # User2 needs to be following user1 follow_user(user2, user1) approve_user(user1, user2) self.assertTrue(is_approved(user1, user2)) resp = self.client.get(url_for('users.profile', username='******')) self.assertIn('Test public', resp.data) self.assertIn('Test pjuu', resp.data) self.assertIn('Test approved', resp.data) resp = self.client.get( url_for('posts.view_post', username='******', post_id=post1)) self.assertEqual(resp.status_code, 200) resp = self.client.get( url_for('posts.view_post', username='******', post_id=post2)) self.assertEqual(resp.status_code, 200) resp = self.client.get( url_for('posts.view_post', username='******', post_id=post3)) self.assertEqual(resp.status_code, 200)