def test_parsing_simple_input_object_with_args_should_fail(): body = ''' input Hello { world(foo: Int): String } ''' with raises(LanguageError) as excinfo: parse(body) assert 'Syntax Error GraphQL (3:8) Expected :, found (' in excinfo.value.message
def test_cannot_be_used_for_execution(): ast = parse(''' extend type Query { newField: String } ''') extended_schema = extend_schema(test_schema, ast) clientQuery = parse('{ newField }') result = execute(extended_schema, object(), clientQuery) assert result.data['newField'] is None assert str( result.errors[0]) == 'Client Schema cannot be used for execution.'
def test_it_concatenates_two_acts_together(): source_a = Source('{ a, b, ... Frag }') source_b = Source(''' fragment Frag on T { c } ''') ast_a = parse(source_a) ast_b = parse(source_b) ast_c = concat_ast([ast_a, ast_b]) assert print_ast(ast_c) == '''{
def test_cannot_be_used_for_execution(): ast = parse(''' extend type Query { newField: String } ''') extended_schema = extend_schema(test_schema, ast) clientQuery = parse('{ newField }') result = execute(extended_schema, object(), clientQuery) assert result.data['newField'] is None assert str(result.errors[0] ) == 'Client Schema cannot be used for execution.'
def test_extends_objects_by_adding_implemented_interfaces(): ast = parse(''' extend type Foo { newObject: NewObject newInterface: NewInterface newUnion: NewUnion newScalar: NewScalar newEnum: NewEnum newTree: [Foo]! } type NewObject implements NewInterface { baz: String } type NewOtherObject { fizz: Int } interface NewInterface { baz: String } union NewUnion = NewObject | NewOtherObject scalar NewScalar enum NewEnum { OPTION_A OPTION_B } ''') original_print = print_schema(test_schema) extended_schema = extend_schema(test_schema, ast) assert extend_schema != test_schema assert print_schema(test_schema) == original_print assert print_schema(extended_schema) == \ '''type Bar implements SomeInterface {
def test_simple_non_null_type(): body = ''' type Hello { world: String! }''' doc = parse(body) loc = create_loc_fn(body) expected = ast.Document(definitions=[ ast.ObjectTypeDefinition( name=ast.Name(value='Hello', loc=loc(6, 11)), interfaces=[], fields=[ ast.FieldDefinition(name=ast.Name(value='world', loc=loc(16, 21)), arguments=[], type=ast.NonNullType(type=ast.NamedType( name=ast.Name(value='String', loc=loc(23, 29)), loc=loc(23, 29)), loc=loc(23, 30)), loc=loc(16, 30)) ], loc=loc(1, 32)) ], loc=loc(1, 32)) assert doc == expected
def test_parses_simple_extension(): body = ''' extend type Hello { world: String }''' doc = parse(body) loc = create_loc_fn(body) expected = ast.Document(definitions=[ ast.TypeExtensionDefinition(definition=ast.ObjectTypeDefinition( name=ast.Name(value='Hello', loc=loc(13, 18)), interfaces=[], fields=[ ast.FieldDefinition(name=ast.Name(value='world', loc=loc(23, 28)), arguments=[], type=ast.NamedType(name=ast.Name( value='String', loc=loc(30, 36)), loc=loc(30, 36)), loc=loc(23, 36)) ], loc=loc(8, 38)), loc=loc(1, 38)) ], loc=loc(1, 38)) assert doc == expected
def test_parses_simple_field_with_list_arg(): body = ''' type Hello { world(things: [String]): String }''' loc = create_loc_fn(body) doc = parse(body) expected = ast.Document(definitions=[ ast.ObjectTypeDefinition( name=ast.Name(value='Hello', loc=loc(6, 11)), interfaces=[], fields=[ ast.FieldDefinition( name=ast.Name(value='world', loc=loc(16, 21)), arguments=[ ast.InputValueDefinition( name=ast.Name(value='things', loc=loc(22, 28)), type=ast.ListType(type=ast.NamedType( name=ast.Name(value='String', loc=loc(31, 37)), loc=loc(31, 37)), loc=loc(30, 38)), default_value=None, loc=loc(22, 38)) ], type=ast.NamedType(name=ast.Name(value='String', loc=loc(41, 47)), loc=loc(41, 47)), loc=loc(16, 47)) ], loc=loc(1, 49)) ], loc=loc(1, 49)) assert doc == expected
def test_validates_using_a_custom_type_info(): type_info = TypeInfo(test_schema, lambda *_: None) ast = parse(''' query { catOrDog { ... on Cat { furColor } ... on Dog { isHousetrained } } } ''') errors = visit_using_rules( test_schema, type_info, ast, specified_rules ) assert len(errors) == 1 assert errors[0].message == 'Cannot query field "catOrDog" on "QueryRoot".'
def test_parses_simple_interface(): body = ''' interface Hello { world: String } ''' loc = create_loc_fn(body) doc = parse(body) expected = ast.Document(definitions=[ ast.InterfaceTypeDefinition( name=ast.Name(value='Hello', loc=loc(11, 16)), fields=[ ast.FieldDefinition(name=ast.Name(value='world', loc=loc(21, 26)), arguments=[], type=ast.NamedType(name=ast.Name( value='String', loc=loc(28, 34)), loc=loc(28, 34)), loc=loc(21, 34)) ], loc=loc(1, 36)) ], loc=loc(1, 37)) assert doc == expected
def test_parses_union_with_two_types(): body = 'union Hello = Wo | Rld' loc = create_loc_fn(body) doc = parse(body) expected = ast.Document( definitions=[ ast.UnionTypeDefinition( name=ast.Name( value='Hello', loc=loc(6, 11) ), types=[ ast.NamedType( name=ast.Name( value='Wo', loc=loc(14, 16) ), loc=loc(14, 16) ), ast.NamedType( name=ast.Name( value='Rld', loc=loc(19, 22) ), loc=loc(19, 22) ) ], loc=loc(0, 22) ) ], loc=loc(0, 22) ) assert doc == expected
def test_validates_using_a_custom_type_info(): type_info = TypeInfo(test_schema, lambda *_: None) ast = parse(''' query { catOrDog { ... on Cat { furColor } ... on Dog { isHousetrained } } } ''') errors = visit_using_rules( test_schema, type_info, ast, specified_rules ) assert len(errors) == 3 assert errors[0].message == 'Cannot query field "catOrDog" on "QueryRoot".' assert errors[1].message == 'Cannot query field "furColor" on "Cat".' assert errors[2].message == 'Cannot query field "isHousetrained" on "Dog".'
def execute_graphql_request(self, request): query, variables, operation_name = self.get_graphql_params(request, self.parse_body(request)) if not query: raise HttpError(HttpResponseBadRequest('Must provide query string.')) source = Source(query, name='GraphQL request') try: document_ast = parse(source) except Exception as e: return ExecutionResult(errors=[e], invalid=True) if request.method.lower() == 'get': operation_ast = get_operation_ast(document_ast, operation_name) if operation_ast and operation_ast.operation != 'query': raise HttpError(HttpResponseNotAllowed( ['POST'], 'Can only perform a {} operation from a POST request.'.format(operation_ast.operation) )) try: return self.execute( document_ast, self.get_root_value(request), variables, operation_name=operation_name, request_context=self.get_request_context(request) ) except Exception as e: return ExecutionResult(errors=[e], invalid=True)
def test_parses_double_value_enum(): body = 'enum Hello { WO, RLD }' loc = create_loc_fn(body) doc = parse(body) expected = ast.Document( definitions=[ ast.EnumTypeDefinition( name=ast.Name( value='Hello', loc=loc(5, 10) ), values=[ ast.EnumValueDefinition( name=ast.Name( value='WO', loc=loc(13, 15) ), loc=loc(13, 15) ), ast.EnumValueDefinition( name=ast.Name( value='RLD', loc=loc(17, 20) ), loc=loc(17, 20) ) ], loc=loc(0, 22) ) ], loc=loc(0, 22) ) assert doc == expected
def test_rejects_fragment_names(): body = '''fragment Foo on Type { field } ''' doc = parse(body) with raises(Exception) as excinfo: build_ast_schema(doc, 'Foo') assert 'Specified query type Foo not found in document' in str(excinfo.value)
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_parses_simple_field_with_arg_with_default_value(): body = ''' type Hello { world(flag: Boolean = true): String }''' loc = create_loc_fn(body) doc = parse(body) expected = ast.Document(definitions=[ ast.ObjectTypeDefinition( name=ast.Name(value='Hello', loc=loc(6, 11)), interfaces=[], fields=[ ast.FieldDefinition( name=ast.Name(value='world', loc=loc(16, 21)), arguments=[ ast.InputValueDefinition( name=ast.Name(value='flag', loc=loc(22, 26)), type=ast.NamedType(name=ast.Name(value='Boolean', loc=loc(28, 35)), loc=loc(28, 35)), default_value=ast.BooleanValue(value=True, loc=loc(38, 42)), loc=loc(22, 42)) ], type=ast.NamedType(name=ast.Name(value='String', loc=loc(45, 51)), loc=loc(45, 51)), loc=loc(16, 51)) ], loc=loc(1, 53)) ], loc=loc(1, 53)) assert doc == expected
def test_parses_simple_union(): body = 'union Hello = World' loc = create_loc_fn(body) doc = parse(body) expected = ast.Document( definitions=[ ast.UnionTypeDefinition( name=ast.Name( value='Hello', loc=loc(6, 11) ), types=[ ast.NamedType( name=ast.Name( value='World', loc=loc(14, 19) ), loc=loc(14, 19) ) ], loc=loc(0, 19) ) ], loc=loc(0, 19) ) assert doc == expected
def test_parses_simple_type_inheriting_multiple_interfaces(): body = 'type Hello implements Wo, rld { }' loc = create_loc_fn(body) doc = parse(body) expected = ast.Document( definitions=[ ast.ObjectTypeDefinition( name=ast.Name( value='Hello', loc=loc(5, 10) ), interfaces=[ ast.NamedType( name=ast.Name( value='Wo', loc=loc(22, 24) ), loc=loc(22, 24) ), ast.NamedType( name=ast.Name( value='rld', loc=loc(26, 29) ), loc=loc(26, 29) ) ], fields=[], loc=loc(0, 33) ) ], loc=loc(0, 33) ) assert doc == expected
def test_ast_to_code_using_kitchen_sink(): doc = parse(fixtures.KITCHEN_SINK) code_ast = ast_to_code(doc) source = Source(fixtures.KITCHEN_SINK) loc = lambda start, end: Loc(start, end, source) parsed_code_ast = eval(code_ast, {}, {'ast': ast, 'loc': loc}) assert doc == parsed_code_ast
def test_parses_simple_field_with_arg_with_default_value(): body = ''' type Hello { world(flag: Boolean = true): String }''' loc = create_loc_fn(body) doc = parse(body) expected = ast.Document( definitions=[ ast.ObjectTypeDefinition( name=ast.Name( value='Hello', loc=loc(6, 11) ), interfaces=[], fields=[ ast.FieldDefinition( name=ast.Name( value='world', loc=loc(16, 21) ), arguments=[ ast.InputValueDefinition( name=ast.Name( value='flag', loc=loc(22, 26) ), type=ast.NamedType( name=ast.Name( value='Boolean', loc=loc(28, 35) ), loc=loc(28, 35) ), default_value=ast.BooleanValue( value=True, loc=loc(38, 42) ), loc=loc(22, 42) ) ], type=ast.NamedType( name=ast.Name( value='String', loc=loc(45, 51) ), loc=loc(45, 51) ), loc=loc(16, 51) ) ], loc=loc(1, 53) ) ], loc=loc(1, 53) ) assert doc == expected
def test_parses_simple_field_with_list_arg(): body = ''' type Hello { world(things: [String]): String }''' loc = create_loc_fn(body) doc = parse(body) expected = ast.Document( definitions=[ ast.ObjectTypeDefinition( name=ast.Name( value='Hello', loc=loc(6, 11) ), interfaces=[], fields=[ ast.FieldDefinition( name=ast.Name( value='world', loc=loc(16, 21) ), arguments=[ ast.InputValueDefinition( name=ast.Name( value='things', loc=loc(22, 28) ), type=ast.ListType( type=ast.NamedType( name=ast.Name( value='String', loc=loc(31, 37) ), loc=loc(31, 37) ), loc=loc(30, 38) ), default_value=None, loc=loc(22, 38) ) ], type=ast.NamedType( name=ast.Name( value='String', loc=loc(41, 47) ), loc=loc(41, 47) ), loc=loc(16, 47) ) ], loc=loc(1, 49) ) ], loc=loc(1, 49) ) assert doc == expected
def test_unknown_type_in_union_list(): body = ''' union TestUnion = Bar type Hello { testUnion: TestUnion } ''' doc = parse(body) with raises(Exception) as excinfo: build_ast_schema(doc, 'Hello') assert 'Type Bar not found in document' in str(excinfo.value)
def test_does_not_allow_extending_a_scalar(): ast = parse(''' extend type String { baz: String } ''') with raises(Exception) as exc_info: extend_schema(test_schema, ast) assert str(exc_info.value) == 'Cannot extend non-object type "String".'
def test_parses_scalar(): body = 'scalar Hello' loc = create_loc_fn(body) doc = parse(body) expected = ast.Document(definitions=[ ast.ScalarTypeDefinition(name=ast.Name(value='Hello', loc=loc(7, 12)), loc=loc(0, 12)) ], loc=loc(0, 12)) assert doc == expected
def test_unknown_mutation_type(): body = ''' type Hello { str: String } ''' doc = parse(body) with raises(Exception) as excinfo: build_ast_schema(doc, 'Hello', 'Wat') assert 'Specified mutation type Wat not found in document' in str(excinfo.value)
def test_unknown_type_referenced(): body = ''' type Hello { bar: Bar } ''' doc = parse(body) with raises(Exception) as excinfo: build_ast_schema(doc, 'Hello') assert 'Type Bar not found in document' in str(excinfo.value)
def test_rejects_query_names(): body = ''' type Hello { str: String } ''' doc = parse(body) with raises(Exception) as excinfo: build_ast_schema(doc, 'Foo') assert 'Specified query type Foo not found in document' in str(excinfo.value)
def test_does_not_allow_replacing_an_existing_interface(): ast = parse(''' extend type Foo implements SomeInterface { otherField: String } ''') with raises(Exception) as exc_info: extend_schema(test_schema, ast) assert str(exc_info.value) == \ ('Type "Foo" already implements "SomeInterface". It cannot also be ' + 'implemented in this type extension.')
def test_does_not_allow_referencing_an_unknown_type(): ast = parse(''' extend type Bar { quix: Quix } ''') with raises(Exception) as exc_info: extend_schema(test_schema, ast) assert str(exc_info.value) == \ ('Unknown type: "Quix". Ensure that this type exists either in the ' + 'original schema, or is added in a type definition.')
def test_does_not_allow_extending_an_unknown_type(): ast = parse(''' extend type UnknownType { baz: String } ''') with raises(Exception) as exc_info: extend_schema(test_schema, ast) assert str(exc_info.value) == \ ('Cannot extend type "UnknownType" because it does not exist in the ' + 'existing schema.')
def test_extends_without_altering_original_schema(): ast = parse(''' extend type Query { newField: String } ''') original_print = print_schema(test_schema) extended_schema = extend_schema(test_schema, ast) assert extend_schema != test_schema assert print_schema(test_schema) == original_print assert 'newField' in print_schema(extended_schema) assert 'newField' not in print_schema(test_schema)
def test_does_not_allow_replacing_an_existing_type(): ast = parse(''' type Bar { baz: String } ''') with raises(Exception) as exc_info: extend_schema(test_schema, ast) assert str(exc_info.value) == \ ('Type "Bar" already exists in the schema. It cannot also be defined ' + 'in this type definition.')
def test_does_not_allow_replacing_an_existing_field(): ast = parse(''' extend type Bar { foo: Foo } ''') with raises(Exception) as exc_info: extend_schema(test_schema, ast) assert str(exc_info.value) == \ ('Field "Bar.foo" already exists in the schema. It cannot also be ' + 'defined in this type extension.')
def test_extends_objects_by_adding_new_fields(): ast = parse(''' extend type Foo { newField: String } ''') original_print = print_schema(test_schema) extended_schema = extend_schema(test_schema, ast) assert extend_schema != test_schema assert print_schema(test_schema) == original_print # print original_print assert print_schema(extended_schema) == \ '''type Bar implements SomeInterface {
def test_extends_objects_by_adding_implemented_interfaces(): ast = parse(''' extend type Biz implements SomeInterface { name: String some: SomeInterface } ''') original_print = print_schema(test_schema) extended_schema = extend_schema(test_schema, ast) assert extend_schema != test_schema assert print_schema(test_schema) == original_print assert print_schema(extended_schema) == \ '''type Bar implements SomeInterface {
def test_extends_objects_by_adding_implemented_new_interfaces(): ast = parse(''' extend type Foo implements NewInterface { baz: String } interface NewInterface { baz: String } ''') original_print = print_schema(test_schema) extended_schema = extend_schema(test_schema, ast) assert extend_schema != test_schema assert print_schema(test_schema) == original_print assert print_schema(extended_schema) == \ '''type Bar implements SomeInterface {
def test_extends_objects_by_adding_new_fields_with_arguments(): ast = parse(''' extend type Foo { newField(arg1: String, arg2: NewInputObj!): String } input NewInputObj { field1: Int field2: [Float] field3: String! } ''') original_print = print_schema(test_schema) extended_schema = extend_schema(test_schema, ast) assert extend_schema != test_schema assert print_schema(test_schema) == original_print assert print_schema(extended_schema) == \ '''type Bar implements SomeInterface {
def test_parses_scalar(): body = 'scalar Hello' loc = create_loc_fn(body) doc = parse(body) expected = ast.Document( definitions=[ ast.ScalarTypeDefinition( name=ast.Name( value='Hello', loc=loc(7, 12) ), loc=loc(0, 12) ) ], loc=loc(0, 12) ) assert doc == expected