def test_builds_a_schema_with_a_union(): DogType = GraphQLObjectType( name='Dog', fields=lambda: { 'bestFriend': GraphQLField(FriendlyType) } ) HumanType = GraphQLObjectType( name='Human', fields=lambda: { 'bestFriend': GraphQLField(FriendlyType) } ) FriendlyType = GraphQLUnionType( name='Friendly', resolve_type=lambda: None, types=[DogType, HumanType] ) schema = GraphQLSchema( query=GraphQLObjectType( name='WithUnion', fields={ 'friendly': GraphQLField(FriendlyType) } ) ) _test_schema(schema)
def test_builds_a_schema_with_an_interface(): FriendlyType = GraphQLInterfaceType( name='Friendly', resolve_type=lambda: None, fields=lambda: { 'bestFriend': GraphQLField(FriendlyType, description='The best friend of this friendly thing.') } ) GraphQLObjectType( name='Human', interfaces=[FriendlyType], fields=lambda: { 'bestFriend': GraphQLField(FriendlyType) } ) schema = GraphQLSchema( query=GraphQLObjectType( name='WithInterface', fields={ 'friendly': GraphQLField(FriendlyType) } ) ) _test_schema(schema)
def test_fails_when_an_is_type_of_check_is_not_met(): class Special(object): def __init__(self, value): self.value = value class NotSpecial(object): def __init__(self, value): self.value = value SpecialType = GraphQLObjectType( 'SpecialType', fields={ 'value': GraphQLField(GraphQLString), }, is_type_of=lambda obj, info: isinstance(obj, Special)) schema = GraphQLSchema( GraphQLObjectType(name='Query', fields={ 'specials': GraphQLField( GraphQLList(SpecialType), resolver=lambda root, *_: root['specials']) })) query = parse('{ specials { value } }') value = {'specials': [Special('foo'), NotSpecial('bar')]} result = execute(schema, value, query) assert result.data == {'specials': [{'value': 'foo'}, None]} assert 'Expected value of type "SpecialType" but got NotSpecial.' in str( result.errors)
def test_includes_interfaces_thunk_subtypes_in_the_type_map(): SomeInterface = GraphQLInterfaceType( name='SomeInterface', fields={ 'f': GraphQLField(GraphQLInt) } ) SomeSubtype = GraphQLObjectType( name='SomeSubtype', fields={ 'f': GraphQLField(GraphQLInt) }, interfaces=lambda: [SomeInterface], is_type_of=lambda: True ) schema = GraphQLSchema(query=GraphQLObjectType( name='Query', fields={ 'iface': GraphQLField(SomeInterface) } )) assert schema.get_type_map()['SomeSubtype'] is SomeSubtype
def test_may_extend_mutations_and_subscriptions(): mutationSchema = GraphQLSchema( query=GraphQLObjectType('Query', fields=lambda: { 'queryField': GraphQLField(GraphQLString), }), mutation=GraphQLObjectType('Mutation', fields={ 'mutationField': GraphQLField(GraphQLString), }), subscription=GraphQLObjectType('Subscription', fields={ 'subscriptionField': GraphQLField(GraphQLString), }), ) ast = parse(''' extend type Query { newQueryField: Int } extend type Mutation { newMutationField: Int } extend type Subscription { newSubscriptionField: Int } ''') original_print = print_schema(mutationSchema) extended_schema = extend_schema(mutationSchema, ast) assert extend_schema != mutationSchema assert print_schema(mutationSchema) == original_print assert print_schema(extended_schema) == \ '''type Mutation {
def test_prints_interface(): FooType = GraphQLInterfaceType( name='Foo', resolve_type=lambda *_: None, fields={ 'str': GraphQLField(GraphQLString) } ) BarType = GraphQLObjectType( name='Bar', fields={ 'str': GraphQLField(GraphQLString), }, interfaces=[FooType] ) Root = GraphQLObjectType( name='Root', fields={ 'bar': GraphQLField(BarType) } ) Schema = GraphQLSchema(Root) output = print_for_test(Schema) assert output == '''
def test_builds_a_simple_schema_with_both_operation_types(): QueryType = GraphQLObjectType( name='QueryType', description='This is a simple query type', fields={ 'string': GraphQLField(GraphQLString, description='This is a string field.') }) MutationType = GraphQLObjectType( name='MutationType', description='This is a simple mutation type', fields={ 'setString': GraphQLField(GraphQLString, description='Set the string field', args={'value': GraphQLArgument(GraphQLString)}) }) SubscriptionType = GraphQLObjectType( name='SubscriptionType', description='This is a simple subscription type', fields={ 'string': GraphQLField(type=GraphQLString, description='This is a string field') }) schema = GraphQLSchema(QueryType, MutationType, SubscriptionType) _test_schema(schema)
def test_prints_unions(): FooType = GraphQLObjectType( name='Foo', fields={ 'bool': GraphQLField(GraphQLBoolean), }, ) BarType = GraphQLObjectType( name='Bar', fields={ 'str': GraphQLField(GraphQLString), }, ) SingleUnion = GraphQLUnionType(name='SingleUnion', resolve_type=lambda *_: None, types=[FooType]) MultipleUnion = GraphQLUnionType( name='MultipleUnion', resolve_type=lambda *_: None, types=[FooType, BarType], ) Root = GraphQLObjectType(name='Root', fields=OrderedDict([ ('single', GraphQLField(SingleUnion)), ('multiple', GraphQLField(MultipleUnion)), ])) Schema = GraphQLSchema(Root) output = print_for_test(Schema) assert output == '''
def test_does_not_mutate_passed_field_definitions(): fields = { 'field1': GraphQLField(GraphQLString), 'field2': GraphQLField(GraphQLString, args={'id': GraphQLArgument(GraphQLString)}), } TestObject1 = GraphQLObjectType(name='Test1', fields=fields) TestObject2 = GraphQLObjectType(name='Test1', fields=fields) assert TestObject1.get_fields() == TestObject2.get_fields() assert fields == { 'field1': GraphQLField(GraphQLString), 'field2': GraphQLField(GraphQLString, args={'id': GraphQLArgument(GraphQLString)}), } input_fields = { 'field1': GraphQLInputObjectField(GraphQLString), 'field2': GraphQLInputObjectField(GraphQLString), } TestInputObject1 = GraphQLInputObjectType(name='Test1', fields=input_fields) TestInputObject2 = GraphQLInputObjectType(name='Test2', fields=input_fields) assert TestInputObject1.get_fields() == TestInputObject2.get_fields() assert input_fields == { 'field1': GraphQLInputObjectField(GraphQLString), 'field2': GraphQLInputObjectField(GraphQLString), }
def test_includes_nested_input_objects_in_the_map(): NestedInputObject = GraphQLInputObjectType( name='NestedInputObject', fields={'value': GraphQLInputObjectField(GraphQLString)}) SomeInputObject = GraphQLInputObjectType( name='SomeInputObject', fields={'nested': GraphQLInputObjectField(NestedInputObject)}) SomeMutation = GraphQLObjectType( name='SomeMutation', fields={ 'mutateSomething': GraphQLField(type=BlogArticle, args={'input': GraphQLArgument(SomeInputObject)}) }) SomeSubscription = GraphQLObjectType( name='SomeSubscription', fields={ 'subscribeToSomething': GraphQLField(type=BlogArticle, args={'input': GraphQLArgument(SomeInputObject)}) }) schema = GraphQLSchema(query=BlogQuery, mutation=SomeMutation, subscription=SomeSubscription) assert schema.get_type_map()['NestedInputObject'] is NestedInputObject
def test_does_not_include_illegal_fields_in_output(): doc = 'mutation M { thisIsIllegalDontIncludeMe }' ast = parse(doc) Q = GraphQLObjectType('Q', {'a': GraphQLField(GraphQLString)}) M = GraphQLObjectType('M', {'c': GraphQLField(GraphQLString)}) result = execute(GraphQLSchema(Q, M), None, ast) assert not result.errors assert result.data == {}
def test_prints_object_field(): FooType = GraphQLObjectType(name='Foo', fields={'str': GraphQLField(GraphQLString)}) Root = GraphQLObjectType(name='Root', fields={'foo': GraphQLField(FooType)}) Schema = GraphQLSchema(Root) output = print_for_test(Schema) assert output == '''
def test_uses_the_mutation_schema_for_queries(): doc = 'query Q { a } mutation M { c }' class Data(object): a = 'b' c = 'd' ast = parse(doc) Q = GraphQLObjectType('Q', {'a': GraphQLField(GraphQLString)}) M = GraphQLObjectType('M', {'c': GraphQLField(GraphQLString)}) result = execute(GraphQLSchema(Q, M), Data(), ast, 'M') assert not result.errors assert result.data == {'c': 'd'}
def test_uses_the_subscription_schema_for_subscriptions(): doc = 'query Q { a } subscription S { a }' class Data(object): a = 'b' c = 'd' ast = parse(doc) Q = GraphQLObjectType('Q', {'a': GraphQLField(GraphQLString)}) S = GraphQLObjectType('S', {'a': GraphQLField(GraphQLString)}) result = execute(GraphQLSchema(Q, subscription=S), Data(), ast, 'S') assert not result.errors assert result.data == {'a': 'b'}
def test_builds_a_schema_with_a_circular_type_reference(): DogType = GraphQLObjectType( name='Dog', fields=lambda: {'bestFriend': GraphQLField(HumanType)}) HumanType = GraphQLObjectType( name='Human', fields=lambda: {'bestFriend': GraphQLField(DogType)}) schema = GraphQLSchema( query=GraphQLObjectType(name='Circular', fields=OrderedDict([ ('dog', GraphQLField(DogType)), ('human', GraphQLField(HumanType)), ]))) _test_schema(schema)
def test_identifies_deprecated_enum_values(): TestEnum = GraphQLEnumType('TestEnum', OrderedDict([ ('NONDEPRECATED', GraphQLEnumValue(0)), ('DEPRECATED', GraphQLEnumValue(1, deprecation_reason='Removed in 1.0')), ('ALSONONDEPRECATED', GraphQLEnumValue(2)) ])) TestType = GraphQLObjectType('TestType', { 'testEnum': GraphQLField(TestEnum) }) schema = GraphQLSchema(TestType) request = '''{__type(name: "TestEnum") { name enumValues(includeDeprecated: true) { name isDeprecated deprecationReason } } }''' result = graphql(schema, request) assert not result.errors assert result.data == {'__type': { 'name': 'TestEnum', 'enumValues': [ {'name': 'NONDEPRECATED', 'isDeprecated': False, 'deprecationReason': None}, {'name': 'DEPRECATED', 'isDeprecated': True, 'deprecationReason': 'Removed in 1.0'}, {'name': 'ALSONONDEPRECATED', 'isDeprecated': False, 'deprecationReason': None}, ]}}
def test_respects_the_includedeprecated_parameter_for_enum_values(): TestEnum = GraphQLEnumType('TestEnum', OrderedDict([ ('NONDEPRECATED', GraphQLEnumValue(0)), ('DEPRECATED', GraphQLEnumValue(1, deprecation_reason='Removed in 1.0')), ('ALSONONDEPRECATED', GraphQLEnumValue(2)) ])) TestType = GraphQLObjectType('TestType', { 'testEnum': GraphQLField(TestEnum) }) schema = GraphQLSchema(TestType) request = '''{__type(name: "TestEnum") { name trueValues: enumValues(includeDeprecated: true) { name } falseValues: enumValues(includeDeprecated: false) { name } omittedValues: enumValues { name } } }''' result = graphql(schema, request) assert not result.errors assert result.data == {'__type': { 'name': 'TestEnum', 'trueValues': [{'name': 'NONDEPRECATED'}, {'name': 'DEPRECATED'}, {'name': 'ALSONONDEPRECATED'}], 'falseValues': [{'name': 'NONDEPRECATED'}, {'name': 'ALSONONDEPRECATED'}], 'omittedValues': [{'name': 'NONDEPRECATED'}, {'name': 'ALSONONDEPRECATED'}], }}
def test_synchronous_executor_doesnt_support_defers(): class Data(object): def promise(self): return succeed('i shouldn\'nt work') def notPromise(self): return 'i should work' DataType = GraphQLObjectType( 'DataType', { 'promise': GraphQLField(GraphQLNonNull(GraphQLString)), 'notPromise': GraphQLField(GraphQLString), }) doc = ''' query Example { promise notPromise } ''' schema = GraphQLSchema(query=DataType) executor = Executor([SynchronousExecutionMiddleware()]) result = executor.execute(schema, doc, Data(), operation_name='Example') assert not isinstance(result, Deferred) assert result.data is None formatted_errors = list(map(format_error, result.errors)) assert formatted_errors == [{ 'locations': [dict(line=3, column=9)], 'message': 'You cannot return a Deferred from a resolver ' 'when using SynchronousExecutionMiddleware' }]
def test_executor_defer_failure(): class Data(object): def promise(self): return fail(Exception('Something bad happened! Sucks :(')) def notPromise(self): return 'i should work' DataType = GraphQLObjectType( 'DataType', { 'promise': GraphQLField(GraphQLNonNull(GraphQLString)), 'notPromise': GraphQLField(GraphQLString), }) doc = ''' query Example { promise notPromise } ''' schema = GraphQLSchema(query=DataType) executor = Executor() result = executor.execute(schema, doc, Data(), operation_name='Example') assert result.called result = result.result assert result.data is None formatted_errors = list(map(format_error, result.errors)) assert formatted_errors == [{ 'locations': [dict(line=3, column=9)], 'message': "Something bad happened! Sucks :(" }]
def test_gevent_executor(): @run_in_greenlet def resolver(context, *_): gevent.sleep(0.001) return 'hey' @run_in_greenlet def resolver_2(context, *_): gevent.sleep(0.003) return 'hey2' def resolver_3(contest, *_): return 'hey3' Type = GraphQLObjectType( 'Type', { 'a': GraphQLField(GraphQLString, resolver=resolver), 'b': GraphQLField(GraphQLString, resolver=resolver_2), 'c': GraphQLField(GraphQLString, resolver=resolver_3) }) doc = '{ a b c }' executor = Executor([GeventExecutionMiddleware()]) result = executor.execute(GraphQLSchema(Type), doc) assert not result.errors assert result.data == {'a': 'hey', 'b': 'hey2', 'c': 'hey3'}
def test_gevent_executor_with_error(): doc = 'query Example { a, b }' @run_in_greenlet def resolver(context, *_): gevent.sleep(0.001) return 'hey' @run_in_greenlet def resolver_2(context, *_): gevent.sleep(0.003) raise Exception('resolver_2 failed!') Type = GraphQLObjectType( 'Type', { 'a': GraphQLField(GraphQLString, resolver=resolver), 'b': GraphQLField(GraphQLString, resolver=resolver_2) }) executor = Executor([GeventExecutionMiddleware()]) result = executor.execute(GraphQLSchema(Type), doc) formatted_errors = list(map(format_error, result.errors)) assert formatted_errors == [{ 'locations': [{ 'line': 1, 'column': 20 }], 'message': 'resolver_2 failed!' }] assert result.data == {'a': 'hey', 'b': None}
def test_cannot_use_client_schema_for_general_execution(): customScalar = GraphQLScalarType(name='CustomScalar', serialize=lambda: None) schema = GraphQLSchema(query=GraphQLObjectType( name='Query', fields={ 'foo': GraphQLField(GraphQLString, args=OrderedDict([('custom1', GraphQLArgument(customScalar)), ('custom2', GraphQLArgument(customScalar))])) })) introspection = graphql(schema, introspection_query) client_schema = build_client_schema(introspection.data) class data: foo = 'bar' result = graphql( client_schema, 'query NoNo($v: CustomScalar) { foo(custom1: 123, custom2: $v) }', data, {'v': 'baz'}) assert result.data == {'foo': None} assert [format_error(e) for e in result.errors] == [{ 'locations': [{ 'column': 32, 'line': 1 }], 'message': 'Client Schema cannot be used for execution.' }]
def test_builds_a_schema_aware_of_deprecation(): schema = GraphQLSchema(query=GraphQLObjectType( name='Simple', description='This is a simple type', fields=OrderedDict( [('shinyString', GraphQLField(type=GraphQLString, description='This is a shiny string field')), ('deprecatedString', GraphQLField(type=GraphQLString, description='This is a deprecated string field', deprecation_reason='Use shinyString')), ('color', GraphQLField(type=GraphQLEnumType( name='Color', values=OrderedDict([ ('RED', GraphQLEnumValue(description='So rosy')), ('GREEN', GraphQLEnumValue(description='So grassy')), ('BLUE', GraphQLEnumValue(description='So calming')), ('MAUVE', GraphQLEnumValue( description='So sickening', deprecation_reason='No longer in fashion')), ]))))]))) _test_schema(schema)
def test_executor_can_enforce_strict_ordering(): Type = GraphQLObjectType('Type', lambda: { 'a': GraphQLField(GraphQLString, resolver=lambda *_: 'Apple'), 'b': GraphQLField(GraphQLString, resolver=lambda *_: 'Banana'), 'c': GraphQLField(GraphQLString, resolver=lambda *_: 'Cherry'), 'deep': GraphQLField(Type, resolver=lambda *_: {}), }) schema = GraphQLSchema(query=Type) executor = Executor(execution_middlewares=[SynchronousExecutionMiddleware], map_type=OrderedDict) query = '{ a b c aa: c cc: c bb: b aaz: a bbz: b deep { b a c deeper: deep { c a b } } ' \ 'ccz: c zzz: c aaa: a }' def check_result(result): assert not result.errors data = result.data assert isinstance(data, OrderedDict) assert list(data.keys()) == ['a', 'b', 'c', 'aa', 'cc', 'bb', 'aaz', 'bbz', 'deep', 'ccz', 'zzz', 'aaa'] deep = data['deep'] assert isinstance(deep, OrderedDict) assert list(deep.keys()) == ['b', 'a', 'c', 'deeper'] deeper = deep['deeper'] assert isinstance(deeper, OrderedDict) assert list(deeper.keys()) == ['c', 'a', 'b'] check_result(executor.execute(schema, query)) check_result(executor.execute(schema, query, execute_serially=True))
def test_correctly_threads_arguments(): doc = ''' query Example { b(numArg: 123, stringArg: "foo") } ''' def resolver(_, args, *_args): assert args['numArg'] == 123 assert args['stringArg'] == 'foo' resolver.got_here = True resolver.got_here = False doc_ast = parse(doc) Type = GraphQLObjectType('Type', { 'b': GraphQLField( GraphQLString, args={ 'numArg': GraphQLArgument(GraphQLInt), 'stringArg': GraphQLArgument(GraphQLString), }, resolver=resolver), }) result = execute(GraphQLSchema(Type), None, doc_ast, 'Example', {}) assert not result.errors assert resolver.got_here
def test_executor_can_enforce_strict_ordering(): Type = GraphQLObjectType('Type', lambda: { 'a': GraphQLField(GraphQLString, resolver=lambda *_: succeed('Apple')), 'b': GraphQLField(GraphQLString, resolver=lambda *_: succeed('Banana')), 'c': GraphQLField(GraphQLString, resolver=lambda *_: succeed('Cherry')), 'deep': GraphQLField(Type, resolver=lambda *_: succeed({})), }) schema = GraphQLSchema(query=Type) executor = Executor(map_type=OrderedDict) query = '{ a b c aa: c cc: c bb: b aaz: a bbz: b deep { b a c deeper: deep { c a b } } ' \ 'ccz: c zzz: c aaa: a }' def handle_results(result): assert not result.errors data = result.data assert isinstance(data, OrderedDict) assert list(data.keys()) == ['a', 'b', 'c', 'aa', 'cc', 'bb', 'aaz', 'bbz', 'deep', 'ccz', 'zzz', 'aaa'] deep = data['deep'] assert isinstance(deep, OrderedDict) assert list(deep.keys()) == ['b', 'a', 'c', 'deeper'] deeper = deep['deeper'] assert isinstance(deeper, OrderedDict) assert list(deeper.keys()) == ['c', 'a', 'b'] raise_callback_results(executor.execute(schema, query), handle_results) raise_callback_results(executor.execute(schema, query, execute_serially=True), handle_results)
def test_builds_a_schema_with_an_input_object(): AddressType = GraphQLInputObjectType( name='Address', description='An input address', fields=OrderedDict([ ('street', GraphQLInputObjectField( GraphQLNonNull(GraphQLString), description='What street is this address?')), ('city', GraphQLInputObjectField( GraphQLNonNull(GraphQLString), description='The city the address is within?')), ('country', GraphQLInputObjectField( GraphQLString, description='The country (blank will assume USA).', default_value='USA')), ])) schema = GraphQLSchema(query=GraphQLObjectType( name='HasInputObjectFields', fields={ 'geocode': GraphQLField(description='Get a geocode from an address', type=GraphQLString, args={ 'address': GraphQLArgument( description='The address to lookup', type=AddressType) }) })) _test_schema(schema)
def run_check(self): test_type = self.type data = Data(test=test_data) DataType = GraphQLObjectType( name='DataType', fields=lambda: { 'test': GraphQLField(test_type), 'nest': GraphQLField(DataType, resolver=lambda *_: data) }) schema = GraphQLSchema(query=DataType) response = executor.execute(schema, ast, data) assert response.called response = response.result if response.errors: result = { 'data': response.data, 'errors': [format_error(e) for e in response.errors] } else: result = {'data': response.data} assert result == expected
def test_respects_the_includedeprecated_parameter_for_fields(): TestType = GraphQLObjectType( 'TestType', { 'nonDeprecated': GraphQLField(GraphQLString), 'deprecated': GraphQLField(GraphQLString, deprecation_reason='Removed in 1.0') }) schema = GraphQLSchema(TestType) request = '''{__type(name: "TestType") { name trueFields: fields(includeDeprecated: true) { name } falseFields: fields(includeDeprecated: false) { name } omittedFields: fields { name } } }''' result = graphql(schema, request) assert not result.errors assert sort_lists(result.data) == sort_lists({ '__type': { 'name': 'TestType', 'trueFields': [{ 'name': 'nonDeprecated' }, { 'name': 'deprecated' }], 'falseFields': [{ 'name': 'nonDeprecated' }], 'omittedFields': [{ 'name': 'nonDeprecated' }], } })
def test_identifies_deprecated_fields(): TestType = GraphQLObjectType('TestType', { 'nonDeprecated': GraphQLField(GraphQLString), 'deprecated': GraphQLField(GraphQLString, deprecation_reason='Removed in 1.0') }) schema = GraphQLSchema(TestType) request = '''{__type(name: "TestType") { name fields(includeDeprecated: true) { name isDeprecated deprecationReason } } }''' result = graphql(schema, request) assert not result.errors assert sort_lists(result.data) == sort_lists({'__type': { 'name': 'TestType', 'fields': [ {'name': 'nonDeprecated', 'isDeprecated': False, 'deprecationReason': None}, {'name': 'deprecated', 'isDeprecated': True, 'deprecationReason': 'Removed in 1.0'}, ] }})