diff options
Diffstat (limited to 'mediagoblin/tests')
-rw-r--r-- | mediagoblin/tests/.gitignore | 1 | ||||
-rw-r--r-- | mediagoblin/tests/fake_carrot_conf_good.ini | 2 | ||||
-rw-r--r-- | mediagoblin/tests/resources.py | 1 | ||||
-rw-r--r-- | mediagoblin/tests/test_api.py | 90 | ||||
-rw-r--r-- | mediagoblin/tests/test_auth.py | 50 | ||||
-rw-r--r-- | mediagoblin/tests/test_celery_setup.py | 5 | ||||
-rw-r--r-- | mediagoblin/tests/test_config.py | 4 | ||||
-rw-r--r-- | mediagoblin/tests/test_exif.py | 17 | ||||
-rw-r--r-- | mediagoblin/tests/test_exif/bad-gps.jpg | bin | 0 -> 141096 bytes | |||
-rw-r--r-- | mediagoblin/tests/test_tools.py | 57 | ||||
-rw-r--r-- | mediagoblin/tests/test_util.py | 29 | ||||
-rw-r--r-- | mediagoblin/tests/tools.py | 22 |
12 files changed, 230 insertions, 48 deletions
diff --git a/mediagoblin/tests/.gitignore b/mediagoblin/tests/.gitignore new file mode 100644 index 00000000..16d3c4db --- /dev/null +++ b/mediagoblin/tests/.gitignore @@ -0,0 +1 @@ +.cache diff --git a/mediagoblin/tests/fake_carrot_conf_good.ini b/mediagoblin/tests/fake_carrot_conf_good.ini index 1377907b..8dc32525 100644 --- a/mediagoblin/tests/fake_carrot_conf_good.ini +++ b/mediagoblin/tests/fake_carrot_conf_good.ini @@ -7,7 +7,7 @@ num_carrots = 88 encouragement_phrase = "I'd love it if you eat your carrots!" # Something extra! -blah_blah = "blah!" +blah_blah = "blæh!" [celery] EAT_CELERY_WITH_CARROTS = False diff --git a/mediagoblin/tests/resources.py b/mediagoblin/tests/resources.py index 480f6d9a..38406d62 100644 --- a/mediagoblin/tests/resources.py +++ b/mediagoblin/tests/resources.py @@ -41,3 +41,4 @@ GOOD_JPG = resource_exif('good.jpg') EMPTY_JPG = resource_exif('empty.jpg') BAD_JPG = resource_exif('bad.jpg') GPS_JPG = resource_exif('has-gps.jpg') +BAD_GPS_JPG = resource_exif('bad-gps.jpg') diff --git a/mediagoblin/tests/test_api.py b/mediagoblin/tests/test_api.py index 90873cb9..f4741fd1 100644 --- a/mediagoblin/tests/test_api.py +++ b/mediagoblin/tests/test_api.py @@ -25,11 +25,11 @@ from webtest import AppError from .resources import GOOD_JPG from mediagoblin import mg_globals -from mediagoblin.db.models import User, Activity, MediaEntry, TextComment -from mediagoblin.tools.routing import extract_url_arguments +from mediagoblin.db.models import User, MediaEntry, TextComment from mediagoblin.tests.tools import fixture_add_user from mediagoblin.moderation.tools import take_away_privileges + class TestAPI(object): """ Test mediagoblin's pump.io complient APIs """ @@ -38,7 +38,8 @@ class TestAPI(object): self.test_app = test_app self.db = mg_globals.database - self.user = fixture_add_user(privileges=[u'active', u'uploader', u'commenter']) + self.user = fixture_add_user(privileges=[u'active', u'uploader', + u'commenter']) self.other_user = fixture_add_user( username="otheruser", privileges=[u'active', u'uploader', u'commenter'] @@ -61,7 +62,7 @@ class TestAPI(object): return response, json.loads(response.body.decode()) - def _upload_image(self, test_app, image): + def _upload_image(self, test_app, image, custom_filename=None): """ Uploads and image to MediaGoblin via pump.io API """ data = open(image, "rb").read() headers = { @@ -69,6 +70,8 @@ class TestAPI(object): "Content-Length": str(len(data)) } + if custom_filename is not None: + headers["X-File-Name"] = custom_filename with self.mock_oauth(): response = test_app.post( @@ -126,9 +129,48 @@ class TestAPI(object): assert image["objectType"] == "image" # Check that we got the response we're expecting - response, _ = self._post_image_to_feed(test_app, image) + response, data = self._post_image_to_feed(test_app, image) + assert response.status_code == 200 + assert data["object"]["fullImage"]["url"].endswith("unknown.jpe") + assert data["object"]["image"]["url"].endswith("unknown.thumbnail.jpe") + + def test_can_post_image_custom_filename(self, test_app): + """ Tests an image can be posted to the API with custom filename """ + # First request we need to do is to upload the image + response, image = self._upload_image(test_app, GOOD_JPG, + custom_filename="hello.jpg") + + # I should have got certain things back + assert response.status_code == 200 + + assert "id" in image + assert "fullImage" in image + assert "url" in image["fullImage"] + assert "url" in image + assert "author" in image + assert "published" in image + assert "updated" in image + assert image["objectType"] == "image" + + # Check that we got the response we're expecting + response, data = self._post_image_to_feed(test_app, image) + assert response.status_code == 200 + assert data["object"]["fullImage"]["url"].endswith("hello.jpg") + assert data["object"]["image"]["url"].endswith("hello.thumbnail.jpg") + + def test_can_post_image_tags(self, test_app): + """ Tests that an image can be posted to the API """ + # First request we need to do is to upload the image + response, image = self._upload_image(test_app, GOOD_JPG) assert response.status_code == 200 + image["tags"] = ["hello", "world"] + + # Check that we got the response we're expecting + response, data = self._post_image_to_feed(test_app, image) + assert response.status_code == 200 + assert data["object"]["tags"] == ["hello", "world"] + def test_unable_to_upload_as_someone_else(self, test_app): """ Test that can't upload as someoen else """ data = open(GOOD_JPG, "rb").read() @@ -172,7 +214,7 @@ class TestAPI(object): assert "403 FORBIDDEN" in excinfo.value.args[0] def test_only_able_to_update_own_image(self, test_app): - """ Test's that the uploader is the only person who can update an image """ + """ Test uploader is the only person who can update an image """ response, data = self._upload_image(test_app, GOOD_JPG) response, data = self._post_image_to_feed(test_app, data) @@ -186,13 +228,16 @@ class TestAPI(object): } # Lets change the image uploader to be self.other_user, this is easier - # than uploading the image as someone else as the way self.mocked_oauth_required - # and self._upload_image. - media = MediaEntry.query.filter_by(public_id=data["object"]["id"]).first() + # than uploading the image as someone else as the way + # self.mocked_oauth_required and self._upload_image. + media = MediaEntry.query \ + .filter_by(public_id=data["object"]["id"]) \ + .first() media.actor = self.other_user.id media.save() - # Now lets try and edit the image as self.user, this should produce a 403 error. + # Now lets try and edit the image as self.user, this should produce a + # 403 error. with self.mock_oauth(): with pytest.raises(AppError) as excinfo: test_app.post( @@ -242,7 +287,6 @@ class TestAPI(object): assert image["content"] == description assert image["license"] == license - def test_only_uploaders_post_image(self, test_app): """ Test that only uploaders can upload images """ # Remove uploader permissions from user @@ -288,12 +332,15 @@ class TestAPI(object): image = json.loads(request.body.decode()) entry = MediaEntry.query.filter_by(public_id=image["id"]).first() + assert entry is not None + assert request.status_code == 200 assert "image" in image assert "fullImage" in image assert "pump_io" in image assert "links" in image + assert "tags" in image def test_post_comment(self, test_app): """ Tests that I can post an comment media """ @@ -316,7 +363,9 @@ class TestAPI(object): assert response.status_code == 200 # Find the objects in the database - media = MediaEntry.query.filter_by(public_id=data["object"]["id"]).first() + media = MediaEntry.query \ + .filter_by(public_id=data["object"]["id"]) \ + .first() comment = media.get_comments()[0].comment() # Tests that it matches in the database @@ -378,7 +427,9 @@ class TestAPI(object): response, comment_data = self._activity_to_feed(test_app, activity) # change who uploaded the comment as it's easier than changing - comment = TextComment.query.filter_by(public_id=comment_data["object"]["id"]).first() + comment = TextComment.query \ + .filter_by(public_id=comment_data["object"]["id"]) \ + .first() comment.actor = self.other_user.id comment.save() @@ -432,7 +483,7 @@ class TestAPI(object): def test_whoami_without_login(self, test_app): """ Test that whoami endpoint returns error when not logged in """ with pytest.raises(AppError) as excinfo: - response = test_app.get("/api/whoami") + test_app.get("/api/whoami") assert "401 UNAUTHORIZED" in excinfo.value.args[0] @@ -621,8 +672,11 @@ class TestAPI(object): delete = self._activity_to_feed(test_app, activity)[1] # Verify the comment no longer exists - assert TextComment.query.filter_by(public_id=comment["object"]["id"]).first() is None - comment_id = comment["object"]["id"] + assert TextComment.query \ + .filter_by(public_id=comment["object"]["id"]) \ + .first() is None + + assert "id" in comment["object"] # Check we've got a delete activity back assert "id" in delete @@ -662,6 +716,8 @@ class TestAPI(object): comment = self._activity_to_feed(test_app, activity)[1] # Verify the comment reflects the changes - model = TextComment.query.filter_by(public_id=comment["object"]["id"]).first() + model = TextComment.query \ + .filter_by(public_id=comment["object"]["id"]) \ + .first() assert model.content == activity["object"]["content"] diff --git a/mediagoblin/tests/test_auth.py b/mediagoblin/tests/test_auth.py index cb971fdb..9cf5ccb0 100644 --- a/mediagoblin/tests/test_auth.py +++ b/mediagoblin/tests/test_auth.py @@ -1,4 +1,3 @@ - # GNU MediaGoblin -- federated, autonomous media hosting # Copyright (C) 2011, 2012 MediaGoblin contributors. See AUTHORS. # @@ -102,7 +101,7 @@ def test_register_views(test_app): 'password': 'iamsohappy', 'email': 'easter@egg.com'}) - ## At this point there should on user in the database + ## At this point there should be one user in the database assert User.query.count() == 1 # Successful register @@ -373,6 +372,53 @@ def test_authentication_views(test_app): assert not form.username.data == u'ANDREW' assert form.username.data == u'andrew' + # Successful login with short user + # -------------------------------- + short_user = fixture_add_user(username=u'me', password=u'sho') + template.clear_test_template_context() + response = test_app.post( + '/auth/login/', { + 'username': u'me', + 'password': 'sho'}) + + # User should be redirected + response.follow() + + assert urlparse.urlsplit(response.location)[2] == '/' + assert 'mediagoblin/root.html' in template.TEMPLATE_TEST_CONTEXT + + # Make sure user is in the session + context = template.TEMPLATE_TEST_CONTEXT['mediagoblin/root.html'] + session = context['request'].session + assert session['user_id'] == six.text_type(short_user.id) + + # Must logout + template.clear_test_template_context() + response = test_app.get('/auth/logout/') + + # Successful login with long user + # ---------------- + long_user = fixture_add_user( + username=u'realllylonguser@reallylongdomain.com.co', password=u'sho') + template.clear_test_template_context() + response = test_app.post( + '/auth/login/', { + 'username': u'realllylonguser@reallylongdomain.com.co', + 'password': 'sho'}) + + # User should be redirected + response.follow() + assert urlparse.urlsplit(response.location)[2] == '/' + assert 'mediagoblin/root.html' in template.TEMPLATE_TEST_CONTEXT + + # Make sure user is in the session + context = template.TEMPLATE_TEST_CONTEXT['mediagoblin/root.html'] + session = context['request'].session + assert session['user_id'] == six.text_type(long_user.id) + + template.clear_test_template_context() + response = test_app.get('/auth/logout/') + @pytest.fixture() def authentication_disabled_app(request): return get_app( diff --git a/mediagoblin/tests/test_celery_setup.py b/mediagoblin/tests/test_celery_setup.py index df0d04b0..0749c7f4 100644 --- a/mediagoblin/tests/test_celery_setup.py +++ b/mediagoblin/tests/test_celery_setup.py @@ -55,7 +55,4 @@ def test_setup_celery_from_config(): 'sqlite:///' + pkg_resources.resource_filename('mediagoblin.tests', 'celery.db')) - assert fake_celery_module.BROKER_TRANSPORT == 'sqlalchemy' - assert fake_celery_module.BROKER_URL == ( - 'sqlite:///' + - pkg_resources.resource_filename('mediagoblin.tests', 'kombu.db')) + assert fake_celery_module.BROKER_URL == 'amqp://' diff --git a/mediagoblin/tests/test_config.py b/mediagoblin/tests/test_config.py index b13adae6..c3527418 100644 --- a/mediagoblin/tests/test_config.py +++ b/mediagoblin/tests/test_config.py @@ -1,3 +1,5 @@ +# -*- coding: utf-8 -*- +# # GNU MediaGoblin -- federated, autonomous media hosting # Copyright (C) 2011, 2012 MediaGoblin contributors. See AUTHORS. # @@ -47,7 +49,7 @@ def test_read_mediagoblin_config(): assert this_conf['carrotapp']['num_carrots'] == 88 assert this_conf['carrotapp']['encouragement_phrase'] == \ "I'd love it if you eat your carrots!" - assert this_conf['carrotapp']['blah_blah'] == "blah!" + assert this_conf['carrotapp']['blah_blah'] == u"blæh!" assert this_conf['celery']['EAT_CELERY_WITH_CARROTS'] == False # A bad file diff --git a/mediagoblin/tests/test_exif.py b/mediagoblin/tests/test_exif.py index d0495a7a..ad771cca 100644 --- a/mediagoblin/tests/test_exif.py +++ b/mediagoblin/tests/test_exif.py @@ -24,7 +24,7 @@ from collections import OrderedDict from mediagoblin.tools.exif import exif_fix_image_orientation, \ extract_exif, clean_exif, get_gps_data, get_useful -from .resources import GOOD_JPG, EMPTY_JPG, BAD_JPG, GPS_JPG +from .resources import GOOD_JPG, EMPTY_JPG, BAD_JPG, GPS_JPG, BAD_GPS_JPG def assert_in(a, b): @@ -437,3 +437,18 @@ def test_exif_gps_data(): 'direction': 25.674046740467404, 'altitude': 37.64365671641791, 'longitude': 18.016166666666667} + + +def test_exif_bad_gps_data(): + ''' + Test extraction of GPS data from an image with bad GPS data + ''' + result = extract_exif(BAD_GPS_JPG) + gps = get_gps_data(result) + print(gps) + + assert gps == { + 'latitude': 0.0, + 'direction': 0.0, + 'altitude': 0.0, + 'longitude': 0.0} diff --git a/mediagoblin/tests/test_exif/bad-gps.jpg b/mediagoblin/tests/test_exif/bad-gps.jpg Binary files differnew file mode 100644 index 00000000..bd6c7bf2 --- /dev/null +++ b/mediagoblin/tests/test_exif/bad-gps.jpg diff --git a/mediagoblin/tests/test_tools.py b/mediagoblin/tests/test_tools.py index 6d3dd475..5f916400 100644 --- a/mediagoblin/tests/test_tools.py +++ b/mediagoblin/tests/test_tools.py @@ -16,10 +16,16 @@ from __future__ import absolute_import, unicode_literals +try: + import mock +except ImportError: + import unittest.mock as mock + from werkzeug.wrappers import Request from werkzeug.test import EnvironBuilder from mediagoblin.tools.request import decode_request +from mediagoblin.tools.pagination import Pagination class TestDecodeRequest(object): """Test the decode_request function.""" @@ -59,3 +65,54 @@ class TestDecodeRequest(object): request.form = {'foo': 'bar'} data = decode_request(request) assert data['foo'] == 'bar' + + +class TestPagination(object): + def _create_paginator(self, num_items, page, per_page): + """Create a Paginator with a mock database cursor.""" + mock_cursor = mock.MagicMock() + mock_cursor.count.return_value = num_items + return Pagination(page, mock_cursor, per_page) + + def test_creates_valid_page_url_from_explicit_base_url(self): + """Check that test_page_url_explicit runs. + + This is a regression test for a Python 2/3 compatibility fix. + + """ + paginator = self._create_paginator(num_items=1, page=1, per_page=30) + url = paginator.get_page_url_explicit('http://example.com', [], 1) + assert url == 'http://example.com?page=1' + + def test_iter_pages_handles_single_page(self): + """Check that iter_pages produces the expected result for single page. + + This is a regression test for a Python 2/3 compatibility fix. + + """ + paginator = self._create_paginator(num_items=1, page=1, per_page=30) + assert list(paginator.iter_pages()) == [1] + + def test_zero_items(self): + """Check that no items produces no pages.""" + paginator = self._create_paginator(num_items=0, page=1, per_page=30) + assert paginator.total_count == 0 + assert paginator.pages == 0 + + def test_single_item(self): + """Check that one item produces one page.""" + paginator = self._create_paginator(num_items=1, page=1, per_page=30) + assert paginator.total_count == 1 + assert paginator.pages == 1 + + def test_full_page(self): + """Check that a full page of items produces one page.""" + paginator = self._create_paginator(num_items=30, page=1, per_page=30) + assert paginator.total_count == 30 + assert paginator.pages == 1 + + def test_multiple_pages(self): + """Check that more than a full page produces two pages.""" + paginator = self._create_paginator(num_items=31, page=1, per_page=30) + assert paginator.total_count == 31 + assert paginator.pages == 2 diff --git a/mediagoblin/tests/test_util.py b/mediagoblin/tests/test_util.py index 8193233f..02976405 100644 --- a/mediagoblin/tests/test_util.py +++ b/mediagoblin/tests/test_util.py @@ -19,6 +19,7 @@ try: except ImportError: import unittest.mock as mock import email +import socket import pytest import smtplib import pkg_resources @@ -26,6 +27,7 @@ import pkg_resources import six from mediagoblin.tests.tools import get_app +from mediagoblin import mg_globals from mediagoblin.tools import common, url, translate, mail, text, testing testing._activate_testing() @@ -181,3 +183,30 @@ def test_html_cleaner(): '<p><a href="javascript:nasty_surprise">innocent link!</a></p>') assert result == ( '<p><a href="">innocent link!</a></p>') + + +class TestMail(object): + """ Test mediagoblin's mail tool """ + def test_no_mail_server(self): + """ Tests that no smtp server is available """ + with pytest.raises(mail.NoSMTPServerError), mock.patch("smtplib.SMTP") as smtp_mock: + smtp_mock.side_effect = socket.error + mg_globals.app_config = { + "email_debug_mode": False, + "email_smtp_use_ssl": False, + "email_smtp_host": "127.0.0.1", + "email_smtp_port": 0} + common.TESTS_ENABLED = False + mail.send_email("", "", "", "") + + def test_no_smtp_host(self): + """ Empty email_smtp_host """ + with pytest.raises(mail.NoSMTPServerError), mock.patch("smtplib.SMTP") as smtp_mock: + smtp_mock.return_value.connect.side_effect = socket.error + mg_globals.app_config = { + "email_debug_mode": False, + "email_smtp_use_ssl": False, + "email_smtp_host": "", + "email_smtp_port": 0} + common.TESTS_ENABLED = False + mail.send_email("", "", "", "") diff --git a/mediagoblin/tests/tools.py b/mediagoblin/tests/tools.py index 39b9ac50..82def02c 100644 --- a/mediagoblin/tests/tools.py +++ b/mediagoblin/tests/tools.py @@ -153,28 +153,6 @@ def install_fixtures_simple(db, fixtures): collection.insert(fixture) -def assert_db_meets_expected(db, expected): - """ - Assert a database contains the things we expect it to. - - Objects are found via 'id', so you should make sure your document - has an id. - - Args: - - db: pymongo or mongokit database connection - - expected: the data we expect. Formatted like: - {'collection_name': [ - {'id': 'foo', - 'some_field': 'some_value'},]} - """ - for collection_name, collection_data in six.iteritems(expected): - collection = db[collection_name] - for expected_document in collection_data: - document = collection.query.filter_by(id=expected_document['id']).first() - assert document is not None # make sure it exists - assert document == expected_document # make sure it matches - - def fixture_add_user(username=u'chris', password=u'toast', privileges=[], wants_comment_notification=True): # Reuse existing user or create a new one |