def test_nested_error(): _test( [{"foo": "abc"}], ListType(Input), None, "Int cannot represent non integer value: abc at value[0].foo", )
def test_ListType_raises_for_invalid_item(): _test( [1, "abc", "3"], ListType(Int), None, "Int cannot represent non integer value: abc at value[1]", )
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"', ])
async def test_nullable_list_of_non_nullable_items_ok(assert_execution, data, expected): await run_test( ListType(NonNullType(Int)), data, expected_data=expected, assert_execution=assert_execution, )
async def test_nullable_list_of_non_nullable_items_fail( assert_execution, data, expected_err): await run_test( ListType(NonNullType(Int)), data, expected_errors=[expected_err], assert_execution=assert_execution, )
async def test_it_accepts_iterables_for_list_type(assert_execution, iterable, result): await run_test( ListType(String), lazy(iterable), expected_data=result, assert_execution=assert_execution, )
def test_accept_object_with_non_list_interface_list_field(): iface = InterfaceType("IFace", [Field("f", ListType(String))]) schema = _single_type_schema( ObjectType("SomeObject", [Field("f", String)], interfaces=[iface])) with pytest.raises(SchemaError) as exc_info: validate_schema(schema) assert ('Interface field "IFace.f" expects type "[String]" but ' '"SomeObject.f" is type "String"' in str(exc_info.value))
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".'), ), )
async def test_it_raises_on_non_iterable_value_for_list_type( assert_execution, not_iterable): await run_test( ListType(String), not_iterable, assert_execution=assert_execution, expected_exc=RuntimeError, expected_msg=( 'Field "nest.test" is a list type and resolved value should ' "be iterable"), )
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 schema() -> Schema: Object = InterfaceType("Object", fields=[Field("id", NonNullType(ID))]) Person = ObjectType( "Person", fields=[ Field("id", NonNullType(ID)), Field("name", NonNullType(String)), Field("pets", NonNullType(ListType(lambda: Animal))), ], interfaces=[Object], ) Animal = ObjectType( "Animal", fields=[ Field("id", NonNullType(ID)), Field("name", NonNullType(String)), Field("owner", Person), ], interfaces=[Object], ) LivingBeing = UnionType("LivingBeing", [Person, Animal]) CreatePersonInput = InputObjectType( "CreatePersonInput", [InputField("id", ID), InputField("name", NonNullType(String))], ) return Schema( query_type=ObjectType( "Query", fields=[ Field("person", Person, args=[Argument("id", ID)]), Field("pet", Animal, args=[Argument("id", ID)]), Field("living_being", LivingBeing, args=[Argument("id", ID)]), ], ), mutation_type=ObjectType( "Mutation", fields=[Field("createPerson", CreatePersonInput)]), )
assert print_schema(Schema()) == "" class CustomDirective(SchemaDirective): definition = Directive( "custom", args=[Argument("arg", NonNullType(String))], locations=Directive.SCHEMA_LOCATONS, ) @pytest.mark.parametrize( "type_, opts, expected", [ (String, {}, "String"), (ListType(String), {}, "[String]"), (NonNullType(String), {}, "String!"), (NonNullType(ListType(String)), {}, "[String]!"), (ListType(NonNullType(String)), {}, "[String!]"), (NonNullType(ListType(NonNullType(String))), {}, "[String!]!"), ], ) def test_single_field_schema(type_, opts, expected): assert (dedent(""" type Query { singleField: %s } """ % expected) == print_schema(_single_field_schema( type_, **opts), indent=" "))
def test_ListType_for_single_valid_value(): _test("1", ListType(Int), [1])
def test_ListType_for_valid_values(): _test([1, "2", "3"], ListType(Int), [1, 2, 3])
def _type_modifiers(t): return [t, ListType(t), NonNullType(t), NonNullType(ListType(t))]
) def test_ast_node_from_value_with_enums(value, expected): if isinstance(expected, Exception): with pytest.raises(type(expected)) as exc_info: ast_node_from_value(value, Enum) assert str(expected) == str(exc_info.value) else: assert ast_node_from_value(value, Enum) == expected @pytest.mark.parametrize( "value, input_type, expected", [ ( ["FOO", "BAR"], ListType(String), _ast.ListValue(values=[ _ast.StringValue(value="FOO"), _ast.StringValue(value="BAR"), ]), ), ( ["HELLO", "GOODBYE"], ListType(Enum), _ast.ListValue(values=[ _ast.EnumValue(value="HELLO"), _ast.EnumValue(value="GOODBYE"), ]), ), ("FOO", ListType(String), _ast.StringValue(value="FOO")), ],
def schema(): Being = InterfaceType( "Being", [Field("name", String, [Argument("surname", Boolean)])]) Pet = InterfaceType( "Pet", [Field("name", String, [Argument("surname", Boolean)])]) Canine = InterfaceType( "Canine", [Field("name", String, [Argument("surname", Boolean)])]) DogCommand = EnumType( "DogCommand", [EnumValue("SIT", 0), EnumValue("HEEL", 1), EnumValue("DOWN", 2)], ) FurColor = EnumType( "FurColor", [ EnumValue("BROWN", 0), EnumValue("BLACK", 1), EnumValue("TAN", 2), EnumValue("SPOTTED", 3), EnumValue("NO_FUR", None), EnumValue("UNKNOWN", -1), ], ) Dog = ObjectType( "Dog", [ Field("name", String, args=[Argument("surname", Boolean)]), Field("nickname", String), Field("barkVolume", Int), Field("barks", Boolean), Field("doesKnowCommand", Boolean, [Argument("dogCommand", DogCommand)]), Field( "isHousetrained", Boolean, [Argument("atOtherHomes", Boolean, True)], ), Field( "isAtLocation", Boolean, [Argument("x", Int), Argument("y", Int)], ), ], [Being, Pet, Canine], ) Cat = ObjectType( "Cat", [ Field("name", String, args=[Argument("surname", Boolean)]), Field("nickname", String), Field("meowVolume", Int), Field("meows", Boolean), Field("furColor", FurColor), ], [Being, Pet], ) CatOrDog = UnionType("CatOrDog", [Dog, Cat]) Intelligent = InterfaceType("Intelligent", [Field("iq", Int)]) Human = ObjectType( "Human", lambda: [ Field("name", String, args=[Argument("surname", Boolean)]), Field("iq", Int), Field("pets", ListType(Pet)), Field("relatives", ListType(Human)), ], [Being, Intelligent], ) Alien = ObjectType( "Alien", [ Field("name", String, args=[Argument("surname", Boolean)]), Field("iq", Int), Field("numEyes", Int), ], [Being, Intelligent], ) DogOrHuman = UnionType("DogOrHuman", [Dog, Human]) HumanOrAlien = UnionType("HumanOrAlien", [Human, Alien]) ComplexInput = InputObjectType( "ComplexInput", [ InputField("requiredField", NonNullType(Boolean)), InputField( "nonNullField", NonNullType(Boolean), default_value=False), InputField("intField", Int), InputField("stringField", String), InputField("booleanField", Boolean), InputField("stringListField", ListType(String)), ], ) ComplicatedArgs = ObjectType( "ComplicatedArgs", [ Field("intArgField", String, [Argument("intArg", Int)]), Field( "nonNullIntArgField", String, [Argument("nonNullIntArg", NonNullType(Int))], ), Field("stringArgField", String, [Argument("stringArg", String)]), Field("booleanArgField", String, [Argument("booleanArg", Boolean)]), Field("enumArgField", String, [Argument("enumArg", FurColor)]), Field("floatArgField", String, [Argument("floatArg", Float)]), Field("idArgField", String, [Argument("idArg", ID)]), Field( "stringListArgField", String, [Argument("stringListArg", ListType(String))], ), Field( "stringListNonNullArgField", String, [ Argument("stringListNonNullArg", ListType(NonNullType(String))) ], ), Field( "complexArgField", String, [Argument("complexArg", ComplexInput)], ), Field( "multipleReqs", String, [ Argument("req1", NonNullType(Int)), Argument("req2", NonNullType(Int)), ], ), Field( "nonNullFieldWithDefault", String, [Argument("arg", NonNullType(Int), default_value=0)], ), Field( "multipleOpts", String, [Argument("opt1", Int, 0), Argument("opt2", Int, 0)], ), Field( "multipleOptAndReq", String, [ Argument("req1", NonNullType(Int)), Argument("req2", NonNullType(Int)), Argument("opt1", Int, 0), Argument("opt2", Int, 0), ], ), ], ) def _invalid(*args, **kwargs): raise ValueError("Invalid scalar is always invalid") def _stringify(value): return str(value) InvalidScalar = ScalarType("Invalid", _stringify, _invalid, _invalid) AnyScalar = ScalarType("Any", _stringify, lambda x: x) # type: ScalarType return Schema( ObjectType( "QueryRoot", [ Field("human", Human, [Argument("id", ID)]), Field("alien", Alien), Field("dog", Dog), Field("cat", Cat), Field("pet", Pet), Field("catOrDog", CatOrDog), Field("dogOrHuman", DogOrHuman), Field("humanOrAlien", HumanOrAlien), Field("humanOrAlien", HumanOrAlien), Field("complicatedArgs", ComplicatedArgs), Field("invalidArg", String, [Argument("arg", InvalidScalar)]), Field("anydArg", String, [Argument("arg", AnyScalar)]), ], ), types=[Cat, Dog, Human, Alien], directives=[ Directive("onQuery", ["QUERY"]), Directive("onMutation", ["MUTATION"]), Directive("onSubscription", ["SUBSCRIPTION"]), Directive("onField", ["FIELD"]), Directive("onFragmentDefinition", ["FRAGMENT_DEFINITION"]), Directive("onFragmentSpread", ["FRAGMENT_SPREAD"]), Directive("onInlineFragment", ["INLINE_FRAGMENT"]), Directive("onSchema", ["SCHEMA"]), Directive("onScalar", ["SCALAR"]), Directive("onObject", ["OBJECT"]), Directive("onFieldDefinition", ["FIELD_DEFINITION"]), Directive("onArgumentDefinition", ["ARGUMENT_DEFINITION"]), Directive("onInterface", ["INTERFACE"]), Directive("onUnion", ["UNION"]), Directive("onEnum", ["ENUM"]), Directive("onEnumValue", ["ENUM_VALUE"]), Directive("onInputObject", ["INPUT_OBJECT"]), Directive("onInputFieldDefinition", ["INPUT_FIELD_DEFINITION"]), ], )
def schema_2(): SomeBox = InterfaceType( "SomeBox", [Field("deepBox", lambda: SomeBox), Field("unrelatedField", String)], ) # type: InterfaceType StringBox = ObjectType( "StringBox", [ Field("scalar", String), Field("deepBox", lambda: StringBox), Field("unrelatedField", String), Field("listStringBox", lambda: ListType(StringBox)), Field("stringBox", lambda: StringBox), Field("intBox", lambda: IntBox), ], [SomeBox], ) # type: ObjectType IntBox = ObjectType( "IntBox", [ Field("scalar", Int), Field("deepBox", lambda: IntBox), Field("unrelatedField", String), Field("listStringBox", lambda: ListType(StringBox)), Field("stringBox", lambda: StringBox), Field("intBox", lambda: IntBox), ], [SomeBox], ) # type: ObjectType NonNullStringBox1 = InterfaceType("NonNullStringBox1", [Field("scalar", NonNullType(String))]) NonNullStringBox1Impl = ObjectType( "NonNullStringBox1Impl", [ Field("scalar", NonNullType(String)), Field("unrelatedField", String), Field("deepBox", SomeBox), ], [SomeBox, NonNullStringBox1], ) NonNullStringBox2 = InterfaceType("NonNullStringBox2", [Field("scalar", NonNullType(String))]) NonNullStringBox2Impl = ObjectType( "NonNullStringBox2Impl", [ Field("scalar", NonNullType(String)), Field("unrelatedField", String), Field("deepBox", SomeBox), ], [SomeBox, NonNullStringBox2], ) Connection = ObjectType( "Connection", [ Field( "edges", ListType( ObjectType( "Edge", [ Field( "node", ObjectType( "Node", [Field("id", ID), Field("name", String)], ), ) ], )), ) ], ) yield Schema( ObjectType( "QueryRoot", [Field("someBox", SomeBox), Field("connection", Connection)], ), types=[ IntBox, StringBox, NonNullStringBox1Impl, NonNullStringBox2Impl ], )
Interface = InterfaceType("Interface", [Field("fieldName", String)]) Implementing = ObjectType("Object", [Field("fieldName", String)], interfaces=[Interface]) DirInput = InputObjectType("DirInput", [InputField("field", String)]) WrappedDirInput = InputObjectType("WrappedDirInput", [InputField("field", String)]) Dir = Directive( "dir", ["OBJECT"], [ Argument("arg", DirInput), Argument("argList", ListType(WrappedDirInput)) ], ) BlogImage = ObjectType( "Image", [Field("url", String), Field("width", Int), Field("height", Int)]) BlogAuthor = ObjectType( "Author", [ Field("id", String), Field("name", String), Field("pic", BlogImage, [Argument("width", Int),
pytestmark = pytest.mark.asyncio def _complex_parse(value): if value == "SerializedValue": return "DeserializedValue" raise ValueError(value) ComplexScalar = ScalarType("ComplexScalar", _complex_parse, _complex_parse) TestInputObject = InputObjectType( "TestInputObject", [ InputField("a", String), InputField("b", ListType(String)), InputField("c", NonNullType(String)), InputField("d", ComplexScalar), ], ) TestNestedInputObject = InputObjectType( "TestNestedInputObject", [ InputField("na", NonNullType(TestInputObject)), InputField("nb", NonNullType(String)), ], ) def _inspect(name):
def resolve_character_type(character, *_): return {"Human": Human, "Droid": Droid}[character["type"]] Character = InterfaceType( "Character", [ Field( "id", NonNullType(String), description="The id of the character." ), Field("name", String, description="The name of the character."), Field( "friends", ListType(lambda: Character), description=( "The friends of the character, or an empty list if they have " "none." ), ), Field( "appearsIn", ListType(Episode), description="Which movies they appear in.", ), Field( "secretBackstory", String, description="All secrets about their past.", ),
def test_as_list(): assert UUID.as_list() == ListType(UUID)
} BlogImage = ObjectType( "Image", [Field("url", String), Field("width", Int), Field("height", Int)]) BlogArticle = ObjectType( "Article", [ Field("id", String), Field("isPublished", Boolean), Field("author", lambda: BlogAuthor, resolver=lambda *_: _JOHN_SMITH), Field("title", String), Field("body", String), Field("keywords", ListType(String)), ], ) # type: ObjectType BlogAuthor = ObjectType( "Author", [ Field("id", String), Field("name", String), Field( "pic", BlogImage, [Argument("width", Int), Argument("height", Int)], resolver=lambda *_, **args: { "url": "cdn://123",
def test_accept_object_with_list_interface_list_field(): iface = InterfaceType("IFace", [Field("f", ListType(String))]) schema = _single_type_schema( ObjectType("SomeObject", [Field("f", ListType(String))], interfaces=[iface])) schema.validate()
def _resolve_pet_type(value, *_): if isinstance(value, Dog): return DogType elif isinstance(value, Cat): return CatType PetType = UnionType("Pet", [DogType, CatType], resolve_type=_resolve_pet_type) PersonType = ObjectType( "Person", [ Field("name", String), Field("pets", ListType(PetType)), Field("friends", lambda: ListType(NamedType)), ], interfaces=[NamedType], ) _SCHEMA = Schema(PersonType) _GARFIELD = Cat("Garfield", False) _ODIE = Dog("Odie", True) _LIZ = Person("Liz", None, None) _JOHN = Person("John", [_GARFIELD, _ODIE], [_LIZ, _ODIE]) @pytest.mark.filterwarnings("ignore::RuntimeWarning") async def test_it_can_introspect_on_union_and_intersection_types(