コード例 #1
0
    def setup(self):
        self.graph = create_object_graph(name="example", testing=True)

        self.ns = Namespace(subject="file")
        self.relation_ns = Namespace(subject=Person, object_="file")

        self.controller = FileController()

        UPLOAD_MAPPINGS = {
            Operation.Upload: EndpointDefinition(
                func=self.controller.upload,
                request_schema=FileExtraSchema(),
            ),
        }

        UPLOAD_FOR_MAPPINGS = {
            Operation.UploadFor: EndpointDefinition(
                func=self.controller.upload_for_person,
                request_schema=FileExtraSchema(),
                response_schema=FileResponseSchema(),
            ),
        }

        configure_upload(self.graph, self.ns, UPLOAD_MAPPINGS)
        configure_upload(self.graph, self.relation_ns, UPLOAD_FOR_MAPPINGS)
        configure_swagger(self.graph)

        self.client = self.graph.flask.test_client()
コード例 #2
0
def test_operation_naming_relation():
    """
    Complext (subject+object) endpoint naming works.

    """
    ns = Namespace(subject="foo", object_="bar")
    endpoint = ns.endpoint_for(Operation.SearchFor)
    assert_that(endpoint, is_(equal_to("foo.search_for.bar.v1")))
コード例 #3
0
def test_endpoint_for():
    """
    Simple (subject-only) endpoint naming works.

    """
    ns = Namespace(subject="foo")
    endpoint = ns.endpoint_for(Operation.Search)
    assert_that(endpoint, is_(equal_to("foo.search.v1")))
コード例 #4
0
def test_operation_href_for():
    """
    Operations can resolve themselves as fully expanded hrefs.

    """
    graph = create_object_graph(name="example", testing=True)
    ns = Namespace(subject="foo")

    @graph.route(ns.collection_path, Operation.Search, ns)
    def search_foo():
        pass

    with graph.app.test_request_context():
        url = ns.href_for(Operation.Search)
        assert_that(url, is_(equal_to("http://localhost/api/foo")))
コード例 #5
0
def test_operation_url_for_internal():
    """
    Operations can resolve themselves via Flask's `url_for` and get internal URIs.

    """
    graph = create_object_graph(name="example", testing=True)
    ns = Namespace(subject="foo")

    @graph.route(ns.collection_path, Operation.Search, ns)
    def search_foo():
        pass

    with graph.app.test_request_context():
        url = ns.url_for(Operation.Search, _external=False)
        assert_that(url, is_(equal_to("/api/foo")))
コード例 #6
0
def test_operation_url_for_internal():
    """
    Operations can resolve themselves via Flask's `url_for` and get internal URIs.

    """
    graph = create_object_graph(name="example", testing=True)
    ns = Namespace(subject="foo")

    @graph.route(ns.collection_path, Operation.Search, ns)
    def search_foo():
        pass

    with graph.app.test_request_context():
        url = ns.url_for(Operation.Search, _external=False)
        assert_that(url, is_(equal_to("/api/foo")))
コード例 #7
0
def test_operation_href_for():
    """
    Operations can resolve themselves as fully expanded hrefs.

    """
    graph = create_object_graph(name="example", testing=True)
    ns = Namespace(subject="foo")

    @graph.route(ns.collection_path, Operation.Search, ns)
    def search_foo():
        pass

    with graph.app.test_request_context():
        url = ns.href_for(Operation.Search)
        assert_that(url, is_(equal_to("http://localhost/api/foo")))
コード例 #8
0
class TestAlias(object):
    def setup(self):
        self.graph = create_object_graph(name="example", testing=True)

        self.ns = Namespace(subject=Person)
        configure_crud(self.graph, self.ns, PERSON_MAPPINGS)
        configure_alias(self.graph, self.ns, PERSON_MAPPINGS)

        self.client = self.graph.flask.test_client()

    def test_url_for(self):
        with self.graph.app.test_request_context():
            url = self.ns.url_for(Operation.Alias, person_name="foo")
        assert_that(url, is_(equal_to("http://localhost/api/person/foo")))

    def test_swagger_path(self):
        with self.graph.app.test_request_context():
            path = build_path(Operation.Alias, self.ns)
        assert_that(path, is_(equal_to("/api/person/{person_name}")))

    def test_alias(self):
        response = self.client.get("/api/person/foo")
        assert_that(response.status_code, is_(equal_to(302)))
        assert_that(response.headers["Location"],
                    is_(equal_to("http://localhost/api/person/1")))
コード例 #9
0
 def __init__(self, graph):
     super(TaskEventController, self).__init__(graph,
                                               graph.task_event_store)
     self.ns = Namespace(
         subject=TaskEvent,
         version="v1",
     )
コード例 #10
0
    def __init__(self, graph):
        super().__init__(graph, graph.encryptable_store)

        self.ns = Namespace(
            subject="encryptable",
            version="v1",
        )
コード例 #11
0
    def __init__(self, graph):
        super().__init__(graph, graph.customer_event_store)

        self.ns = Namespace(
            subject=CustomerEvent,
            version="v1",
        )
コード例 #12
0
    def __init__(self, graph):
        super().__init__(graph, graph.order_store)

        self.ns = Namespace(
            subject=Order,
            version="v1",
        )
コード例 #13
0
ファイル: controller.py プロジェクト: pankajghosh/peetza
    def __init__(self, graph):
        super().__init__(graph, graph.topping_store)

        self.ns = Namespace(
            subject=Topping,
            version="v1",
        )
コード例 #14
0
def test_build_integer_valued_param():
    graph = create_object_graph(name="example", testing=True)
    ns = Namespace(
        subject=Person,
        version="v1",
        identifier_type="int",
    )
    configure_crud(graph, ns, PERSON_MAPPINGS)

    with graph.flask.test_request_context():
        operations = list(iter_endpoints(graph, match_function))
        swagger_schema = build_swagger(graph, ns, operations)

        assert_that(
            build_path_for_integer_param(ns, Operation.Update,
                                         set(["person_id"])),
            equal_to("/api/v1/person/{person_id}"),
        )

    assert_that(
        swagger_schema,
        has_entries(paths=has_entries(
            **{
                "/person/{person_id}":
                has_entries(patch=has_entries(parameters=has_items({
                    "required":
                    True,
                    "type":
                    "integer",
                    "name":
                    "person_id",
                    "in":
                    "path",
                }), ), ),
            }, ), ))
コード例 #15
0
def test_discovery():
    graph = create_object_graph(name="example", testing=True)
    graph.use("discovery_convention")

    ns = Namespace("foo")

    @graph.route(ns.collection_path, Operation.Search, ns)
    def search_foo():
        pass

    client = graph.flask.test_client()

    response = client.get("/api/")
    assert_that(response.status_code, is_(equal_to(200)))
    data = loads(response.get_data().decode("utf-8"))
    assert_that(
        data,
        is_(
            equal_to({
                "_links": {
                    "search": [{
                        "href": "http://localhost/api/foo?offset=0&limit=20",
                        "type": "foo",
                    }],
                    "self": {
                        "href": "http://localhost/api/?offset=0&limit=20",
                    },
                }
            })))
コード例 #16
0
ファイル: controller.py プロジェクト: sindyjlee/rest-api
    def __init__(self, graph):
        super().__init__(graph, graph.follower_relationship_store)

        self.ns = Namespace(
            subject=FollowerRelationship,
            version="v1",
        )
コード例 #17
0
def test_operation_href_for_qs():
    """
    Operations can resolve themselves as fully expanded hrefs with
    custom query string parameter.

    """
    graph = create_object_graph(name="example", testing=True)
    ns = Namespace(subject="foo")

    @graph.route(ns.collection_path, Operation.Search, ns)
    def search_foo():
        pass

    with graph.app.test_request_context():
        url = ns.href_for(Operation.Search, offset=0, limit=10, qs=dict(foo="bar"))
        assert_that(url, matches_uri("http://localhost/api/foo?offset=0&limit=10&foo=bar"))
コード例 #18
0
    def __init__(self, graph):
        super().__init__(graph, graph.account_store)

        self.ns = Namespace(
            subject=Account,
            version="v1",
        )
コード例 #19
0
def test_operation_href_for_qs():
    """
    Operations can resolve themselves as fully expanded hrefs with
    custom query string parameter.

    """
    graph = create_object_graph(name="example", testing=True)
    ns = Namespace(subject="foo")

    @graph.route(ns.collection_path, Operation.Search, ns)
    def search_foo():
        pass

    with graph.app.test_request_context():
        url = ns.href_for(Operation.Search, offset=0, limit=10, qs=dict(foo="bar"))
        assert_that(url, matches_uri("http://localhost/api/foo?offset=0&limit=10&foo=bar"))
コード例 #20
0
ファイル: controller.py プロジェクト: ml-globality/pizza_app
    def __init__(self, graph):
        super().__init__(graph, graph.example_store)

        self.ns = Namespace(
            subject=Example,
            version="v1",
        )
コード例 #21
0
def test_custom_paginated_list():
    graph = create_object_graph(name="example", testing=True)
    ns = Namespace(subject="foo", object_="bar")

    @graph.route(ns.relation_path, Operation.SearchFor, ns)
    def search_foo():
        pass

    uid = uuid4()
    paginated_list = PaginatedList(
        ns,
        Page.from_query_string(
            dict(
                offset=2,
                limit=2,
                baz="baz",
                uid=uid,
                value=MyEnum.ONE,
            )),
        ["1", "2"],
        10,
        operation=Operation.SearchFor,
        foo_id="FOO_ID",
    )

    rest = "baz=baz&uid={}&value=ONE".format(uid)

    with graph.flask.test_request_context():
        assert_that(
            paginated_list.to_dict(),
            is_(
                equal_to({
                    "count": 10,
                    "items": [
                        "1",
                        "2",
                    ],
                    "offset": 2,
                    "limit": 2,
                    "_links": {
                        "self": {
                            "href":
                            "http://localhost/api/foo/FOO_ID/bar?offset=2&limit=2&{}"
                            .format(rest),
                        },
                        "next": {
                            "href":
                            "http://localhost/api/foo/FOO_ID/bar?offset=4&limit=2&{}"
                            .format(rest),
                        },
                        "prev": {
                            "href":
                            "http://localhost/api/foo/FOO_ID/bar?offset=0&limit=2&{}"
                            .format(rest),
                        },
                    },
                    "baz": "baz",
                    "uid": str(uid),
                    "value": "ONE",
                })))
コード例 #22
0
    def __init__(self, graph):
        super().__init__(graph, graph.pizza_store)

        self.ns = Namespace(
            subject=Pizza,
            version="v1",
        )
コード例 #23
0
ファイル: user_resources.py プロジェクト: sindyjlee/rest-api
 def get_links(self, obj):
     links = Links()
     links["self"] = Link.for_(
         Operation.Retrieve,
         Namespace(
             subject=User,
             version="v1",
         ),
         user_id=obj.id,
     )
     links["tweets"] = Link.for_(
         Operation.SearchFor,
         Namespace(
             subject=User,
             object_="tweets",
             version="v1",
         ),
         user_id=obj.id,
     )
     links["followers"] = Link.for_(
         Operation.SearchFor,
         Namespace(
             subject=User,
             object_="followers",
             version="v1",
         ),
         user_id=obj.id,
     )
     links["following"] = Link.for_(
         Operation.SearchFor,
         Namespace(
             subject=User,
             object_="following",
             version="v1",
         ),
         user_id=obj.id,
     )
     links["feed"] = Link.for_(
         Operation.SearchFor,
         Namespace(
             subject=User,
             object_="feed",
             version="v1",
         ),
         user_id=obj.id,
     )
     return links.to_dict()
コード例 #24
0
    def setup(self):
        # override configuration to use "query" operations for swagger
        def loader(metadata):
            return dict(
                swagger_convention=dict(
                    # default behavior appends this list to defaults; use a tuple to override
                    operations=["query"],
                    version="v1",
                ),
            )
        self.graph = create_object_graph(name="example", testing=True, loader=loader)
        self.graph.use("swagger_convention")
        self.ns = Namespace(subject="foo")

        make_query(self.graph, self.ns, QueryStringSchema(), QueryResultSchema())

        self.client = self.graph.flask.test_client()
コード例 #25
0
 def get_links(self, obj):
     links = Links()
     links["self"] = Link.for_(
         Operation.Retrieve,
         Namespace(subject=Address),
         address_id=obj.id,
     )
     return links.to_dict()
コード例 #26
0
ファイル: controller.py プロジェクト: sindyjlee/rest-api
    def __init__(self, graph):
        super().__init__(graph, graph.tweet_store)
        self.follower_relationship_store = graph.follower_relationship_store

        self.ns = Namespace(
            subject=Tweet,
            version="v1",
        )
コード例 #27
0
 def setup(self):
     self.graph = create_object_graph(name="example", testing=True)
     self.person_ns = Namespace(subject=Person)
     self.ns = Namespace(subject=PersonSearch)
     # ensure that link hrefs work
     configure_crud(
         self.graph, self.person_ns, {
             Operation.Retrieve:
             (person_retrieve, PersonLookupSchema(), PersonSchema()),
         })
     # enable saved search
     configure_saved_search(
         self.graph, self.ns, {
             Operation.SavedSearch:
             (person_search, OffsetLimitPageSchema(), PersonSchema()),
         })
     self.client = self.graph.flask.test_client()
コード例 #28
0
ファイル: relation.py プロジェクト: lior001/microcosm-flask
def configure_relation(graph, ns, mappings, path_prefix=""):
    """
    Register relation endpoint(s) between two resources.

    """
    ns = Namespace.make(ns, path=path_prefix)
    convention = RelationConvention(graph)
    convention.configure(ns, mappings)
コード例 #29
0
def test_parse_endpoint_relation():
    """
    Complex (subject+object) endpoints can be parsed.

    """
    operation, ns = Namespace.parse_endpoint("foo.search_for.bar.v1")
    assert_that(operation, is_(equal_to(Operation.SearchFor)))
    assert_that(ns.subject, is_(equal_to("foo")))
    assert_that(ns.object_, is_(equal_to("bar")))
コード例 #30
0
def test_parse_endpoint():
    """
    Simple (subject-only) endpoints can be parsed.

    """
    operation, ns = Namespace.parse_endpoint("foo.search.v1")
    assert_that(operation, is_(equal_to(Operation.Search)))
    assert_that(ns.subject, is_(equal_to("foo")))
    assert_that(ns.object_, is_(none()))
コード例 #31
0
def test_parse_endpoint_relation():
    """
    Complex (subject+object) endpoints can be parsed.

    """
    operation, ns = Namespace.parse_endpoint("foo.search_for.bar.v1")
    assert_that(operation, is_(equal_to(Operation.SearchFor)))
    assert_that(ns.subject, is_(equal_to("foo")))
    assert_that(ns.object_, is_(equal_to("bar")))
コード例 #32
0
    def get_links(self, obj):
        links = Links()
        links["self"] = Link.for_(
            Operation.Retrieve,
            Namespace(subject=OrderEvent, version="v1",),
            order_event_id=obj.id,
        )

        return links.to_dict()
コード例 #33
0
def test_parse_endpoint():
    """
    Simple (subject-only) endpoints can be parsed.

    """
    operation, ns = Namespace.parse_endpoint("foo.search.v1")
    assert_that(operation, is_(equal_to(Operation.Search)))
    assert_that(ns.subject, is_(equal_to("foo")))
    assert_that(ns.object_, is_(none()))
コード例 #34
0
    def setup(self):
        self.graph = create_object_graph(name="example", testing=True)

        self.ns = Namespace(subject="foo")

        configure_crud(self.graph, self.ns, FOO_MAPPINGS)
        configure_swagger(self.graph)

        self.client = self.graph.flask.test_client()
コード例 #35
0
ファイル: discovery.py プロジェクト: KensoDev/microcosm-flask
def configure_discovery(graph):
    """
    Build a singleton endpoint that provides a link to all search endpoints.

    """
    ns = Namespace(subject=graph.config.discovery_convention.name, )
    convention = DiscoveryConvention(graph)
    convention.configure(ns, discover=tuple())
    return ns.subject
コード例 #36
0
ファイル: controller.py プロジェクト: rh-glob/rob_onboarding
    def __init__(self, graph):
        super().__init__(graph, graph.pizza_store)

        self.ns = Namespace(
            subject=Pizza,
            version="v1",
        )
        self.order_event_factory = graph.order_event_factory
        self.sns_producer = graph.sns_producer
コード例 #37
0
def test_namespace_accepts_controller():
    """
    Namespaces may optionally contain a controller.

    """
    graph = create_object_graph(name="example", testing=True)
    controller = Mock()
    ns = Namespace(subject="foo", controller=controller)

    @graph.route(ns.collection_path, Operation.Search, ns)
    def search_foo():
        pass

    with graph.app.test_request_context():
        url = ns.href_for(Operation.Search)
        assert_that(url, is_(equal_to("http://localhost/api/foo")))
        url = ns.url_for(Operation.Search)
        assert_that(url, is_(equal_to("http://localhost/api/foo")))
        assert_that(ns.controller, is_(equal_to(controller)))
コード例 #38
0
def test_qualified_operation_href_for():
    """
    Qualified operations add to the URI.

    """
    graph = create_object_graph(name="example", testing=True)
    ns = Namespace(subject="foo", qualifier="bar", version="v1")

    @graph.route(ns.collection_path, Operation.Search, ns)
    def search_foo():
        pass

    @graph.route(ns.instance_path, Operation.Retrieve, ns)
    def get_foo(foo_id):
        pass

    with graph.app.test_request_context():
        url = ns.href_for(Operation.Retrieve, foo_id="baz")
        assert_that(url, is_(equal_to("http://localhost/api/v1/bar/foo/baz")))
コード例 #39
0
def test_qualified_operation_href_for():
    """
    Qualified operations add to the URI.

    """
    graph = create_object_graph(name="example", testing=True)
    ns = Namespace(subject="foo", qualifier="bar", version="v1")

    @graph.route(ns.collection_path, Operation.Search, ns)
    def search_foo():
        pass

    @graph.route(ns.instance_path, Operation.Retrieve, ns)
    def get_foo(foo_id):
        pass

    with graph.app.test_request_context():
        url = ns.href_for(Operation.Retrieve, foo_id="baz")
        assert_that(url, is_(equal_to("http://localhost/api/v1/bar/foo/baz")))
コード例 #40
0
def configure_build_info(graph):
    """
    Configure the build info endpoint.

    """
    ns = Namespace(subject=BuildInfo, )

    convention = BuildInfoConvention(graph)
    convention.configure(ns, retrieve=tuple())
    return convention.build_info
コード例 #41
0
def test_parse_endpoint_swagger():
    """
    Versioned discovery endpoint can be parsed.

    """
    operation, ns = Namespace.parse_endpoint("swagger.discover.v2")
    assert_that(operation, is_(equal_to(Operation.Discover)))
    assert_that(ns.subject, is_(equal_to("swagger")))
    assert_that(ns.version, is_(equal_to("v2")))
    assert_that(ns.object_, is_(none()))
コード例 #42
0
def test_parse_endpoint_swagger():
    """
    Versioned discovery endpoint can be parsed.

    """
    operation, ns = Namespace.parse_endpoint("swagger.discover.v2")
    assert_that(operation, is_(equal_to(Operation.Discover)))
    assert_that(ns.subject, is_(equal_to("swagger")))
    assert_that(ns.version, is_(equal_to("v2")))
    assert_that(ns.object_, is_(none()))
コード例 #43
0
    def setup(self):
        self.graph = create_object_graph(name="example", testing=True)

        self.ns = Namespace(
            subject=Person,
        )
        configure_crud(self.graph, self.ns, PERSON_MAPPINGS)
        configure_alias(self.graph, self.ns, PERSON_MAPPINGS)
        self.graph.config.swagger_convention.operations.append("alias")
        configure_swagger(self.graph)

        self.client = self.graph.flask.test_client()
コード例 #44
0
    def setup(self):
        # override configuration to use "query" operations for swagger
        def loader(metadata):
            return dict(
                swagger_convention=dict(
                    # default behavior appends this list to defaults; use a tuple to override
                    operations=["query"],
                    version="v1",
                ),
            )
        self.graph = create_object_graph(name="example", testing=True, loader=loader)
        self.graph.use("swagger_convention")
        self.ns = Namespace(subject="foo")

        make_query(self.graph, self.ns, QueryStringSchema(), QueryResultSchema())

        self.client = self.graph.flask.test_client()
コード例 #45
0
class TestAlias:

    def setup(self):
        self.graph = create_object_graph(name="example", testing=True)

        self.ns = Namespace(
            subject=Person,
        )
        configure_crud(self.graph, self.ns, PERSON_MAPPINGS)
        configure_alias(self.graph, self.ns, PERSON_MAPPINGS)
        self.graph.config.swagger_convention.operations.append("alias")
        configure_swagger(self.graph)

        self.client = self.graph.flask.test_client()

    def test_url_for(self):
        with self.graph.app.test_request_context():
            url = self.ns.url_for(Operation.Alias, person_name="foo")
        assert_that(url, is_(equal_to("http://localhost/api/person/foo")))

    def test_swagger_path(self):
        with self.graph.app.test_request_context():
            path = build_path(Operation.Alias, self.ns)
        assert_that(path, is_(equal_to("/api/person/{person_name}")))

    def test_alias(self):
        response = self.client.get("/api/person/foo")
        assert_that(response.status_code, is_(equal_to(302)))
        assert_that(response.headers["Location"], is_(equal_to("http://localhost/api/person/1")))

    def test_swagger(self):
        response = self.client.get("/api/swagger")
        assert_that(response.status_code, is_(equal_to(200)))
        data = loads(response.data)

        alias = data["paths"]["/person/{person_name}"]["get"]
        assert_that(
            alias["responses"],
            has_key("302"),
        )

        retrieve = data["paths"]["/person/{person_id}"]["get"]
        assert_that(
            retrieve["responses"],
            has_key("200"),
        )
コード例 #46
0
def iter_endpoints(graph, match_func):
    """
    Iterate through matching endpoints.

    The `match_func` is expected to have a signature of:

        def matches(operation, ns, rule):
            return True

    :returns: a generator over (`Operation`, `Namespace`, rule, func) tuples.

    """
    for rule in graph.flask.url_map.iter_rules():
        try:
            operation, ns = Namespace.parse_endpoint(rule.endpoint, get_converter(rule))
        except (IndexError, ValueError, InternalServerError):
            # operation follows a different convention (e.g. "static")
            continue
        else:
            # match_func gets access to rule to support path version filtering
            if match_func(operation, ns, rule):
                func = graph.flask.view_functions[rule.endpoint]
                yield operation, ns, rule, func
コード例 #47
0
class TestCreateCollection:

    def setup(self):
        self.graph = create_object_graph(name="example", testing=True)

        self.ns = Namespace(subject="foo")

        configure_crud(self.graph, self.ns, FOO_MAPPINGS)
        configure_swagger(self.graph)

        self.client = self.graph.flask.test_client()

    def test_create_collection_url(self):
        with self.graph.app.test_request_context():
            url = self.ns.url_for(Operation.CreateCollection)

        assert_that(url, is_(equal_to("http://localhost/api/foo")))

    def test_swagger_path(self):
        with self.graph.app.test_request_context():
            path = build_path(Operation.CreateCollection, self.ns)

        assert_that(path, is_(equal_to("/api/foo")))

    def test_swagger(self):
        response = self.client.get("/api/swagger")
        assert_that(response.status_code, is_(equal_to(200)))
        data = loads(response.data)["paths"]["/foo"]["post"]

        assert_that(
            data["parameters"],
            has_items(
                has_entry(
                    "in",
                    "body",
                ),
                has_entry(
                    "schema",
                    has_entry(
                        "$ref",
                        "#/definitions/FooRequest",
                    ),
                ),
            ),
        )
        assert_that(
            data["responses"],
            all_of(
                has_key("200"),
                is_not(has_key("204")),
                has_entry(
                    "200",
                    has_entry(
                        "schema",
                        has_entry(
                            "$ref",
                            "#/definitions/FooList",
                        ),
                    ),
                ),
            ),
        )

    def test_create_collection(self):
        text = "Some text..."
        response = self.client.post(
            "/api/foo",
            data=dumps({"text": text}),
        )

        assert_that(response.status_code, is_(equal_to(200)))
        assert_that(loads(response.data), is_(equal_to({
            "count": 1,
            "offset": 0,
            "limit": 20,
            "items": [{"text": text}],
            "_links": {
                "self": {
                    "href": "http://localhost/api/foo?offset=0&limit=20",
                },
            },
        })))
コード例 #48
0
class TestCommand:

    def setup(self):
        # override configuration to use "query" operations for swagger
        def loader(metadata):
            return dict(
                swagger_convention=dict(
                    # default behavior appends this list to defaults; use a tuple to override
                    operations=["command"],
                    version="v1",
                ),
            )

        self.graph = create_object_graph(name="example", testing=True, loader=loader)
        self.graph.use("swagger_convention")
        self.ns = Namespace(subject="foo")

        make_command(self.graph, self.ns, CommandArgumentSchema(), CommandResultSchema())

        self.client = self.graph.flask.test_client()

    def test_url_for(self):
        """
        The operation knowns how to resolve a URI for this command.

        """
        with self.graph.flask.test_request_context():
            assert_that(self.ns.url_for(Operation.Command), is_(equal_to("http://localhost/api/v1/foo/do")))

    def test_command(self):
        """
        The command can take advantage of boilerplate encoding/decoding.

        """
        uri = "/api/v1/foo/do"
        request_data = {
            "value": "bar",
        }
        response = self.client.post(uri, data=dumps(request_data))
        assert_that(response.status_code, is_(equal_to(200)))
        assert_that(loads(response.get_data().decode("utf-8")), is_(equal_to({
            "result": True,
            "value": "bar",
        })))

    def test_swagger(self):
        """
        Swagger definitions including this operation.

        """
        response = self.client.get("/api/v1/swagger")
        assert_that(response.status_code, is_(equal_to(200)))
        swagger = loads(response.get_data().decode("utf-8"))
        assert_that(swagger["paths"], is_(equal_to({
            "/foo/do": {
                "post": {
                    "tags": ["foo"],
                    "responses": {
                        "default": {
                            "description": "An error occurred", "schema": {
                                "$ref": "#/definitions/Error",
                            }
                        },
                        "200": {
                            "description": "My doc string",
                            "schema": {
                                "$ref": "#/definitions/CommandResult",
                            }
                        }
                    },
                    "parameters": [
                        {
                            "in": "header",
                            "name": "X-Response-Skip-Null",
                            "required": False,
                            "type": "string",
                        },
                        {
                            "schema": {
                                "$ref": "#/definitions/CommandArgument",
                            },
                            "name": "body",
                            "in": "body",
                        },
                    ],
                    "operationId": "command",
                }
            }
        })))
コード例 #49
0
class TestUpload:

    def setup(self):
        self.graph = create_object_graph(name="example", testing=True)

        self.ns = Namespace(subject="file")
        self.relation_ns = Namespace(subject=Person, object_="file")

        self.controller = FileController()

        UPLOAD_MAPPINGS = {
            Operation.Upload: EndpointDefinition(
                func=self.controller.upload,
                request_schema=FileExtraSchema(),
            ),
        }

        UPLOAD_FOR_MAPPINGS = {
            Operation.UploadFor: EndpointDefinition(
                func=self.controller.upload_for_person,
                request_schema=FileExtraSchema(),
                response_schema=FileResponseSchema(),
            ),
        }

        configure_upload(self.graph, self.ns, UPLOAD_MAPPINGS)
        configure_upload(self.graph, self.relation_ns, UPLOAD_FOR_MAPPINGS)
        configure_swagger(self.graph)

        self.client = self.graph.flask.test_client()

    def test_upload_url_for(self):
        with self.graph.app.test_request_context():
            url = self.ns.url_for(Operation.Upload)
        assert_that(url, is_(equal_to("http://localhost/api/file")))

    def test_upload_for_url_for(self):
        with self.graph.app.test_request_context():
            url = self.relation_ns.url_for(Operation.UploadFor, person_id=1)
        assert_that(url, is_(equal_to("http://localhost/api/person/1/file")))

    def test_upload_swagger_path(self):
        with self.graph.app.test_request_context():
            path = build_path(Operation.Upload, self.ns)
        assert_that(path, is_(equal_to("/api/file")))

    def test_upload_for_swagger_path(self):
        with self.graph.app.test_request_context():
            path = build_path(Operation.UploadFor, self.relation_ns)
        assert_that(path, is_(equal_to("/api/person/{person_id}/file")))

    def test_swagger(self):
        response = self.client.get("/api/swagger")
        assert_that(response.status_code, is_(equal_to(200)))
        data = loads(response.data)

        upload = data["paths"]["/file"]["post"]
        upload_for = data["paths"]["/person/{person_id}/file"]["post"]

        # both endpoints return form data
        assert_that(
            upload["consumes"],
            contains("multipart/form-data"),
        )
        assert_that(
            upload_for["consumes"],
            contains("multipart/form-data"),
        )

        # one endpoint gets an extra query string parameter (and the other doesn't)
        assert_that(
            upload["parameters"],
            has_item(
                has_entries(name="extra"),
            ),
        )
        assert_that(
            upload_for["parameters"],
            has_item(
                is_not(has_entries(name="extra")),
            ),
        )

        # one endpoint gets a custom response type (and the other doesn't)
        assert_that(
            upload["responses"],
            all_of(
                has_key("204"),
                is_not(has_key("200")),
                has_entry("204", is_not(has_key("schema"))),
            ),
        )
        assert_that(
            upload_for["responses"],
            all_of(
                has_key("200"),
                is_not(has_key("204")),
                has_entry("200", has_entry("schema", has_entry("$ref", "#/definitions/FileResponse"))),
            ),
        )

    def test_upload(self):
        response = self.client.post(
            "/api/file",
            data=dict(
                file=(BytesIO(b"Hello World\n"), "hello.txt"),
            ),
        )
        assert_that(response.status_code, is_(equal_to(204)))
        assert_that(self.controller.calls, contains(
            has_entries(
                files=contains(contains("file", anything(), "hello.txt")),
                extra="something",
            ),
        ))

    def test_upload_for(self):
        person_id = uuid4()
        response = self.client.post(
            "/api/person/{}/file".format(person_id),
            data=dict(
                file=(BytesIO(b"Hello World\n"), "hello.txt"),
            ),
        )
        assert_that(response.status_code, is_(equal_to(200)))
        response_data = loads(response.get_data().decode("utf-8"))
        assert_that(response_data, is_(equal_to(dict(
            id=str(person_id),
        ))))
        assert_that(self.controller.calls, contains(
            has_entries(
                files=contains(contains("file", anything(), "hello.txt")),
                extra="something",
                person_id=person_id,
            ),
        ))

    def test_upload_multipart(self):
        response = self.client.post(
            "/api/file",
            data=dict(
                file=(BytesIO(b"Hello World\n"), "hello.txt"),
                extra="special",
            ),
        )
        assert_that(response.status_code, is_(equal_to(204)))
        assert_that(self.controller.calls, contains(
            has_entries(
                files=contains(contains("file", anything(), "hello.txt")),
                extra="special",
            ),
        ))