def test_userflags(self): """Ensure user flags are set as expected. """ user1 = create_account('user1', '*****@*****.**', 'Password') self.assertIsNotNone(user1) # Not active by default self.assertFalse(get_user(user1).get('active')) # TTL should be set self.assertIsNotNone(get_user(user1).get('ttl')) # Activate self.assertTrue(activate(user1)) self.assertTrue(get_user(user1).get('active')) self.assertIsNone(get_user(user1).get('ttl')) # Deactivate self.assertTrue(activate(user1, False)) self.assertFalse(get_user(user1).get('active')) # Invalid self.assertFalse(activate(None)) self.assertFalse(activate(K.NIL_VALUE)) # Banning, not by default self.assertFalse(get_user(user1).get('banned')) # Ban self.assertTrue(ban(user1)) self.assertTrue(get_user(user1).get('banned')) # Un-ban self.assertTrue(ban(user1, False)) self.assertFalse(get_user(user1).get('banned')) # Invalid self.assertFalse(ban(None)) self.assertFalse(ban(K.NIL_VALUE)) # OP (Over powered or Operator?) Account should not be op self.assertFalse(get_user(user1).get('op')) # Bite self.assertTrue(bite(user1)) self.assertTrue(get_user(user1).get('op')) # Un-bite self.assertTrue(bite(user1, False)) self.assertFalse(get_user(user1).get('op')) # Invalid self.assertFalse(bite(None)) self.assertFalse(bite(K.NIL_VALUE)) # Muted, can't post, not by default self.assertFalse(get_user(user1).get('muted')) # Mute self.assertTrue(mute(user1)) self.assertTrue(get_user(user1).get('muted')) # Un-mute self.assertTrue(mute(user1, False)) self.assertFalse(get_user(user1).get('muted')) # Invalid self.assertFalse(mute(None)) self.assertFalse(mute(K.NIL_VALUE))
def test_stats(self): """Ensure the ``pjuu.auth.stats``s exposed stats are correct. """ stats = dict(get_stats()) self.assertEqual(stats.get('Total users'), 0) self.assertEqual(stats.get('Total active users'), 0) self.assertEqual(stats.get('Total banned users'), 0) self.assertEqual(stats.get('Total muted users'), 0) self.assertEqual(stats.get('Total OP users'), 0) self.assertEqual(stats.get('Newest users'), []) create_account('user1', '*****@*****.**', 'Password') user2 = create_account('user2', '*****@*****.**', 'Password') activate(user2) user3 = create_account('user3', '*****@*****.**', 'Password') activate(user3) ban(user3) user4 = create_account('user4', '*****@*****.**', 'Password') activate(user4) mute(user4) user5 = create_account('user5', '*****@*****.**', 'Password') bite(user5) # Turn in to dict for easier checking. stats = dict(get_stats()) # URL string to ensure links are being added in to newest users self.assertEqual(stats.get('Total users'), 5) self.assertEqual(stats.get('Total active users'), 3) self.assertEqual(stats.get('Total banned users'), 1) self.assertEqual(stats.get('Total muted users'), 1) self.assertEqual(stats.get('Total OP users'), 1) user_list = ['user5', 'user4', 'user3', 'user2', 'user1'] newest_users = stats.get('Newest users') for i in xrange(len(newest_users)): self.assertIn(user_list[i], newest_users[i])
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('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('post'), data={ 'body': 'Test post' }) self.assertEqual(resp.status_code, 302) # Let's create a user an login user1 = create_user('user1', '*****@*****.**', 'Password') # Activate the account self.assertTrue(activate(user1)) # Log the user in resp = self.client.post(url_for('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('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('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('post', next=url_for('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_user('user2', '*****@*****.**', 'Password') activate(user2) follow_user(user2, user1) user3 = create_user('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('post', next=url_for('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('signout')) # Log in as test2 and ensure the post is in their feed resp = self.client.post(url_for('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('signout')) # Log in as test3 and ensure the post in their feed resp = self.client.post(url_for('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('signout')) # Sign back in as user1 so that we can keep testing resp = self.client.post(url_for('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('post', next=url_for('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('post', next=url_for('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('post', next=url_for('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('post', next=url_for('feed')), data={ 'body': ('testtesttesttesttesttesttesttesttesttesttesttesttesttest' 'testtesttesttesttesttesttesttesttesttesttesttesttesttest' 'testtesttesttesttesttesttesttesttesttesttesttesttesttest' 'testtesttesttesttesttesttesttesttesttesttesttesttesttest' 'testtesttesttesttesttesttesttesttesttesttesttesttesttest' 'testtesttesttesttest') }, follow_redirects=True) self.assertIn('Posts can not be larger than 255 characters', resp.data)
def test_comment(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_user('user1', '*****@*****.**', 'Password') # Activate the account activate(user1) # Log the user in resp = self.client.post(url_for('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, '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('comment', username='******', pid=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('comment', username='******', pid=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 comment -->', resp.data) # Lets signout resp = self.client.get(url_for('signout')) self.assertEqual(resp.status_code, 302) # Lets create another test user and ensure that they can see the # comment user2 = create_user('user2', '*****@*****.**', 'password') # Activate the account activate(user2) # Log the user in resp = self.client.post(url_for('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('view_post', username='******', pid=post1)) self.assertEqual(resp.status_code, 200) self.assertIn('Test comment', resp.data) # Lets comment ourselves resp = self.client.post(url_for('comment', username='******', pid=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('comment', username='******', pid=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('comment', username='******', pid=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('comment', username='******', pid=post1), data={ 'body': ('testtesttesttesttesttesttesttesttesttesttesttesttesttest' 'testtesttesttesttesttesttesttesttesttesttesttesttesttest' 'testtesttesttesttesttesttesttesttesttesttesttesttesttest' 'testtesttesttesttesttesttesttesttesttesttesttesttesttest' 'testtesttesttesttesttesttesttesttesttesttesttesttesttest' 'testtesttesttesttest') }, follow_redirects=True) self.assertIn('Posts can not be larger than 255 characters', resp.data)
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)
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)