def test_unions(): Foo = ObjectType("Foo", [Field("str", String)]) Bar = ObjectType("Bar", [Field("int", Int)]) SingleUnion = UnionType("SingleUnion", types=[Foo]) MultiUnion = UnionType("MultiUnion", types=[Foo, Bar]) Query = ObjectType( "Query", [Field("single", SingleUnion), Field("multi", MultiUnion)]) assert print_schema(Schema(Query), indent=" ") == dedent(""" type Bar { int: Int } type Foo { str: String } union MultiUnion = Foo | Bar type Query { single: SingleUnion multi: MultiUnion } union SingleUnion = Foo """)
def test_Schema_includes_nested_input_objects_in_the_map(): NestedInputObject = InputObjectType("NestedInputObject", [InputField("value", String)]) SomeInputObject = InputObjectType( "SomeInputObject", [InputField("nested", NestedInputObject)]) SomeMutation = ObjectType( "SomeMutation", [ Field( "mutateSomething", BlogArticle, [Argument("input", SomeInputObject)], ) ], ) SomeSubscription = ObjectType( "SomeSubscription", [ Field( "subscribeToSomething", BlogArticle, [Argument("input", SomeInputObject)], ) ], ) schema = Schema( BlogQuery, mutation_type=SomeMutation, subscription_type=SomeSubscription, ) assert schema.types.get("NestedInputObject") is NestedInputObject
def test_Schema_refuses_duplicate_type_names(): type_1 = ObjectType("Object", [Field("f", String)]) type_2 = ObjectType("Object", [Field("f", String)]) with pytest.raises(SchemaError) as exc_info: Schema(ObjectType("Query", [Field("f1", type_1), Field("f2", type_2)])) assert str(exc_info.value) == 'Duplicate type "Object"'
def test_register_resolver_raises_on_unknown_field(): Object = ObjectType("Object", [Field("id", String)]) schema = Schema(ObjectType("Query", [Field("foo", Object)])) resolver = lambda *_, **__: None with pytest.raises(SchemaError): schema.register_resolver("Object", "foo", resolver)
def test_register_subscription_raises_on_missing_field(): Query = ObjectType("Query", [Field("id", String)]) Subscription = ObjectType("Subscription", [Field("values", Int)]) schema = Schema(Query, subscription_type=Subscription) with pytest.raises(SchemaError): schema.register_subscription("Subscription", "value", lambda *_: 42)
def test_interfaces(): Foo = InterfaceType("Foo", [Field("str", String)]) Baz = InterfaceType("Baz", [Field("int", Int)]) Bar = ObjectType( "Bar", [Field("str", String), Field("int", Int)], interfaces=[Foo, Baz]) Query = ObjectType("Query", [Field("bar", Bar)]) assert print_schema(Schema(Query), indent=" ") == dedent(""" type Bar implements Foo & Baz { str: String int: Int } interface Baz { int: Int } interface Foo { str: String } type Query { bar: Bar } """)
def test_register_resolver_raises_on_override_by_default(): resolver = lambda *_, **__: None Object = ObjectType("Object", [Field("id", String, resolver=resolver)]) schema = Schema(ObjectType("Query", [Field("foo", Object)])) new_resolver = lambda *_, **__: None with pytest.raises(ValueError): schema.register_resolver("Object", "id", new_resolver)
def test_register_subscription_works(): Query = ObjectType("Query", [Field("id", String)]) Subscription = ObjectType("Subscription", [Field("values", Int)]) schema = Schema(Query, subscription_type=Subscription) schema.register_subscription("Subscription", "values", lambda *_: 42) assert (schema.subscription_type.field_map[ # type: ignore "values"].subscription_resolver() == 42)
async def test_type_resolution_supports_object_attribute(assert_execution): PetType = InterfaceType("Pet", [Field("name", String)]) DogType = ObjectType( "Dog", [Field("name", String), Field("woofs", Boolean)], interfaces=[PetType], ) CatType = ObjectType( "Cat", [Field("name", String), Field("meows", Boolean)], interfaces=[PetType], ) class Dog: __typename__ = "Dog" def __init__(self, name, woofs): self.name = name self.woofs = woofs class Cat: __typename__ = "Cat" def __init__(self, name, meows): self.name = name self.meows = meows schema = Schema( ObjectType( "Query", [ Field( "pets", ListType(PetType), resolver=lambda *_: [ Dog("Odie", True), Cat("Garfield", False), ], ) ], ), types=[DogType, CatType], ) await assert_execution( schema, """{ pets { name __typename ... on Dog { woofs } ... on Cat { meows } } }""", )
async def test_type_resolution_on_union_yields_useful_error(assert_execution): # WARN: Different from ref implementation -> this should never happen so we crash . def _resolve_pet_type(value, *_): return { Dog: DogType, Cat: CatType, Human: HumanType }.get(type(value), None) HumanType = ObjectType("Human", [Field("name", String)]) DogType = ObjectType( "Dog", [Field("name", String), Field("woofs", Boolean)]) CatType = ObjectType( "Cat", [Field("name", String), Field("meows", Boolean)]) PetType = UnionType("Pet", [DogType, CatType], resolve_type=_resolve_pet_type) schema = Schema( ObjectType( "Query", [ Field( "pets", ListType(PetType), resolver=lambda *_: [ Dog("Odie", True), Cat("Garfield", False), Human("Jon"), ], ) ], ), types=[DogType, CatType], ) await assert_execution( schema, """{ pets { __typename ... on Dog { woofs, name } ... on Cat { meows, name } } }""", expected_exc=( RuntimeError, ('Runtime ObjectType "Human" is not a possible type for field ' '"pets[2]" of type "Pet".'), ), )
def test_register_resolver_on_child_type(): Object = ObjectType("Object", [Field("id", String)]) schema = Schema(ObjectType("Query", [Field("foo", Object)])) resolver = lambda *_, **__: None schema.register_resolver("Object", "id", resolver) assert (schema.get_type("Object").fields[0].resolver is resolver # type: ignore )
def test_register_resolver_accepts_override_with_flag(): old_resolver = lambda *_, **__: None Object = ObjectType("Object", [Field("id", String, resolver=old_resolver)]) schema = Schema(ObjectType("Query", [Field("foo", Object)])) resolver = lambda *_, **__: None schema.register_resolver("Object", "id", resolver, allow_override=True) assert (schema.get_type("Object").fields[0].resolver is resolver # type: ignore )
def test_Schema_includes_interface_possible_types_in_the_type_map(): SomeInterface = InterfaceType("SomeInterface", [Field("f", Int)]) SomeSubtype = ObjectType("SomeSubtype", [Field("f", Int)], lambda: [SomeInterface]) schema = Schema( ObjectType("Query", [Field("iface", SomeInterface)]), types=[SomeSubtype], ) assert schema.types.get("SomeSubtype") is SomeSubtype
async def test_full_response_path_is_included_on_error(raiser, assert_execution): A = ObjectType( "A", [ Field("nullableA", lambda: A, resolver=lambda *_: {}), Field("nonNullA", lambda: NonNullType(A), resolver=lambda *_: {}), Field( "raises", lambda: NonNullType(String), resolver=raiser(ResolverError, "Catch me if you can"), ), ], ) # type: ObjectType await assert_execution( Schema( ObjectType( "query", [Field("nullableA", lambda: A, resolver=lambda *_: {})])), """ query { nullableA { aliasedA: nullableA { nonNullA { anotherA: nonNullA { raises } } } } } """, expected_data={ "nullableA": { "aliasedA": { "nonNullA": { "anotherA": { "raises": None } } } } }, expected_errors=[( "Catch me if you can", (134, 140), "nullableA.aliasedA.nonNullA.anotherA.raises", )], )
def test_mutation(): assert (dedent(""" type Mutation { foo: Int } """) == print_schema( Schema(mutation_type=ObjectType("Mutation", [Field("foo", Int)]))))
def test_register_resolver_on_root_type(): schema = Schema(ObjectType("Query", [Field("author", BlogAuthor)])) resolver = lambda *_, **__: None schema.register_resolver("Query", "author", resolver) assert schema.query_type.fields[0].resolver is resolver # type: ignore
async def test_forwarded_resolver_arguments(mocker, assert_execution): resolver = mocker.Mock(return_value="foo") context = mocker.Mock() root = mocker.Mock() field = Field("test", String, [Argument("arg", String)], resolver=resolver) query_type = ObjectType("Test", [field]) doc = parse("query ($var: String) { result: test(arg: $var) }") schema = Schema(query_type) result = assert_execution( schema, doc, context_value=context, initial_value=root, variables={"var": 123}, ) if isawaitable(result): await result (parent_value, ctx, info), args = resolver.call_args assert info.field_definition is field assert info.parent_type is query_type assert info.path == ["result"] assert info.variables == {"var": "123"} assert info.schema is schema assert ctx is context assert parent_value is root assert args == {"arg": "123"}
async def test_custom_scalar(assert_execution): Email = RegexType("Email", r"(^[a-zA-Z0-9_.+-]+@[a-zA-Z0-9-]+\.[a-zA-Z0-9-.]+$)") schema = Schema( ObjectType( "Query", [Field("foo", UUID), Field("bar", Email)])) await assert_execution( schema, """ { foo bar } """, initial_value={ "foo": "aff929fe-25a1-5e3d-8634-4c122f38d596", "bar": "*****@*****.**", }, expected_data={ "foo": "aff929fe-25a1-5e3d-8634-4c122f38d596", "bar": "*****@*****.**", }, )
def test_accept_field_args_with_correct_names(): schema = _single_type_schema( ObjectType( "SomeObject", [Field("field", String, [Argument("goodArg", String)])], )) schema.validate()
def test_injected_object_type_extension(): Foo = ObjectType("Foo", [Field("one", String)]) schema = build_schema( """ type Query { foo: Foo } extend type Foo { two: Int } """, additional_types=[Foo], ) assert schema.to_string() == dedent(""" type Foo { one: String two: Int } type Query { foo: Foo } """) assert schema.types["Foo"] is not Foo
def test_collects_multiple_errors(): iface = InterfaceType("IFace", [Field("f", ListType(String))]) bad_name_union = UnionType("#BadNameUnion", lambda: [object_type]) empty_union = UnionType("EmptyUnion", []) object_type = ObjectType( "SomeObject", [ Field("f", String), Field("__f", lambda: empty_union), Field("g", lambda: bad_name_union), ], interfaces=[iface], ) # type: ObjectType schema = _single_type_schema(object_type) with pytest.raises(SchemaValidationError) as exc_info: validate_schema(schema) assert set([str(e) for e in exc_info.value.errors]) == set([ 'Invalid name "__f".', 'Interface field "IFace.f" expects type "[String]" but "SomeObject.f" ' 'is type "String"', 'UnionType "EmptyUnion" must at least define one member', 'Invalid type name "#BadNameUnion"', ])
def test_accept_object_fields_with_interface_subtype_of_interface_field(): iface = InterfaceType("IFace", [Field("f", lambda: iface)]) # type: InterfaceType obj = ObjectType("Obj", [Field("f", lambda: obj)], interfaces=[iface]) # type: ObjectType schema = _single_type_schema(obj) schema.validate()
def test_accept_input_type(): schema = _single_type_schema( ObjectType( "Object", [Field("field", String, [Argument("arg", SomeInputObject)])], )) schema.validate()
async def run_test(test_type, test_data, *, assert_execution, expected_data=None, expected_errors=None, expected_exc=None, expected_msg=None): data = _obj(test=test_data) data_type = ObjectType( "DataType", [ Field("test", test_type), Field("nest", lambda: data_type, resolver=lambda *_: data), ], ) # type: ObjectType schema = Schema(data_type) await assert_execution( schema, "{ nest { test } }", initial_value=data, expected_data=({ "nest": { "test": expected_data } } if expected_data is not None else None), expected_errors=expected_errors, expected_exc=(expected_exc, expected_msg), )
def test_replace_mutation_type(schema: Schema) -> None: NewMutation = ObjectType( "Mutation", fields=[Field("update_some_number", Int)], ) schema._replace_types_and_directives({"Mutation": NewMutation}) assert schema.mutation_type is NewMutation
def test_Schema_is_possible_handles_non_object_types(): schema = Schema( ObjectType("Query", [Field("getObject", Interface, resolver=_null_resolver)]), directives=[Dir], ) assert not schema.is_possible_type(Interface, Int)
def test_Schema_is_possible_type_is_accurate(): schema = Schema( ObjectType("Query", [Field("getObject", Interface, resolver=_null_resolver)]), directives=[Dir], ) assert not schema.is_possible_type(Interface, Implementing)
async def test_type_resolution_supports_strings(assert_execution): def _resolve_pet_type(value, *_): return type(value).__name__ PetType = InterfaceType("Pet", [Field("name", String)], resolve_type=_resolve_pet_type) DogType = ObjectType( "Dog", [Field("name", String), Field("woofs", Boolean)], interfaces=[PetType], ) CatType = ObjectType( "Cat", [Field("name", String), Field("meows", Boolean)], interfaces=[PetType], ) schema = Schema( ObjectType( "Query", [ Field( "pets", ListType(PetType), resolver=lambda *_: [ Dog("Odie", True), Cat("Garfield", False), ], ) ], ), types=[DogType, CatType], ) await assert_execution( schema, """{ pets { name __typename ... on Dog { woofs } ... on Cat { meows } } }""", )
def test_Schema_get_type_raises_on_unknown_type(): schema = Schema( ObjectType("Query", [Field("getObject", Interface, resolver=_null_resolver)]), directives=[Dir], ) with pytest.raises(UnknownType): schema.get_type("UnknownType")
def test_Schema_includes_input_types_only_used_in_directives(): schema = Schema( ObjectType("Query", [Field("getObject", Interface, resolver=_null_resolver)]), directives=[Dir], ) assert schema.get_type("DirInput") is DirInput assert schema.get_type("WrappedDirInput") is WrappedDirInput