Merge remote-tracking branch 'gsoc2016/Subtitle-1'
[mediagoblin.git] / mediagoblin / tests / test_api.py
index 10bf08fe83a828f6f0838ff322a86f404c6dd353..f4741fd102009941477406b49fdf2fcde750baf3 100644 (file)
@@ -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,8 +363,10 @@ 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()
-        comment = media.get_comments()[0]
+        media = MediaEntry.query \
+            .filter_by(public_id=data["object"]["id"]) \
+            .first()
+        comment = media.get_comments()[0].comment()
 
         # Tests that it matches in the database
         assert comment.actor == self.user.id
@@ -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,14 +483,14 @@ 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]
 
     def test_read_feed(self, test_app):
         """ Test able to read objects from the feed """
-        response, data = self._upload_image(test_app, GOOD_JPG)
-        response, data = self._post_image_to_feed(test_app, data)
+        response, image_data = self._upload_image(test_app, GOOD_JPG)
+        response, data = self._post_image_to_feed(test_app, image_data)
 
         uri = "/api/user/{0}/feed".format(self.active_user.username)
         with self.mock_oauth():
@@ -462,6 +513,48 @@ class TestAPI(object):
             assert feed["items"][0]["object"]["objectType"] == "image"
             assert feed["items"][0]["object"]["id"] == data["object"]["id"]
 
+        default_limit = 20
+        items_count = default_limit * 2
+        for i in range(items_count):
+            response, image_data = self._upload_image(test_app, GOOD_JPG)
+            self._post_image_to_feed(test_app, image_data)
+        items_count += 1  # because there already is one
+
+        #
+        # default returns default_limit items
+        #
+        with self.mock_oauth():
+            response = test_app.get(uri)
+            feed = json.loads(response.body.decode())
+            assert len(feed["items"]) == default_limit
+
+        #
+        # silentely ignore count and offset that that are
+        # not a number
+        #
+        with self.mock_oauth():
+            response = test_app.get(uri + "?count=BAD&offset=WORSE")
+            feed = json.loads(response.body.decode())
+            assert len(feed["items"]) == default_limit
+
+        #
+        # if offset is less than default_limit items
+        # from the end of the feed, return less than
+        # default_limit
+        #
+        with self.mock_oauth():
+            near_the_end = items_count - default_limit / 2
+            response = test_app.get(uri + "?offset=%d" % near_the_end)
+            feed = json.loads(response.body.decode())
+            assert len(feed["items"]) < default_limit
+
+        #
+        # count=5 returns 5 items
+        #
+        with self.mock_oauth():
+            response = test_app.get(uri + "?count=5")
+            feed = json.loads(response.body.decode())
+            assert len(feed["items"]) == 5
 
     def test_read_another_feed(self, test_app):
         """ Test able to read objects from someone else's feed """
@@ -579,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
@@ -620,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"]