Add more tests for federation APIs
authorJessica Tallon <jessica@megworld.co.uk>
Fri, 11 Jul 2014 14:23:55 +0000 (15:23 +0100)
committerJessica Tallon <jessica@megworld.co.uk>
Tue, 22 Jul 2014 22:13:16 +0000 (23:13 +0100)
mediagoblin/db/models.py
mediagoblin/federation/views.py
mediagoblin/media_types/image/__init__.py
mediagoblin/tests/test_api.py
mediagoblin/tests/tools.py

index cc5d0afa673fb87304bf4b8273dd222eb4c9f28a..27ca74e034fcd28e9b2f2813e9580fef9a886a9b 100644 (file)
@@ -446,9 +446,8 @@ class MediaEntry(Base, MediaEntryMixin):
             )
 
         context = {
-            "id": self.id, 
+            "id": self.id,
             "author": author.serialize(request),
-            "displayName": self.title,
             "objectType": self.objectType,
             "url": url,
             "image": {
@@ -464,6 +463,15 @@ class MediaEntry(Base, MediaEntryMixin):
             },
         }
 
+        if self.title:
+            context["displayName"] = self.title
+
+        if self.description:
+            context["content"] = self.description
+
+        if self.license:
+            context["license"] = self.license
+
         if show_comments:
             comments = [comment.serialize(request) for comment in self.get_comments()]
             total = len(comments)
@@ -478,7 +486,7 @@ class MediaEntry(Base, MediaEntryMixin):
                         ),
             }
 
-        return context 
+        return context
 
 class FileKeynames(Base):
     """
@@ -630,6 +638,7 @@ class MediaComment(Base, MediaCommentMixin):
         media = MediaEntry.query.filter_by(id=self.media_entry).first()
         author = self.get_author
         context = {
+            "id": self.id,
             "objectType": "comment",
             "content": self.content,
             "inReplyTo": media.serialize(request, show_comments=False),
index 6e4d81d4d951ec104f9167ae937e22a924d09210..c2b02ec00fe63125f05db0e7de98481b647a0c16 100644 (file)
@@ -116,15 +116,27 @@ def feed(request):
 
         elif obj.get("objectType", None) == "image":
             # Posting an image to the feed
-            # NB: This is currently just handing the image back until we have an
-            #     to send the image to the actual feed
-
             media_id = int(data["object"]["id"])
             media = MediaEntry.query.filter_by(id=media_id)
             if media is None:
                 error = "No such 'image' with id '{0}'".format(id=media_id)
                 return json_response(error, status=404)
-            media = media[0]
+
+            media = media.first()
+            obj = data["object"]
+
+            if "displayName" in obj:
+                media.title = obj["displayName"]
+
+            if "content" in obj:
+                media.description = obj["content"]
+
+            if "license" in obj:
+                media.license = obj["license"]
+
+            media.save()
+            manager = media.media_manager.api_add_to_feed(request, media)
+
             return json_response({
                 "verb": "post",
                 "object": media.serialize(request)
@@ -206,6 +218,11 @@ def feed(request):
             }
             return json_response(activity)
 
+    elif request.method != "GET":
+        # Currently unsupported
+        error = "Unsupported HTTP method {0}".format(request.method)
+        return json_response({"error": error}, status=501)
+
     feed_url = request.urlgen(
         "mediagoblin.federation.feed",
         username=request.user.username,
index 7b9296fe24a9d7a01607e213afab5070105fe1ae..96081068431183f5d240929f014fe51481334e8e 100644 (file)
@@ -63,10 +63,7 @@ class ImageMediaManager(MediaManagerBase):
         """ This handles a image upload request """
         # Use the same kind of method from mediagoblin/submit/views:submit_start
         entry.media_type = unicode(MEDIA_TYPE)
-        entry.title = unicode(request.args.get("title", file_data.filename))
-        entry.description = unicode(request.args.get("description", ""))
-        entry.license = request.args.get("license", "") # not part of the standard API
-
+        entry.title = file_data.filename
         entry.generate_slug()
 
         queue_file = prepare_queue_task(request.app, entry, file_data.filename)
@@ -74,6 +71,16 @@ class ImageMediaManager(MediaManagerBase):
             queue_file.write(request.data)
 
         entry.save()
+        return json_response(entry.serialize(request))
+
+    @staticmethod
+    def api_add_to_feed(request, entry):
+        """ Add media to Feed """
+        if entry.title:
+            # Shame we have to do this here but we didn't have the data in
+            # api_upload_request as no filename is usually specified.
+            entry.slug = None
+            entry.generate_slug()
 
         feed_url = request.urlgen(
             'mediagoblin.user_pages.atom_feed',
index 212223042834d8336b197eb1154a8ca09f7bcb78..38d4c0d54b801009b58c7133919e7786aad92c09 100644 (file)
@@ -23,11 +23,10 @@ from webtest import AppError
 
 from mediagoblin import mg_globals
 from .resources import GOOD_JPG
-from mediagoblin.db.models import User
+from mediagoblin.db.models import User, MediaEntry
 from mediagoblin.tests.tools import fixture_add_user
 from mediagoblin.moderation.tools import take_away_privileges
-from .resources import GOOD_JPG, GOOD_PNG, EVIL_FILE, EVIL_JPG, EVIL_PNG, \
-    BIG_BLUE
+from .resources import GOOD_JPG
 
 class TestAPI(object):
 
@@ -35,8 +34,54 @@ class TestAPI(object):
     def setup(self, test_app):
         self.test_app = test_app
         self.db = mg_globals.database
+
         self.user = fixture_add_user(privileges=[u'active', u'uploader'])
 
+    def _activity_to_feed(self, test_app, activity, headers=None):
+        """ Posts an activity to the user's feed """
+        if headers:
+            headers.setdefault("Content-Type", "application/json")
+        else:
+            headers = {"Content-Type": "application/json"}
+
+        with mock.patch("mediagoblin.decorators.oauth_required", new_callable=self.mocked_oauth_required):
+            response = test_app.post(
+                "/api/user/{0}/feed".format(self.user.username),
+                json.dumps(activity),
+                headers=headers
+            )
+
+        return response, json.loads(response.body)
+
+    def _upload_image(self, test_app, image):
+        """ Uploads and image to MediaGoblin via pump.io API """
+        data = open(image, "rb").read()
+        headers = {
+            "Content-Type": "image/jpeg",
+            "Content-Length": str(len(data))
+        }
+
+
+        with mock.patch("mediagoblin.decorators.oauth_required", new_callable=self.mocked_oauth_required):
+            response = test_app.post(
+                "/api/user/{0}/uploads".format(self.user.username),
+                data,
+                headers=headers
+            )
+            image = json.loads(response.body)
+
+        return response, image
+
+    def _post_image_to_feed(self, test_app, image):
+        """ Posts an already uploaded image to feed """
+        activity = {
+            "verb": "post",
+            "object": image,
+        }
+
+        return self._activity_to_feed(test_app, activity)
+
+
     def mocked_oauth_required(self, *args, **kwargs):
         """ Mocks mediagoblin.decorator.oauth_required to always validate """
 
@@ -52,46 +97,63 @@ class TestAPI(object):
     def test_can_post_image(self, test_app):
         """ Tests that an image can be posted to the API """
         # First request we need to do is to upload the image
-        data = open(GOOD_JPG, "rb").read()
-        headers = {
-            "Content-Type": "image/jpeg",
-            "Content-Length": str(len(data))
-        }
+        response, image = self._upload_image(test_app, GOOD_JPG)
 
+        # I should have got certain things back
+        assert response.status_code == 200
 
-        with mock.patch("mediagoblin.decorators.oauth_required", new_callable=self.mocked_oauth_required):
-            response = test_app.post(
-                "/api/user/{0}/uploads".format(self.user.username),
-                data,
-                headers=headers
-            )
-            image = json.loads(response.body)
+        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, _ = self._post_image_to_feed(test_app, image)
+        assert response.status_code == 200
 
-            # I should have got certain things back
-            assert response.status_code == 200
+    def test_upload_image_with_filename(self, test_app):
+        """ Tests that you can upload an image with filename and description """
+        response, data = self._upload_image(test_app, GOOD_JPG)
+        response, data = self._post_image_to_feed(test_app, data)
 
-            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"
-
-            # Now post this to the feed
-            activity = {
-                "verb": "post",
-                "object": image,
-            }
+        image = data["object"]
+
+        # Now we need to add a title and description
+        title = "My image ^_^"
+        description = "This is my super awesome image :D"
+        license = "CC-BY-SA"
+
+        image["displayName"] = title
+        image["content"] = description
+        image["license"] = license
+
+        activity = {"verb": "update", "object": image}
+
+        with mock.patch("mediagoblin.decorators.oauth_required", new_callable=self.mocked_oauth_required):
             response = test_app.post(
                 "/api/user/{0}/feed".format(self.user.username),
-                activity
+                json.dumps(activity),
+                headers={"Content-Type": "application/json"}
             )
 
-            # Check that we got the response we're expecting
-            assert response.status_code == 200
+        image = json.loads(response.body)["object"]
+
+        # Check everything has been set on the media correctly
+        media = MediaEntry.query.filter_by(id=image["id"]).first()
+        assert media.title == title
+        assert media.description == description
+        assert media.license == license
+
+        # Check we're being given back everything we should on an update
+        assert image["id"] == media.id
+        assert image["displayName"] == title
+        assert image["content"] == description
+        assert image["license"] == license
+
 
     def test_only_uploaders_post_image(self, test_app):
         """ Test that only uploaders can upload images """
@@ -115,3 +177,50 @@ class TestAPI(object):
 
             # Assert that we've got a 403
             assert "403 FORBIDDEN" in excinfo.value.message
+
+
+    def test_post_comment(self, test_app):
+        """ Tests that I can post an comment media """
+        # Upload some media to comment on
+        response, data = self._upload_image(test_app, GOOD_JPG)
+        response, data = self._post_image_to_feed(test_app, data)
+
+        content = "Hai this is a comment on this lovely picture ^_^"
+
+        activity = {
+            "verb": "post",
+            "object": {
+                "objectType": "comment",
+                "content": content,
+                "inReplyTo": data["object"],
+            }
+        }
+
+        response, comment_data = self._activity_to_feed(test_app, activity)
+        assert response.status_code == 200
+
+        # Find the objects in the database
+        media = MediaEntry.query.filter_by(id=data["object"]["id"]).first()
+        comment = media.get_comments()[0]
+
+        # Tests that it matches in the database
+        assert comment.author == self.user.id
+        assert comment.content == content
+
+        # Test that the response is what we should be given
+        assert comment.id == comment_data["object"]["id"]
+        assert comment.content == comment_data["object"]["content"]
+
+    def test_profile(self, test_app):
+        """ Tests profile endpoint """
+        uri = "/api/user/{0}/profile".format(self.user.username)
+        with mock.patch("mediagoblin.decorators.oauth_required", new_callable=self.mocked_oauth_required):
+            response = test_app.get(uri)
+            profile = json.loads(response.body)
+
+            assert response.status_code == 200
+
+            assert profile["preferredUsername"] == self.user.username
+            assert profile["objectType"] == "person"
+
+            assert "links" in profile
index d839373bb0423e97dbd7e0efafab77040847e5a4..57dea7b059c487bb052591668e8189abd53ab37f 100644 (file)
@@ -347,61 +347,3 @@ def fixture_add_comment_report(comment=None, reported_user=None,
 
     return comment_report
 
-def fixture_add_oauth_client(client_name=None, client_type="native",
-    redirect_uri=None, contacts=None):
-
-    client_id = random_string(22, OAUTH_ALPHABET)
-    client_secret = random_string(43, OAUTH_ALPHABET)
-
-    client = Client(
-        id=client_id,
-        secret=client_secret,
-        expirey=None,
-        application_type=client_type,
-        application_name=client_name,
-        contacts=contacts,
-        redirect_uri=redirect_uri
-    )
-    client.save()
-
-    return client
-
-def fixture_add_oauth_request_token(user, client=None):
-    if client is None:
-        client = fixture_add_oauth_client()
-
-    rt_token = random_string(22, OAUTH_ALPHABET)
-    rt_secret = random_string(43, OAUTH_ALPHABET)
-    rt_verifier = random_string(22, OAUTH_ALPHABET)
-
-    request_token = RequestToken(
-        token=rt_token,
-        secret=rt_secret,
-        user=user.id,
-        used=True,
-        authenticated=True,
-        verifier=rt_verifier,
-    )
-    request_token.save()
-
-    return request_token
-
-def fixture_add_oauth_access_token(user, client=None, request_token=None):
-    if client is None:
-        client = fixture_add_oauth_client()
-
-    if request_token is None:
-        request_token = fixture_add_oauth_request_token(user)
-
-    at_token = random_string(22, OAUTH_ALPHABET)
-    at_secret = random_string(43, OAUTH_ALPHABET)
-
-    access_token = AccessToken(
-        token=at_token,
-        secret=at_secret,
-        user=user.id,
-        request_token=request_token.token
-    )
-    access_token.save()
-
-    return access_token