Add experimental mutation decorator

This commit is contained in:
Jonathan Kim 2020-06-27 12:58:16 +01:00
parent 0a5c8c1268
commit 48f249af3b
5 changed files with 185 additions and 0 deletions

View File

View File

@ -0,0 +1,23 @@
from graphene.types.field import Field
from graphene.utils.str_converters import to_camel_case
def mutation(return_type, arguments=None, **kwargs):
# TODO: validate input arguments
if arguments is None:
arguments = {}
def decorate(resolver_function):
name = kwargs.pop("name", None) or resolver_function.__name__
description = kwargs.pop("description", None) or resolver_function.__doc__
return Field(
return_type,
args=arguments,
name=to_camel_case(name),
resolver=resolver_function,
description=description,
**kwargs
)
return decorate

View File

@ -0,0 +1,162 @@
from textwrap import dedent
from graphene import String, ObjectType, Schema, Union, Field
from ..mutation import mutation
def test_mutation_basic():
@mutation(String, required=True)
def my_mutation(root, info):
return "hi"
class Query(ObjectType):
a = String()
schema = Schema(query=Query, mutations=[my_mutation])
result = schema.execute(
"""
mutation MyMutation {
myMutation
}
"""
)
assert not result.errors
assert result.data == {"myMutation": "hi"}
def test_mutation_arguments():
@mutation(String, required=True, arguments={"name": String(required=True)})
def my_mutation(root, info, name):
return f"hi {name}"
class Query(ObjectType):
a = String()
schema = Schema(query=Query, mutations=[my_mutation])
result = schema.execute(
"""
mutation MyMutation {
myMutation(name: "world")
}
"""
)
assert not result.errors
assert result.data == {"myMutation": "hi world"}
def test_mutation_field_options():
@mutation(
String,
required=True,
arguments={"name": String(required=True)},
name="other_mutation",
deprecation_reason="Don't use this mutation",
description="Some description",
)
def my_mutation(root, info, name):
return f"hi {name}"
class Query(ObjectType):
a = String()
schema = Schema(query=Query, mutations=[my_mutation])
result = schema.execute(
"""
mutation MyMutation {
otherMutation(name: "world")
}
"""
)
assert not result.errors
assert result.data == {"otherMutation": "hi world"}
assert str(schema) == dedent(
"""\
type Query {
a: String
}
type Mutation {
\"\"\"Some description\"\"\"
otherMutation(name: String!): String! @deprecated(reason: \"Don't use this mutation\")
}
"""
)
def test_mutation_complex_return():
class User(ObjectType):
name = String(required=True)
class CreateUserSuccess(ObjectType):
user = Field(User, required=True)
class CreateUserError(ObjectType):
error_message = String(required=True)
class CreateUserOutput(Union):
class Meta:
types = [
CreateUserSuccess,
CreateUserError,
]
@mutation(
CreateUserOutput, required=True, arguments={"name": String(required=True)}
)
def create_user(root, info, name):
return CreateUserSuccess(user=User(name=name))
class Query(ObjectType):
a = String()
schema = Schema(query=Query, mutations=[create_user])
result = schema.execute(
"""
mutation CreateUserMutation {
createUser(name: "Kate") {
__typename
... on CreateUserSuccess {
user {
name
}
}
}
}
"""
)
assert not result.errors
assert result.data == {
"createUser": {"__typename": "CreateUserSuccess", "user": {"name": "Kate"}}
}
assert str(schema) == dedent(
"""\
type Query {
a: String
}
type Mutation {
createUser(name: String!): CreateUserOutput!
}
union CreateUserOutput = CreateUserSuccess | CreateUserError
type CreateUserSuccess {
user: User!
}
type User {
name: String!
}
type CreateUserError {
errorMessage: String!
}
"""
)