示例#1
0
def test_supports_generic_in_unions_multiple_vars():
    A = typing.TypeVar("A")
    B = typing.TypeVar("B")

    @strawberry.type
    class Edge(typing.Generic[A, B]):
        info: A
        node: B

    @strawberry.type
    class Fallback:
        node: str

    @strawberry.type
    class Query:
        @strawberry.field
        def example(self) -> typing.Union[Fallback, Edge[int, str]]:
            return Edge(node="string", info=1)

    schema = strawberry.Schema(query=Query)

    query = """{
        example {
            __typename

            ... on IntStrEdge {
                node
                info
            }
        }
    }"""

    result = schema.execute_sync(query)

    assert not result.errors
    assert result.data == {
        "example": {
            "__typename": "IntStrEdge",
            "node": "string",
            "info": 1
        }
    }
示例#2
0
def test_supports_lists_within_unions():
    T = typing.TypeVar("T")

    @strawberry.type
    class User:
        name: str

    @strawberry.type
    class Edge(typing.Generic[T]):
        nodes: typing.List[T]

    @strawberry.type
    class Query:
        @strawberry.field
        def user(self, info) -> typing.Union[User, Edge[User]]:
            return Edge(nodes=[User("P")])

    schema = strawberry.Schema(query=Query)

    query = """{
        user {
            __typename

            ... on UserEdge {
                nodes {
                    name
                }
            }
        }
    }"""

    result = schema.execute_sync(query)

    assert not result.errors
    assert result.data == {
        "user": {
            "__typename": "UserEdge",
            "nodes": [{
                "name": "P"
            }]
        }
    }
示例#3
0
def test_field_description():
    @strawberry.type
    class Query:
        a: str = strawberry.field(description="Example")

        @strawberry.field
        def b(self, info, id: int) -> str:
            return "I'm a resolver"

        @strawberry.field(description="Example C")
        def c(self, info, id: int) -> str:
            return "I'm a resolver"

    schema = strawberry.Schema(query=Query)

    query = """{
        __type(name: "Query") {
            fields {
                name
                description
            }
        }
    }"""

    result = schema.execute_sync(query)

    assert not result.errors

    assert result.data["__type"]["fields"] == [
        {
            "name": "a",
            "description": "Example"
        },
        {
            "name": "b",
            "description": None
        },
        {
            "name": "c",
            "description": "Example C"
        },
    ]
示例#4
0
def test_raises_error_when_unable_to_find_type():
    global T, User, Edge

    T = typing.TypeVar("T")

    @strawberry.type
    class User:
        name: str

    @strawberry.type
    class Edge(typing.Generic[T]):
        nodes: typing.List[T]

    @strawberry.type
    class Query:
        @strawberry.field
        def user(self) -> typing.Union[User, Edge[User]]:
            return Edge(nodes=["bad example"])  # type: ignore

    schema = strawberry.Schema(query=Query)

    query = """{
        user {
            __typename

            ... on UserEdge {
                nodes {
                    name
                }
            }
        }
    }"""

    result = schema.execute_sync(query)

    assert result.errors[0].message == (
        "Unable to find type for <class 'tests.schema.test_generics."
        "test_raises_error_when_unable_to_find_type.<locals>.Edge'> "
        "and (<class 'str'>,)"
    )

    del T, User, Edge
示例#5
0
async def test_runs_directives():
    @strawberry.type
    class Person:
        name: str = "Jess"

    @strawberry.type
    class Query:
        @strawberry.field
        def person(self, info) -> Person:
            return Person()

    @strawberry.directive(locations=[DirectiveLocation.FIELD],
                          description="Make string uppercase")
    def uppercase(value: str):
        return value.upper()

    @strawberry.directive(locations=[DirectiveLocation.FIELD])
    def replace(value: str, old: str, new: str):
        return value.replace(old, new)

    schema = strawberry.Schema(query=Query, directives=[uppercase, replace])

    query = """query People($identified: Boolean!){
        person {
            name @uppercase
        }
        jess: person {
            name @replace(old: "Jess", new: "Jessica")
        }
        johnDoe: person {
            name @replace(old: "Jess", new: "John") @include(if: $identified)
        }
    }"""

    result = await execute(schema,
                           query,
                           variable_values={"identified": False})

    assert not result.errors
    assert result.data["person"]["name"] == "JESS"
    assert result.data["jess"]["name"] == "Jessica"
    assert result.data["johnDoe"].get("name") is None
示例#6
0
def test_generated_names():
    T = typing.TypeVar("T")

    @strawberry.type
    class EdgeWithCursor(typing.Generic[T]):
        cursor: strawberry.ID
        node: T

    @strawberry.type
    class SpecialPerson:
        name: str

    @strawberry.type
    class Query:
        @strawberry.field
        def person_edge(self) -> EdgeWithCursor[SpecialPerson]:
            return EdgeWithCursor(
                cursor=strawberry.ID("1"), node=SpecialPerson(name="Example")
            )

    schema = strawberry.Schema(query=Query)

    query = """{
        personEdge {
            __typename
            cursor
            node {
                name
            }
        }
    }"""

    result = schema.execute_sync(query)

    assert not result.errors
    assert result.data == {
        "personEdge": {
            "__typename": "SpecialPersonEdgeWithCursor",
            "cursor": "1",
            "node": {"name": "Example"},
        }
    }
示例#7
0
文件: app.py 项目: estyxx/strawberry
def create_app(**kwargs):
    @strawberry.input
    class FolderInput:
        files: typing.List[Upload]

    @strawberry.type
    class Query:
        hello: str = "strawberry"

    @strawberry.type
    class Mutation:
        @strawberry.mutation
        def read_text(self, text_file: Upload) -> str:
            return text_file.read().decode()

        @strawberry.mutation
        def read_files(self, files: typing.List[Upload]) -> typing.List[str]:
            contents = []
            for file in files:
                contents.append(file.read().decode())
            return contents

        @strawberry.mutation
        def read_folder(self, folder: FolderInput) -> typing.List[str]:
            contents = []
            for file in folder.files:
                contents.append(file.read().decode())
            return contents

    schema = strawberry.Schema(query=Query, mutation=Mutation)

    class GraphQLView(BaseGraphQLView):
        def get_root_value(self):
            return Query()

    app = Sanic(f"test_{int(random()*1000)}")

    app.add_route(
        GraphQLView.as_view(schema=schema, graphiql=kwargs.get("graphiql", True)),
        "/graphql",
    )
    return app
示例#8
0
def test_generic_with_enum_as_param_of_type_inside_unions():
    T = typing.TypeVar("T")

    @strawberry.type
    class Pet:
        name: str

    @strawberry.type
    class ErrorNode(typing.Generic[T]):
        code: T

    @strawberry.enum
    class Codes(Enum):
        a = "a"
        b = "b"

    @strawberry.type
    class Query:
        @strawberry.field
        def result(self) -> typing.Union[Pet, ErrorNode[Codes]]:
            return ErrorNode(code=Codes.a)

    schema = strawberry.Schema(query=Query)

    query = """{
        result {
            __typename
            ... on CodesErrorNode {
                code
            }
        }
    }"""

    result = schema.execute_sync(query)

    assert not result.errors
    assert result.data == {
        "result": {
            "__typename": "CodesErrorNode",
            "code": "a"
        }
    }
示例#9
0
def test_supports_generic():
    T = typing.TypeVar("T")

    @strawberry.type
    class Edge(typing.Generic[T]):
        cursor: strawberry.ID
        node: T

    @strawberry.type
    class Person:
        name: str

    @strawberry.type
    class Query:
        @strawberry.field
        def person_edge(self, info, **kwargs) -> Edge[Person]:
            return Edge(cursor=strawberry.ID("1"), node=Person(name="Example"))

    schema = strawberry.Schema(query=Query)

    query = """{
        personEdge {
            __typename
            cursor
            node {
                name
            }
        }
    }"""

    result = graphql_sync(schema, query)

    assert not result.errors
    assert result.data == {
        "personEdge": {
            "__typename": "PersonEdge",
            "cursor": "1",
            "node": {
                "name": "Example"
            },
        }
    }
示例#10
0
async def test_subscription_with_arguments():
    @strawberry.type
    class Query:
        x: str = "Hello"

    @strawberry.type
    class Subscription:
        @strawberry.subscription
        async def example(self, name: str) -> typing.AsyncGenerator[str, None]:
            yield f"Hi {name}"

    schema = strawberry.Schema(query=Query, subscription=Subscription)

    query = 'subscription { example(name: "Nina") }'

    sub = await schema.subscribe(query)
    result = await sub.__anext__()

    assert not result.errors
    assert result.data["example"] == "Hi Nina"
示例#11
0
def test_private_field_access_in_resolver():
    @strawberry.type
    class Query:
        name: str
        age: strawberry.Private[int]

        @strawberry.field
        def age_in_months(self) -> int:
            return self.age * 12

    schema = strawberry.Schema(query=Query)

    result = schema.execute_sync(
        "query { ageInMonths }", root_value=Query(name="Dave", age=7)
    )

    assert not result.errors
    assert result.data == {
        "ageInMonths": 84,
    }
示例#12
0
def test_override_unknown_scalars():
    Duration = strawberry.scalar(
        timedelta,
        name="Duration",
        serialize=timedelta.total_seconds,
        parse_value=lambda s: timedelta(seconds=s),
    )

    @strawberry.type
    class Query:
        @strawberry.field
        def duration(self, value: timedelta) -> timedelta:
            return value

    schema = strawberry.Schema(Query, scalar_overrides={timedelta: Duration})

    result = schema.execute_sync("{ duration(value: 10) }")

    assert not result.errors
    assert result.data == {"duration": 10}
示例#13
0
def test_deserialization():
    @strawberry.type
    class Query:
        deserialized = None

        @strawberry.field
        def deserialize(self, arg: datetime.date) -> bool:
            Query.deserialized = arg
            return True

    schema = strawberry.Schema(Query)

    query = """query Deserialize($value: Date!) {
        deserialize(arg: $value)
    }"""
    result = schema.execute_sync(query,
                                 variable_values={"value": "2019-10-25"})

    assert not result.errors
    assert Query.deserialized == datetime.date(2019, 10, 25)
示例#14
0
def test_errors_when_using_a_generic_without_passing_a_type():
    T = typing.TypeVar("T")

    @strawberry.type
    class Edge(typing.Generic[T]):
        cursor: strawberry.ID
        node: T

    @strawberry.type
    class Query:
        @strawberry.field
        def int_edge(self, info, **kwargs) -> Edge:
            return Edge(cursor=strawberry.ID("1"), node=1)

    with pytest.raises(TypeError) as error:
        strawberry.Schema(query=Query)

        assert str(error) == (
            f'Query fields cannot be resolved. The type "{Edge}" '
            'of the field "int_edge" is generic, but no type has been passed')
示例#15
0
async def test_subscription():
    @strawberry.type
    class Query:
        x: str = "Hello"

    @strawberry.type
    class Subscription:
        @strawberry.subscription
        async def example(self, info) -> typing.AsyncGenerator[str, None]:
            yield "Hi"

    schema = strawberry.Schema(query=Query, subscription=Subscription)

    query = "subscription { example }"

    sub = await subscribe(schema, parse(query))
    result = await sub.__anext__()

    assert not result.errors
    assert result.data["example"] == "Hi"
示例#16
0
def test_raises_graphql_error_when_permission_is_denied():
    class IsAuthenticated(BasePermission):
        message = "User is not authenticated"

        def has_permission(self, source: typing.Any, info: Info,
                           **kwargs) -> bool:
            return False

    @strawberry.type
    class Query:
        @strawberry.field(permission_classes=[IsAuthenticated])
        def user(self) -> str:
            return "patrick"

    schema = strawberry.Schema(query=Query)

    query = "{ user }"

    result = schema.execute_sync(query)
    assert result.errors[0].message == "User is not authenticated"
示例#17
0
async def test_asking_for_wrong_field():
    @strawberry.type
    class Query:
        example: Optional[str] = None

    schema = strawberry.Schema(query=Query, extensions=[DisableValidation()])

    query = """
        query {
            sample
        }
    """

    result = await schema.execute(
        query,
        root_value=Query(),
    )

    assert result.errors is None
    assert result.data == {}
示例#18
0
def test_argument_descriptions():
    @strawberry.type
    class Query:
        @strawberry.field
        def hello(  # type: ignore
            name: Annotated[
                str,
                strawberry.argument(description="Your name")  # noqa: F722
            ] = "Patrick") -> str:
            return f"Hi {name}"

    schema = strawberry.Schema(query=Query)

    assert str(schema) == dedent('''\
        type Query {
          hello(
            """Your name"""
            name: String! = "Patrick"
          ): String!
        }''')
示例#19
0
def test_using_generics_raises_when_missing_annotation():
    @strawberry.type
    class Edge(Generic[T]):
        node: T

    @strawberry.type
    class User:
        name: str

    error_message = (
        f'Query fields cannot be resolved. The type "{repr(Edge)}" '
        "is generic, but no type has been passed"
    )

    @strawberry.type
    class Query:
        user: Edge

    with pytest.raises(TypeError, match=error_message):
        strawberry.Schema(Query)
示例#20
0
def test_init_var():
    @strawberry.type
    class Category:
        name: str
        id: InitVar[str]

    @strawberry.type
    class Query:
        @strawberry.field
        def category(self, info) -> Category:
            return Category(name="example", id="123")

    schema = strawberry.Schema(query=Query)

    query = "{ category { name } }"

    result = schema.execute_sync(query)

    assert not result.errors
    assert result.data["category"]["name"] == "example"
示例#21
0
def test_bounded_instance_method_resolvers():
    class CoolClass:
        def method(self):
            _ = self
            return "something"

    instance = CoolClass()

    @strawberry.type
    class Query:
        blah: str = strawberry.field(resolver=instance.method)

    schema = strawberry.Schema(query=Query)

    query = "{ blah }"

    result = schema.execute_sync(query)

    assert not result.errors
    assert result.data == {"blah": "something"}
示例#22
0
async def test_invalid_query_with_validation_disabled():
    @strawberry.type
    class Query:
        example: Optional[str] = None

    schema = strawberry.Schema(query=Query)

    query = """
        query {
            example
    """

    result = await schema.execute(query, root_value=Query())

    assert str(
        result.errors[0]) == ("Syntax Error: Expected Name, found <EOF>.\n\n"
                              "GraphQL request:4:5\n"
                              "3 |             example\n"
                              "4 |     \n"
                              "  |     ^")
async def test_errors_when_running_async_in_sync_mode():
    @strawberry.type
    class Query:
        @strawberry.field
        async def name(self) -> str:
            return "Patrick"

    schema = strawberry.Schema(query=Query)

    query = """
        query {
            name
        }
    """

    with pytest.raises(RuntimeError) as e:
        schema.execute_sync(query)

    assert e.value.args[
        0] == "GraphQL execution failed to complete synchronously."
示例#24
0
def test_duplicate_scalars():
    MyCustomScalar = strawberry.scalar(
        str,
        name="MyCustomScalar",
    )

    MyCustomScalar2 = strawberry.scalar(
        int,
        name="MyCustomScalar",
    )

    @strawberry.type
    class Query:
        scalar_1: MyCustomScalar
        scalar_2: MyCustomScalar2

    with pytest.raises(
            TypeError,
            match="Scalar `MyCustomScalar` has already been registered"):
        strawberry.Schema(Query)
示例#25
0
def test_supports_generic_in_unions():
    T = typing.TypeVar("T")

    @strawberry.type
    class Edge(typing.Generic[T]):
        cursor: strawberry.ID
        node: T

    @strawberry.type
    class Fallback:
        node: str

    @strawberry.type
    class Query:
        @strawberry.field
        def example(self) -> typing.Union[Fallback, Edge[int]]:
            return Edge(cursor=strawberry.ID("1"), node=1)

    schema = strawberry.Schema(query=Query)

    query = """{
        example {
            __typename

            ... on IntEdge {
                cursor
                node
            }
        }
    }"""

    result = schema.execute_sync(query)

    assert not result.errors
    assert result.data == {
        "example": {
            "__typename": "IntEdge",
            "cursor": "1",
            "node": 1
        }
    }
示例#26
0
def test_named_union():
    global Result

    @strawberry.type
    class A:
        a: int

    @strawberry.type
    class B:
        b: int

    Result = strawberry.union("Result", (A, B))

    @strawberry.type
    class Query:
        ab: Result = A(a=5)

    schema = strawberry.Schema(query=Query)

    query = """{
        __type(name: "Result") {
            kind
            description
        }

        ab {
            __typename,

            ... on A {
                a
            }
        }
    }"""

    result = schema.execute_sync(query, root_value=Query())

    assert not result.errors
    assert result.data["ab"] == {"__typename": "A", "a": 5}
    assert result.data["__type"] == {"kind": "UNION", "description": None}

    del Result
示例#27
0
def test_union_as_mutation_return():
    global A, B

    @strawberry.type
    class A:
        x: int

    @strawberry.type
    class B:
        y: int

    @strawberry.type
    class Mutation:
        @strawberry.mutation
        def hello(self) -> Union[A, B]:
            return B(y=5)

    schema = strawberry.Schema(query=A, mutation=Mutation)

    query = """
    mutation {
        hello {
            __typename

            ... on A {
                x
            }

            ... on B {
                y
            }
        }
    }
    """

    result = schema.execute_sync(query)

    assert not result.errors
    assert result.data["hello"] == {"__typename": "B", "y": 5}

    del A, B
示例#28
0
def test_field_deprecated_reason():
    @strawberry.type
    class Query:
        a: str = strawberry.field(deprecation_reason="Deprecated A")

        @strawberry.field
        def b(self, id: int) -> str:
            return "I'm a resolver"

        @strawberry.field(deprecation_reason="Deprecated B")
        def c(self, id: int) -> str:
            return "I'm a resolver"

    schema = strawberry.Schema(query=Query)

    query = """{
        __type(name: "Query") {
            fields(includeDeprecated: true) {
                name
                deprecationReason
            }
        }
    }"""

    result = schema.execute_sync(query)

    assert not result.errors
    assert result.data["__type"]["fields"] == [
        {
            "name": "a",
            "deprecationReason": "Deprecated A"
        },
        {
            "name": "b",
            "deprecationReason": None
        },
        {
            "name": "c",
            "deprecationReason": "Deprecated B"
        },
    ]
示例#29
0
def test_optional_input_field_unset():
    @strawberry.input
    class TestInput:
        name: Optional[str] = UNSET
        age: Optional[int] = UNSET

    @strawberry.type
    class Query:
        @strawberry.field
        def hello(self, input: TestInput) -> str:
            if is_unset(input.name):
                return "Hi there"
            return f"Hi {input.name}"

    schema = strawberry.Schema(query=Query)

    assert (
        str(schema)
        == dedent(
            """
        type Query {
          hello(input: TestInput!): String!
        }

        input TestInput {
          name: String
          age: Int
        }
        """
        ).strip()
    )

    result = schema.execute_sync(
        """
        query {
            hello(input: {})
        }
    """
    )
    assert not result.errors
    assert result.data == {"hello": "Hi there"}
示例#30
0
def test_execution_context_operation_name_and_type():
    operation_name = None
    operation_type = None

    class MyExtension(Extension):
        def on_request_end(self):
            nonlocal operation_name
            nonlocal operation_type

            execution_context = self.execution_context

            operation_name = execution_context.operation_name
            operation_type = execution_context.operation_type

    schema = strawberry.Schema(Query, extensions=[MyExtension])

    result = schema.execute_sync("{ ping }")
    assert not result.errors

    assert operation_name is None
    assert operation_type == "QUERY"

    # Try again with an operation_name
    result = schema.execute_sync("query MyOperation { ping }")
    assert not result.errors

    assert operation_name == "MyOperation"
    assert operation_type == "QUERY"

    # Try again with an operation_name override
    result = schema.execute_sync(
        """
        query MyOperation { ping }
        query MyOperation2 { ping }
        """,
        operation_name="MyOperation2",
    )
    assert not result.errors

    assert operation_name == "MyOperation2"
    assert operation_type == "QUERY"