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_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_gets_execution_info_in_resolver(): encountered_schema = [None] encountered_root_value = [None] def resolve_type(obj, info): encountered_schema[0] = info.schema encountered_root_value[0] = info.root_value return PersonType2 NamedType2 = GraphQLInterfaceType( name='Named', fields={'name': GraphQLField(GraphQLString)}, resolve_type=resolve_type) PersonType2 = GraphQLObjectType(name='Person', interfaces=[NamedType2], fields={ 'name': GraphQLField(GraphQLString), 'friends': GraphQLField(GraphQLList(NamedType2)) }) schema2 = GraphQLSchema(query=PersonType2) john2 = Person('John', [], [liz]) ast = parse('''{ name, friends { name } }''') result = execute(schema2, john2, ast) assert result.data == {'name': 'John', 'friends': [{'name': 'Liz'}]} assert encountered_schema[0] == schema2 assert encountered_root_value[0] == john2
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_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_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_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_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_builds_a_schema_with_field_arguments(): schema = GraphQLSchema(query=GraphQLObjectType( name='ArgFields', fields=OrderedDict([ ('one', GraphQLField(GraphQLString, description='A field with a single arg', args={ 'intArg': GraphQLArgument(GraphQLInt, description='This is an int arg') })), ('two', GraphQLField(GraphQLString, description='A field with two args', args=OrderedDict( [('listArg', GraphQLArgument( GraphQLList(GraphQLInt), description='This is a list of int arg')), ('requiredArg', GraphQLArgument( GraphQLNonNull(GraphQLBoolean), description='This is a required arg'))]))), ]))) _test_schema(schema)
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_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'}, ] }})
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_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_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_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 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_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_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_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_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_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 run(test_type, test_data): class Data(object): test = test_data DataType = GraphQLObjectType('DataType', lambda: { 'test': GraphQLField(test_type), 'nest': GraphQLField(DataType, resolver=lambda *_: Data()) }) schema = GraphQLSchema(DataType) ast = parse('{ nest { test } }') return execute(schema, Data(), ast)
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_complex_field_values(): schema = GraphQLSchema(query=GraphQLObjectType( name='ComplexFields', fields=OrderedDict( [('string', GraphQLField(GraphQLString) ), ('listOfString', GraphQLField(GraphQLList(GraphQLString))), ('nonNullString', GraphQLField(GraphQLNonNull(GraphQLString))), ('nonNullListOfString', GraphQLField(GraphQLNonNull(GraphQLList(GraphQLString)))), ('nonNullListOfNonNullString', GraphQLField( GraphQLNonNull(GraphQLList(GraphQLNonNull(GraphQLString)))) )]))) _test_schema(schema)
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_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_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 internal_type(self, schema): resolver = self.resolver description = self.description arguments = self.arguments if not description and resolver: description = resolver.__doc__ type = schema.T(self.get_type(schema)) type_objecttype = schema.objecttype(type) if type_objecttype and issubclass(type_objecttype, Mutation): assert len(arguments) == 0 arguments = type_objecttype.get_arguments() resolver = getattr(type_objecttype, 'mutate') else: my_resolver = resolver @wraps(my_resolver) def wrapped_func(instance, args, info): if not isinstance(instance, self.object_type): instance = self.object_type(_root=instance) return my_resolver(instance, args, info) resolver = wrapped_func assert type, 'Internal type for field %s is None' % str(self) return GraphQLField( type, args=schema.T(arguments), resolver=self.decorate_resolver(resolver), description=description, )
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