Example #1
0
        def fn_create():
            """Creates a new resource and returns it."""

            if request.method == "OPTIONS":
                return

            request_doc = json.loads(request.body.getvalue())
            JsonAPIValidator.validate_create(request_doc,
                                             self.model._meta.name)

            self.listener.before_create(request)

            attributes = {}

            if "attributes" in request_doc["data"]:
                attributes = request_doc["data"]["attributes"]

            if "relationships" in request_doc["data"]:
                for k, dat in request_doc["data"]["relationships"].iteritems():
                    attributes[k] = dat["data"]["id"]

            if "id" in request_doc["data"]:
                primary = self.model._meta.primary_key.name
                attributes[primary] = request_doc["data"]["id"]

            created = self.model.create(**attributes)

            self.listener.after_create(created)

            response.set_header(
                "Location", "{}/{}".format(request.url,
                                           util.get_primary_key(created)))

            return self.__get(util.get_primary_key(created))
Example #2
0
    def testGet(self):
        result = self.app.get("/articles/1")
        self.assertEqual(result.status, "200 OK")
        self.assertIsNotNone(result.json)

        JsonAPIValidator.validate_jsonapi(result.json)

        self.assertIn("data", result.json)

        # we want a single result
        self.assertEqual(type(result.json["data"]), type({}))
        self.assertIn("attributes", result.json["data"])

        attributes = result.json["data"]["attributes"]
        self.assertEqual(attributes["title"], ARTICLE_TITLES[0])

        self.assertIn("relationships", result.json["data"])

        for key, rel in result.json["data"]["relationships"].iteritems():
            self.assertIn(key, ["comments", "cover", "author", "revisions"])
            self.assertIn("links", rel)
            self.assertIn("related", rel["links"])
            self.assertIn("self", rel["links"])

        self.assertIsInstance(
            result.json["data"]["relationships"]["comments"]["data"], list)
Example #3
0
    def testList(self):
        result = self.app.get("/articles")
        self.assertEqual(result.status, "200 OK")

        JsonAPIValidator.validate_content_type(result.content_type)
        self.assertIsNotNone(result.json)

        JsonAPIValidator.validate_jsonapi(result.json)

        self.assertIn("data", result.json)
        self.assertIs(len(result.json["data"]), len(ARTICLE_TITLES))
        for row in result.json["data"]:
            self.assertEqual(row["type"], "article")
            self.assertIn("attributes", row)

            # expected attributes: title, created
            self.assertIs(len(row["attributes"]), 2)
            self.assertIn("title", row["attributes"])
            self.assertIn("created", row["attributes"])
            self.assertNotIn("author", row["attributes"])
            self.assertIn(row["attributes"]["title"], ARTICLE_TITLES)
            self.assertIn("relationships", row)

            for key, relationship in row["relationships"].iteritems():
                self.assertIn(key,
                              ["comments", "cover", "author", "revisions"])
                self.assertIn("links", relationship)
                self.assertIn("related", relationship["links"])
                self.assertIn("self", relationship["links"])
Example #4
0
        def fn_patch_relationship(_id):
            """Patches a relationship with the given ID and returns."""

            if request.method == "OPTIONS":
                return

            request_doc = json.loads(request.body.getvalue())
            # JsonAPIValidator.validate_patch(request_doc, _id, None)

            # PATCH /res/<_id>/relationships/other_res is equal to patching the
            # main resource which is what we are doing now
            rewritten_request = {
                u"data": {
                    u"id": unicode(_id),
                    u"type": unicode(self.model._meta.name),
                    u"relationships": {
                        unicode(relationship): {
                            u"data": request_doc["data"]
                        }
                    }
                }
            }

            JsonAPIValidator.validate_patch(rewritten_request, _id,
                                            self.model._meta.name)

            return self.patch()(_id, request_doc=rewritten_request)
Example #5
0
    def testPatchingRelatedOneToNResourceShouldFail(self):
        result = self.app.get("/people/1/articles")

        self.assertIs(len(result.json["data"]), 2)
        for entry in result.json["data"]:
            self.assertIn(entry["attributes"]["title"], ARTICLE_TITLES)

        # it is not allowed to orphan an article
        request = {
            u"data": {
                u"id": u"1",
                u"type": u"person",
                u"relationships": {
                    u"articles": {
                        u"data": []
                    }
                }
            }
        }

        JsonAPIValidator.validate_jsonapi(request)

        result = self.app.patch_json("/people/1", params=request, status=400)
        JsonAPIValidator.validate_jsonapi(result.json)
        self.assertIn("orphan", result.json["errors"][0]["title"])
Example #6
0
    def testPatchingRelatedOneToNResourceShouldFail(self):
        result = self.app.get("/people/1/articles")

        self.assertIs(len(result.json["data"]), 2)
        for entry in result.json["data"]:
            self.assertIn(entry["attributes"]["title"], ARTICLE_TITLES)

        # it is not allowed to orphan an article
        request = {
            u"data": {
                u"id": u"1",
                u"type": u"person",
                u"relationships": {
                    u"articles": {
                        u"data": []
                    }
                }
            }
        }

        JsonAPIValidator.validate_jsonapi(request)

        result = self.app.patch_json("/people/1", params=request, status=400)
        JsonAPIValidator.validate_jsonapi(result.json)
        self.assertIn("orphan", result.json["errors"][0]["title"])
Example #7
0
        def fn_patch_relationship(_id):
            """Patches a relationship with the given ID and returns."""

            if request.method == "OPTIONS":
                return

            request_doc = json.loads(request.body.getvalue())
            # JsonAPIValidator.validate_patch(request_doc, _id, None)

            # PATCH /res/<_id>/relationships/other_res is equal to patching the
            # main resource which is what we are doing now
            rewritten_request = {
                u"data": {
                    u"id": unicode(_id),
                    u"type": unicode(self.model._meta.name),
                    u"relationships": {
                        unicode(relationship): {
                            u"data": request_doc["data"]
                        }
                    }
                }
            }

            JsonAPIValidator.validate_patch(
                rewritten_request, _id, self.model._meta.name
            )

            return self.patch()(_id, request_doc=rewritten_request)
Example #8
0
    def testGet(self):
        result = self.app.get("/articles/1")
        self.assertEqual(result.status, "200 OK")
        self.assertIsNotNone(result.json)

        JsonAPIValidator.validate_jsonapi(result.json)

        self.assertIn("data", result.json)

        # we want a single result
        self.assertEqual(type(result.json["data"]), type({}))
        self.assertIn("attributes", result.json["data"])

        attributes = result.json["data"]["attributes"]
        self.assertEqual(attributes["title"], ARTICLE_TITLES[0])

        self.assertIn("relationships", result.json["data"])

        for key, rel in result.json["data"]["relationships"].iteritems():
            self.assertIn(key, ["comments", "cover", "author", "revisions"])
            self.assertIn("links", rel)
            self.assertIn("related", rel["links"])
            self.assertIn("self", rel["links"])

        self.assertIsInstance(
            result.json["data"]["relationships"]["comments"]["data"],
            list
        )
Example #9
0
        def fn_patch(_id, request_doc=None):
            """Handles PATCH requests to the given resource."""

            if request.method == "OPTIONS":
                return

            request_doc = request_doc or json.loads(request.body.getvalue())
            JsonAPIValidator.validate_patch(request_doc, _id,
                                            self.model._meta.name)

            self.listener.before_patch(request_doc)

            entry = self.model.select().where(
                self.model._meta.primary_key == _id).get()

            if "attributes" in request_doc["data"]:
                # each attribute that is present will be updated
                for key, val in request_doc["data"]["attributes"].iteritems():
                    setattr(entry, key, val)

                entry.save()

            if "relationships" in request_doc["data"]:
                # patch given relationships
                self.__patch_relationships(
                    _id, request_doc["data"]["relationships"])

            if self.listener.after_patch(response):
                # if the listener changed something else then return the object
                return self.__get(_id)

            else:
                # nothing changed, we return a 204 No Content status
                response.status = 204
Example #10
0
    def testList(self):
        result = self.app.get("/articles")
        self.assertEqual(result.status, "200 OK")

        JsonAPIValidator.validate_content_type(result.content_type)
        self.assertIsNotNone(result.json)

        JsonAPIValidator.validate_jsonapi(result.json)

        self.assertIn("data", result.json)
        self.assertIs(len(result.json["data"]), len(ARTICLE_TITLES))
        for row in result.json["data"]:
            self.assertEqual(row["type"], "article")
            self.assertIn("attributes", row)

            # expected attributes: title, created
            self.assertIs(len(row["attributes"]), 2)
            self.assertIn("title", row["attributes"])
            self.assertIn("created", row["attributes"])
            self.assertNotIn("author", row["attributes"])
            self.assertIn(row["attributes"]["title"], ARTICLE_TITLES)
            self.assertIn("relationships", row)

            for key, relationship in row["relationships"].iteritems():
                self.assertIn(
                    key,
                    ["comments", "cover", "author", "revisions"]
                )
                self.assertIn("links", relationship)
                self.assertIn("related", relationship["links"])
                self.assertIn("self", relationship["links"])
Example #11
0
    def testGetNToMRelationship(self):
        result = self.app.get("/photos/1/tags")
        JsonAPIValidator.validate(result.json)

        self.assertIs(len(result.json["data"]), 2)

        for tag in result.json["data"]:
            self.assertIn(tag["attributes"]["name"], TAG_NAMES)
Example #12
0
    def testGetNToMRelationship(self):
        result = self.app.get("/photos/1/tags")
        JsonAPIValidator.validate(result.json)

        self.assertIs(len(result.json["data"]), 2)

        for tag in result.json["data"]:
            self.assertIn(tag["attributes"]["name"], TAG_NAMES)
Example #13
0
    def testFetchingRelatedOneToNResource(self):
        result = self.app.get("/articles/1/comments")
        JsonAPIValidator.validate_jsonapi(result.json)

        for entry in result.json["data"]:
            self.assertIn(entry["attributes"]["body"], COMMENT_BODIES)
            self.assertEqual(entry["relationships"]["author"]["data"]["id"],
                             "2")
            self.assertEqual(entry["relationships"]["article"]["data"]["id"],
                             "1")
Example #14
0
    def testPatchingRelatedOneToMResource(self):
        result = self.app.get("/articles/1/relationships/comments")
        self.assertIsInstance(result.json["data"], list)

        del result.json["data"][0]

        request = {u"data": result.json["data"]}

        JsonAPIValidator.validate(request)
        result = self.app.patch_json("/articles/1/relationships/comments",
                                     params=request)
Example #15
0
    def testFetchingNullRelationship(self):
        result = self.app.get("/articles/1")
        rel = result.json["data"]["relationships"]["cover"]["links"]["related"]

        result = self.app.get(rel)
        JsonAPIValidator.validate_content_type(result.content_type)

        self.assertEqual(result.status, "200 OK")
        self.assertIsNotNone(result.json)
        JsonAPIValidator.validate_jsonapi(result.json)

        self.assertIsNone(result.json["data"])
Example #16
0
    def testFetchingNullRelationship(self):
        result = self.app.get("/articles/1")
        rel = result.json["data"]["relationships"]["cover"]["links"]["related"]

        result = self.app.get(rel)
        JsonAPIValidator.validate_content_type(result.content_type)

        self.assertEqual(result.status, "200 OK")
        self.assertIsNotNone(result.json)
        JsonAPIValidator.validate_jsonapi(result.json)

        self.assertIsNone(result.json["data"])
Example #17
0
    def testFetchingRelatedOneToNResource(self):
        result = self.app.get("/articles/1/comments")
        JsonAPIValidator.validate_jsonapi(result.json)

        for entry in result.json["data"]:
            self.assertIn(entry["attributes"]["body"], COMMENT_BODIES)
            self.assertEqual(
                entry["relationships"]["author"]["data"]["id"],
                "2"
            )
            self.assertEqual(
                entry["relationships"]["article"]["data"]["id"],
                "1"
            )
Example #18
0
    def testCreatingResourceWithReferences(self):
        request = {
            u"data": {
                u"type": u"photo",
                u"attributes": {
                    u"title": u"Ember Hamster",
                    u"src": u"http://example.com/images/productivity.png"
                },
                u"relationships": {
                    u"photographer": {
                        u"data": {u"type": u"people", u"id": u"2"}
                    }
                }
            }
        }

        JsonAPIValidator.validate_jsonapi(request, True)

        result = self.app.post_json("/photos", params=request)
        JsonAPIValidator.validate_content_type(result.content_type)
        JsonAPIValidator.validate_jsonapi(result.json)

        if not result.location:
            warnings.warn(
                "The response SHOULD include a Location header identifying the"
                "location of the newly created resource."
            )

        else:
            res = self.app.get(result.location)
            self.assertIsNotNone(res.json)
            JsonAPIValidator.validate_jsonapi(res.json)
Example #19
0
    def testPatchRelationship(self):
        result = self.app.get("/articles/1")
        self.assertEqual(result.status, "200 OK")
        JsonAPIValidator.validate_content_type(result.content_type)

        self.assertIsNotNone(result.json)
        JsonAPIValidator.validate_jsonapi(result.json)

        rel = result.json["data"]["relationships"]["author"]["links"]["self"]

        request = {
            u"data": {u"type": u"person", u"id": u"2"}
        }

        JsonAPIValidator.validate_jsonapi(request)

        result = self.app.patch_json(rel, params=request)
        self.assertIn(
            result.status,
            ["200 OK", "202 Accepted", "204 No Content"]
        )

        if result.status == "204 No Content":
            self.assertIs(len(result.body), 0)
        elif result.status == "200 OK":
            self.assertIsNotNone(result.json)
            JsonAPIValidator.validate_jsonapi(result.json)
Example #20
0
    def testCreatingResourceWithReferences(self):
        request = {
            u"data": {
                u"type": u"photo",
                u"attributes": {
                    u"title": u"Ember Hamster",
                    u"src": u"http://example.com/images/productivity.png"
                },
                u"relationships": {
                    u"photographer": {
                        u"data": {
                            u"type": u"people",
                            u"id": u"2"
                        }
                    }
                }
            }
        }

        JsonAPIValidator.validate_jsonapi(request, True)

        result = self.app.post_json("/photos", params=request)
        JsonAPIValidator.validate_content_type(result.content_type)
        JsonAPIValidator.validate_jsonapi(result.json)

        if not result.location:
            warnings.warn(
                "The response SHOULD include a Location header identifying the"
                "location of the newly created resource.")

        else:
            res = self.app.get(result.location)
            self.assertIsNotNone(res.json)
            JsonAPIValidator.validate_jsonapi(res.json)
Example #21
0
    def testDeletingIndividualResource(self):
        result = self.app.get("/photos/1")
        JsonAPIValidator.validate_jsonapi(result.json)

        result = self.app.delete("/photos/1")

        if result.status_int not in [202, 204, 200]:
            warnings.warn("Delete: A server MAY respond with other HTTP status"
                          "codes. This code is unknown to the specification.")

        if result.status_int == 200:
            JsonAPIValidator.validate_jsonapi(result.json)

        # the resource should be gone now
        self.app.get("/photos/1", status=404)
Example #22
0
    def testDeletingIndividualResource(self):
        result = self.app.get("/photos/1")
        JsonAPIValidator.validate_jsonapi(result.json)

        result = self.app.delete("/photos/1")

        if result.status_int not in [202, 204, 200]:
            warnings.warn("Delete: A server MAY respond with other HTTP status"
                          "codes. This code is unknown to the specification.")

        if result.status_int == 200:
            JsonAPIValidator.validate_jsonapi(result.json)

        # the resource should be gone now
        self.app.get("/photos/1", status=404)
Example #23
0
    def testPatchingRelatedOneToMResource(self):
        result = self.app.get("/articles/1/relationships/comments")
        self.assertIsInstance(result.json["data"], list)

        del result.json["data"][0]

        request = {
            u"data": result.json["data"]
        }

        JsonAPIValidator.validate(request)
        result = self.app.patch_json(
            "/articles/1/relationships/comments",
            params=request
        )
Example #24
0
    def testUpdatingResourceRelationships(self):
        result = self.app.get("/articles/1")
        request = result.json

        # Person(1) is the current author
        self.assertEqual(
            result.json["data"]["relationships"]["author"]["data"]["id"],
            "1"
        )

        # don't update attributes, server must ignore missing attributes
        del request["data"]["attributes"]

        # do not update the 'comments' and 'cover' relationships
        del request["data"]["relationships"]["comments"]
        del request["data"]["relationships"]["cover"]
        del request["data"]["relationships"]["revisions"]

        ptype = request["data"]["relationships"]["author"]["data"]["type"]

        # change author to Person(2)
        request["data"]["relationships"]["author"] = {
            u"data": {
                u"id": u"2",
                u"type": ptype
            }
        }

        JsonAPIValidator.validate_jsonapi(request)

        result = self.app.patch_json("/articles/1", params=request)
        result = self.app.get("/articles/1")

        self.assertNotEqual(
            result.json["data"]["relationships"]["author"]["data"]["id"],
            "1"
        )

        self.assertEqual(
            result.json["data"]["relationships"]["author"]["data"]["id"],
            "2"
        )

        self.assertEqual(
            result.json["data"]["attributes"]["title"],
            ARTICLE_TITLES[0]
        )
Example #25
0
    def testCreateResourceWithAlreadyExistingId(self):
        request = {
            u"data": {
                u"type": u"person",
                u"id": u"1",
                u"attributes": {
                    u"name": "Jimmy Cricket",
                    u"age": 12
                }
            }
        }

        JsonAPIValidator.validate_jsonapi(request)

        # expect this to fail
        result = self.app.post_json("/people", params=request, status=409)
        JsonAPIValidator.validate_jsonapi(result.json)
Example #26
0
    def testIncludeParameterForwardRelationship(self):
        result = self.app.get("/articles/2?include=cover")
        JsonAPIValidator.validate(result.json)
        self.assertIn("included", result.json)

        # the server must not return any other fields than requested
        self.assertIs(len(result.json["included"]), 1)

        ref = result.json["data"]["relationships"]["cover"]["data"]
        inc = result.json["included"][0]

        self.assertEqual(inc["type"], ref["type"])
        self.assertEqual(inc["id"], ref["id"])

        # the self link must be valid and refer to the same object
        subresult = self.app.get(inc["links"]["self"])
        self.assertEqual(subresult.json["data"], inc)
Example #27
0
    def testCreateResourceWithAlreadyExistingId(self):
        request = {
            u"data": {
                u"type": u"person",
                u"id": u"1",
                u"attributes": {
                    u"name": "Jimmy Cricket",
                    u"age": 12
                }
            }
        }

        JsonAPIValidator.validate_jsonapi(request)

        # expect this to fail
        result = self.app.post_json("/people", params=request, status=409)
        JsonAPIValidator.validate_jsonapi(result.json)
Example #28
0
    def testIncludeParameterForwardRelationship(self):
        result = self.app.get("/articles/2?include=cover")
        JsonAPIValidator.validate(result.json)
        self.assertIn("included", result.json)

        # the server must not return any other fields than requested
        self.assertIs(len(result.json["included"]), 1)

        ref = result.json["data"]["relationships"]["cover"]["data"]
        inc = result.json["included"][0]

        self.assertEqual(inc["type"], ref["type"])
        self.assertEqual(inc["id"], ref["id"])

        # the self link must be valid and refer to the same object
        subresult = self.app.get(inc["links"]["self"])
        self.assertEqual(subresult.json["data"], inc)
Example #29
0
    def testIncludeParameterReverseRelationship(self):
        result = self.app.get("/articles/1?include=comments")
        JsonAPIValidator.validate(result.json)
        self.assertIn("included", result.json)

        # the server must not return any other fields than requested
        self.assertIs(len(result.json["included"]), len(COMMENT_BODIES))

        refs = result.json["data"]["relationships"]["comments"]["data"]

        for inc in result.json["included"]:
            self.assertIn({"id": inc["id"], "type": inc["type"]}, refs)

            # the self link must be valid and refer to the same object
            subresult = self.app.get(inc["links"]["self"])
            self.assertEqual(subresult.json["data"], inc)
            self.assertEqual(subresult.json["links"]["self"],
                             inc["links"]["self"])
Example #30
0
    def testSparseFieldsetsWithIncludedObjects(self):
        result = self.app.get("/articles/1?include=comments&fields[comment]=")
        JsonAPIValidator.validate(result.json)

        for inc in result.json["included"]:
            self.assertNotIn("attributes", inc)

        result = self.app.get(
            "/comments/1?include=article.author&fields[person]=age")
        JsonAPIValidator.validate(result.json)

        is_included = False
        for inc in result.json["included"]:
            if inc["type"] == "person":
                is_included = True
                self.assertIn("age", inc["attributes"])
                self.assertNotIn("name", inc["attributes"])

        self.assertIsNotNone(is_included)
Example #31
0
    def testSparseFieldsetsWithIncludedObjects(self):
        result = self.app.get("/articles/1?include=comments&fields[comment]=")
        JsonAPIValidator.validate(result.json)

        for inc in result.json["included"]:
            self.assertNotIn("attributes", inc)

        result = self.app.get(
            "/comments/1?include=article.author&fields[person]=age"
        )
        JsonAPIValidator.validate(result.json)

        is_included = False
        for inc in result.json["included"]:
            if inc["type"] == "person":
                is_included = True
                self.assertIn("age", inc["attributes"])
                self.assertNotIn("name", inc["attributes"])

        self.assertIsNotNone(is_included)
Example #32
0
    def testIncludeParameterReverseRelationship(self):
        result = self.app.get("/articles/1?include=comments")
        JsonAPIValidator.validate(result.json)
        self.assertIn("included", result.json)

        # the server must not return any other fields than requested
        self.assertIs(len(result.json["included"]), len(COMMENT_BODIES))

        refs = result.json["data"]["relationships"]["comments"]["data"]

        for inc in result.json["included"]:
            self.assertIn({"id": inc["id"], "type": inc["type"]}, refs)

            # the self link must be valid and refer to the same object
            subresult = self.app.get(inc["links"]["self"])
            self.assertEqual(subresult.json["data"], inc)
            self.assertEqual(
                subresult.json["links"]["self"],
                inc["links"]["self"]
            )
Example #33
0
    def testPatch(self):
        request = {
            u"data": {
                u"type": u"article",
                u"id": u"1",
                u"attributes": {
                    u"title": u"Changed First Entry"
                }
            }
        }

        JsonAPIValidator.validate_jsonapi(request)

        result = self.app.patch_json("/articles/1", params=request)
        self.assertIn(
            result.status,
            ["202 Accepted", "200 OK", "204 No Content"]
        )

        if result.status == "204 No Content":
            # nothing more to test
            return

        JsonAPIValidator.validate_content_type(result.content_type)

        self.assertIsNotNone(result.json)
        JsonAPIValidator.validate_jsonapi(result.json)

        self.assertEqual(
            result.json["data"]["attributes"]["title"],
            "Changed First Entry"
        )
Example #34
0
    def testPatch(self):
        request = {
            u"data": {
                u"type": u"article",
                u"id": u"1",
                u"attributes": {
                    u"title": u"Changed First Entry"
                }
            }
        }

        JsonAPIValidator.validate_jsonapi(request)

        result = self.app.patch_json("/articles/1", params=request)
        self.assertIn(result.status,
                      ["202 Accepted", "200 OK", "204 No Content"])

        if result.status == "204 No Content":
            # nothing more to test
            return

        JsonAPIValidator.validate_content_type(result.content_type)

        self.assertIsNotNone(result.json)
        JsonAPIValidator.validate_jsonapi(result.json)

        self.assertEqual(result.json["data"]["attributes"]["title"],
                         "Changed First Entry")
Example #35
0
    def testPost(self):
        request = {
            u"data": {
                u"type": u"article",
                u"attributes": {
                    u"title": u"Test entry"
                },
                u"relationships": {
                    u"author": {
                        u"data": {
                            u"id": u"1",
                            u"type": u"person"
                        }
                    }
                }
            }
        }

        JsonAPIValidator.validate_jsonapi(request, True)

        result = self.app.post_json("/articles", params=request)
        self.assertEqual(result.status, "200 OK")
        JsonAPIValidator.validate_content_type(result.content_type)

        self.assertIsNotNone(result.json)
        JsonAPIValidator.validate_jsonapi(result.json)

        self.assertIn("relationships", result.json["data"])

        for key, rel in result.json["data"]["relationships"].iteritems():
            self.assertIn(key, ["comments", "cover", "author", "revisions"])
            self.assertIn("links", rel)
            self.assertIn("related", rel["links"])
            self.assertIn("self", rel["links"])
Example #36
0
    def testPost(self):
        request = {
            u"data": {
                u"type": u"article",
                u"attributes": {
                    u"title": u"Test entry"
                },
                u"relationships": {
                    u"author": {
                        u"data": {u"id": u"1", u"type": u"person"}
                    }
                }
            }
        }

        JsonAPIValidator.validate_jsonapi(request, True)

        result = self.app.post_json("/articles", params=request)
        self.assertEqual(result.status, "200 OK")
        JsonAPIValidator.validate_content_type(result.content_type)

        self.assertIsNotNone(result.json)
        JsonAPIValidator.validate_jsonapi(result.json)

        self.assertIn("relationships", result.json["data"])

        for key, rel in result.json["data"]["relationships"].iteritems():
            self.assertIn(key, ["comments", "cover", "author", "revisions"])
            self.assertIn("links", rel)
            self.assertIn("related", rel["links"])
            self.assertIn("self", rel["links"])
Example #37
0
        def fn_patch(_id, request_doc=None):
            """Handles PATCH requests to the given resource."""

            if request.method == "OPTIONS":
                return

            request_doc = request_doc or json.loads(request.body.getvalue())
            JsonAPIValidator.validate_patch(
                request_doc,
                _id,
                self.model._meta.name
            )

            self.listener.before_patch(request_doc)

            entry = self.model.select().where(
                self.model._meta.primary_key == _id
            ).get()

            if "attributes" in request_doc["data"]:
                # each attribute that is present will be updated
                for key, val in request_doc["data"]["attributes"].iteritems():
                    setattr(entry, key, val)

                entry.save()

            if "relationships" in request_doc["data"]:
                # patch given relationships
                self.__patch_relationships(
                    _id,
                    request_doc["data"]["relationships"]
                )

            if self.listener.after_patch(response):
                # if the listener changed something else then return the object
                return self.__get(_id)

            else:
                # nothing changed, we return a 204 No Content status
                response.status = 204
Example #38
0
    def testPatchingRelatedOneToNResourceShouldSucceed(self):
        result = self.app.get("/articles/2/cover")
        self.assertIsInstance(result.json["data"], dict)

        request = {
            u"data": {
                u"id": u"2",
                u"type": u"article",
                u"relationships": {
                    u"cover": {
                        u"data": None
                    }
                }
            }
        }

        JsonAPIValidator.validate_jsonapi(request)

        result = self.app.patch_json("/articles/2", params=request)

        result = self.app.get("/articles/2/cover")
        self.assertIsNone(result.json["data"])
Example #39
0
    def testUpdatingResourceRelationships(self):
        result = self.app.get("/articles/1")
        request = result.json

        # Person(1) is the current author
        self.assertEqual(
            result.json["data"]["relationships"]["author"]["data"]["id"], "1")

        # don't update attributes, server must ignore missing attributes
        del request["data"]["attributes"]

        # do not update the 'comments' and 'cover' relationships
        del request["data"]["relationships"]["comments"]
        del request["data"]["relationships"]["cover"]
        del request["data"]["relationships"]["revisions"]

        ptype = request["data"]["relationships"]["author"]["data"]["type"]

        # change author to Person(2)
        request["data"]["relationships"]["author"] = {
            u"data": {
                u"id": u"2",
                u"type": ptype
            }
        }

        JsonAPIValidator.validate_jsonapi(request)

        result = self.app.patch_json("/articles/1", params=request)
        result = self.app.get("/articles/1")

        self.assertNotEqual(
            result.json["data"]["relationships"]["author"]["data"]["id"], "1")

        self.assertEqual(
            result.json["data"]["relationships"]["author"]["data"]["id"], "2")

        self.assertEqual(result.json["data"]["attributes"]["title"],
                         ARTICLE_TITLES[0])
Example #40
0
    def testPatchingRelatedOneToNResourceShouldSucceed(self):
        result = self.app.get("/articles/2/cover")
        self.assertIsInstance(result.json["data"], dict)

        request = {
            u"data": {
                u"id": u"2",
                u"type": u"article",
                u"relationships": {
                    u"cover": {
                        u"data": None
                    }
                }
            }
        }

        JsonAPIValidator.validate_jsonapi(request)

        result = self.app.patch_json("/articles/2", params=request)

        result = self.app.get("/articles/2/cover")
        self.assertIsNone(result.json["data"])
Example #41
0
        def fn_create():
            """Creates a new resource and returns it."""

            if request.method == "OPTIONS":
                return

            request_doc = json.loads(request.body.getvalue())
            JsonAPIValidator.validate_create(
                request_doc,
                self.model._meta.name
            )

            self.listener.before_create(request)

            attributes = {}

            if "attributes" in request_doc["data"]:
                attributes = request_doc["data"]["attributes"]

            if "relationships" in request_doc["data"]:
                for k, dat in request_doc["data"]["relationships"].iteritems():
                    attributes[k] = dat["data"]["id"]

            if "id" in request_doc["data"]:
                primary = self.model._meta.primary_key.name
                attributes[primary] = request_doc["data"]["id"]

            created = self.model.create(**attributes)

            self.listener.after_create(created)

            response.set_header("Location", "{}/{}".format(
                request.url,
                util.get_primary_key(created))
            )

            return self.__get(util.get_primary_key(created))
Example #42
0
    def testUpdatingResourceViaSelfLink(self):
        UPDATE_TITLE = u"Five Ways You Have Never Tried To Access Your Data"

        result = self.app.get("/articles/1")
        update_uri = result.json["data"]["links"]["self"]

        request = {
            u"data": {
                u"type": u"article",
                u"id": u"1",
                u"attributes": {
                    u"title": UPDATE_TITLE
                }
            }
        }

        JsonAPIValidator.validate_jsonapi(request)
        res = self.app.patch_json(update_uri, params=request)

        if "204" not in res.status:
            JsonAPIValidator.validate_content_type(res.content_type)

        res = self.app.get("/articles/1")
        self.assertEqual(res.json["data"]["attributes"]["title"], UPDATE_TITLE)
Example #43
0
    def testUpdatingResourceViaSelfLink(self):
        UPDATE_TITLE = u"Five Ways You Have Never Tried To Access Your Data"

        result = self.app.get("/articles/1")
        update_uri = result.json["data"]["links"]["self"]

        request = {
            u"data": {
                u"type": u"article",
                u"id": u"1",
                u"attributes": {
                    u"title": UPDATE_TITLE
                }
            }
        }

        JsonAPIValidator.validate_jsonapi(request)
        res = self.app.patch_json(update_uri, params=request)

        if "204" not in res.status:
            JsonAPIValidator.validate_content_type(res.content_type)

        res = self.app.get("/articles/1")
        self.assertEqual(res.json["data"]["attributes"]["title"], UPDATE_TITLE)
Example #44
0
    def testGetRelationship(self):
        result = self.app.get("/articles/1")
        self.assertEqual(result.status, "200 OK")
        JsonAPIValidator.validate_content_type(result.content_type)

        self.assertIsNotNone(result.json)
        JsonAPIValidator.validate_jsonapi(result.json)

        result = self.app.get(
            result.json["data"]["relationships"]["author"]["links"]["self"])

        self.assertEqual(result.status, "200 OK")
        JsonAPIValidator.validate_content_type(result.content_type)

        self.assertIsNotNone(result.json)
        JsonAPIValidator.validate_jsonapi(result.json)

        self.assertIn("data", result.json)
        self.assertIsInstance(result.json["data"], dict)
        self.assertEqual(result.json["data"]["type"], "person")
        self.assertEqual(result.json["data"]["id"], "1")
Example #45
0
    def testFetchingDataCollection(self):
        result = self.app.get("/articles")
        JsonAPIValidator.validate_content_type(result.content_type)

        self.assertEqual(result.status, "200 OK")
        JsonAPIValidator.validate_jsonapi(result.json)

        self.assertIs(len(result.json["data"]), 2)
        for entry in result.json["data"]:
            self.assertEqual(entry["type"], "article")
            self.assertIsInstance(entry["id"], unicode)
            self.assertIn(entry["attributes"]["title"], ARTICLE_TITLES)

        Article.delete().where(True).execute()
        result = self.app.get("/articles")
        JsonAPIValidator.validate_content_type(result.content_type)

        self.assertEqual(result.status, "200 OK")
        self.assertIsNotNone(result.json)
        JsonAPIValidator.validate_jsonapi(result.json)

        self.assertIs(len(result.json["data"]), 0)
Example #46
0
    def testFetchingDataCollection(self):
        result = self.app.get("/articles")
        JsonAPIValidator.validate_content_type(result.content_type)

        self.assertEqual(result.status, "200 OK")
        JsonAPIValidator.validate_jsonapi(result.json)

        self.assertIs(len(result.json["data"]), 2)
        for entry in result.json["data"]:
            self.assertEqual(entry["type"], "article")
            self.assertIsInstance(entry["id"], unicode)
            self.assertIn(entry["attributes"]["title"], ARTICLE_TITLES)

        Article.delete().where(True).execute()
        result = self.app.get("/articles")
        JsonAPIValidator.validate_content_type(result.content_type)

        self.assertEqual(result.status, "200 OK")
        self.assertIsNotNone(result.json)
        JsonAPIValidator.validate_jsonapi(result.json)

        self.assertIs(len(result.json["data"]), 0)
Example #47
0
    def testGetRelationship(self):
        result = self.app.get("/articles/1")
        self.assertEqual(result.status, "200 OK")
        JsonAPIValidator.validate_content_type(result.content_type)

        self.assertIsNotNone(result.json)
        JsonAPIValidator.validate_jsonapi(result.json)

        result = self.app.get(
            result.json["data"]["relationships"]["author"]["links"]["self"]
        )

        self.assertEqual(result.status, "200 OK")
        JsonAPIValidator.validate_content_type(result.content_type)

        self.assertIsNotNone(result.json)
        JsonAPIValidator.validate_jsonapi(result.json)

        self.assertIn("data", result.json)
        self.assertIsInstance(result.json["data"], dict)
        self.assertEqual(result.json["data"]["type"], "person")
        self.assertEqual(result.json["data"]["id"], "1")
Example #48
0
    def testPatchRelationship(self):
        result = self.app.get("/articles/1")
        self.assertEqual(result.status, "200 OK")
        JsonAPIValidator.validate_content_type(result.content_type)

        self.assertIsNotNone(result.json)
        JsonAPIValidator.validate_jsonapi(result.json)

        rel = result.json["data"]["relationships"]["author"]["links"]["self"]

        request = {u"data": {u"type": u"person", u"id": u"2"}}

        JsonAPIValidator.validate_jsonapi(request)

        result = self.app.patch_json(rel, params=request)
        self.assertIn(result.status,
                      ["200 OK", "202 Accepted", "204 No Content"])

        if result.status == "204 No Content":
            self.assertIs(len(result.body), 0)
        elif result.status == "200 OK":
            self.assertIsNotNone(result.json)
            JsonAPIValidator.validate_jsonapi(result.json)
Example #49
0
    def testCreatingResourceWithMissingRequiredAttributeShouldFail(self):
        request = {
            u"data": {
                u"type": u"person",
                u"attributes": {
                    u"name": u"Eve Bobbington"
                    # attribute 'age' is missing
                }
            }
        }

        JsonAPIValidator.validate_jsonapi(request, True)

        result = self.app.post_json("/people", params=request, status=400)
        JsonAPIValidator.validate_content_type(result.content_type)
        JsonAPIValidator.validate_jsonapi(result.json)
Example #50
0
    def testCreatingResourceWithMissingRequiredAttributeShouldFail(self):
        request = {
            u"data": {
                u"type": u"person",
                u"attributes": {
                    u"name": u"Eve Bobbington"
                    # attribute 'age' is missing
                }
            }
        }

        JsonAPIValidator.validate_jsonapi(request, True)

        result = self.app.post_json("/people", params=request, status=400)
        JsonAPIValidator.validate_content_type(result.content_type)
        JsonAPIValidator.validate_jsonapi(result.json)
Example #51
0
    def testListingRelatedOneToNResource(self):
        result = self.app.get("/articles/1/relationships/comments")
        JsonAPIValidator.validate_jsonapi(result.json)

        for entry in result.json["data"]:
            JsonAPIValidator.validate_resource_identifier(entry)
Example #52
0
 def testLinkWithSpecifiedField(self):
     result = self.app.get("/articles/1/relationships/revisions")
     JsonAPIValidator.validate(result.json)
Example #53
0
    def testSparseFieldsets(self):
        result = self.app.get("/people/1?fields[person]=age")
        JsonAPIValidator.validate(result.json)

        self.assertNotIn("name", result.json["data"]["attributes"])
        self.assertIn("age", result.json["data"]["attributes"])
Example #54
0
 def testFetchingMissingSingleResource(self):
     result = self.app.get("/article/1337", status=404)
     self.assertIsNotNone(result.json)
     JsonAPIValidator.validate_jsonapi(result.json)
Example #55
0
    def testListingRelatedOneToNResource(self):
        result = self.app.get("/articles/1/relationships/comments")
        JsonAPIValidator.validate_jsonapi(result.json)

        for entry in result.json["data"]:
            JsonAPIValidator.validate_resource_identifier(entry)
Example #56
0
 def testFetchingMissingSingleResource(self):
     result = self.app.get("/article/1337", status=404)
     self.assertIsNotNone(result.json)
     JsonAPIValidator.validate_jsonapi(result.json)
Example #57
0
 def testLinkWithSpecifiedField(self):
     result = self.app.get("/articles/1/relationships/revisions")
     JsonAPIValidator.validate(result.json)
Example #58
0
    def testSparseFieldsets(self):
        result = self.app.get("/people/1?fields[person]=age")
        JsonAPIValidator.validate(result.json)

        self.assertNotIn("name", result.json["data"]["attributes"])
        self.assertIn("age", result.json["data"]["attributes"])