func TestTypeSystem_ObjectsMustAdhereToInterfaceTheyImplement_AcceptsAnObjectWithAnEquivalentlyModifiedInterfaceField(t *testing.T) { anotherInterface := types.NewGraphQLInterfaceType(types.GraphQLInterfaceTypeConfig{ Name: "AnotherInterface", ResolveType: func(value interface{}, info types.GraphQLResolveInfo) *types.GraphQLObjectType { return nil }, Fields: types.GraphQLFieldConfigMap{ "field": &types.GraphQLFieldConfig{ Type: types.NewGraphQLNonNull(types.NewGraphQLList(types.GraphQLString)), }, }, }) anotherObject := types.NewGraphQLObjectType(types.GraphQLObjectTypeConfig{ Name: "AnotherObject", Interfaces: []*types.GraphQLInterfaceType{anotherInterface}, Fields: types.GraphQLFieldConfigMap{ "field": &types.GraphQLFieldConfig{ Type: types.NewGraphQLNonNull(types.NewGraphQLList(types.GraphQLString)), }, }, }) _, err := schemaWithObjectFieldOfType(anotherObject) if err != nil { t.Fatalf(`unexpected error: %v for type "%v"`, err, anotherObject) } }
func TestTypeSystem_DefinitionExample_StringifiesSimpleTypes(t *testing.T) { type Test struct { ttype types.GraphQLType expected string } tests := []Test{ Test{types.GraphQLInt, "Int"}, Test{blogArticle, "Article"}, Test{interfaceType, "Interface"}, Test{unionType, "Union"}, Test{enumType, "Enum"}, Test{inputObjectType, "InputObject"}, Test{types.NewGraphQLNonNull(types.GraphQLInt), "Int!"}, Test{types.NewGraphQLList(types.GraphQLInt), "[Int]"}, Test{types.NewGraphQLNonNull(types.NewGraphQLList(types.GraphQLInt)), "[Int]!"}, Test{types.NewGraphQLList(types.NewGraphQLNonNull(types.GraphQLInt)), "[Int!]"}, Test{types.NewGraphQLList(types.NewGraphQLList(types.GraphQLInt)), "[[Int]]"}, } for _, test := range tests { ttypeStr := fmt.Sprintf("%v", test.ttype) if ttypeStr != test.expected { t.Fatalf(`expected %v , got: %v`, test.expected, ttypeStr) } } }
func PluralIdentifyingRootField(config PluralIdentifyingRootFieldConfig) *types.GraphQLFieldConfig { inputArgs := types.GraphQLFieldConfigArgumentMap{} if config.ArgName != "" { inputArgs[config.ArgName] = &types.GraphQLArgumentConfig{ Type: types.NewGraphQLNonNull(types.NewGraphQLList(types.NewGraphQLNonNull(config.InputType))), } } return &types.GraphQLFieldConfig{ Description: config.Description, Type: types.NewGraphQLList(config.OutputType), Args: inputArgs, Resolve: func(p types.GQLFRParams) interface{} { inputs, ok := p.Args[config.ArgName] if !ok { return nil } if config.ResolveSingleInput == nil { return nil } switch inputs := inputs.(type) { case []interface{}: res := []interface{}{} for _, input := range inputs { r := config.ResolveSingleInput(input) res = append(res, r) } return res } return nil }, } }
func withModifiers(ttypes []types.GraphQLType) []types.GraphQLType { res := ttypes for _, ttype := range ttypes { res = append(res, types.NewGraphQLList(ttype)) } for _, ttype := range ttypes { res = append(res, types.NewGraphQLNonNull(ttype)) } for _, ttype := range ttypes { res = append(res, types.NewGraphQLNonNull(types.NewGraphQLList(ttype))) } return res }
func TestTypeSystem_ListMustAcceptGraphQLTypes_RejectsANilTypeAsItemTypeOfList(t *testing.T) { result := types.NewGraphQLList(nil) expectedError := `Can only create List of a GraphQLType but got: <nil>.` if result.GetError() == nil || result.GetError().Error() != expectedError { t.Fatalf("Expected error: %v, got %v", expectedError, result.GetError()) } }
func TestTypeSystem_DefinitionExample_IdentifiesOutputTypes(t *testing.T) { type Test struct { ttype types.GraphQLType expected bool } tests := []Test{ Test{types.GraphQLInt, true}, Test{objectType, true}, Test{interfaceType, true}, Test{unionType, true}, Test{enumType, true}, Test{inputObjectType, false}, } for _, test := range tests { ttypeStr := fmt.Sprintf("%v", test.ttype) if types.IsOutputType(test.ttype) != test.expected { t.Fatalf(`expected %v , got: %v`, test.expected, ttypeStr) } if types.IsOutputType(types.NewGraphQLList(test.ttype)) != test.expected { t.Fatalf(`expected %v , got: %v`, test.expected, ttypeStr) } if types.IsOutputType(types.NewGraphQLNonNull(test.ttype)) != test.expected { t.Fatalf(`expected %v , got: %v`, test.expected, ttypeStr) } } }
func TestLists_NonNullListOfNonNullFunc_ReturnsNull(t *testing.T) { ttype := types.NewGraphQLNonNull(types.NewGraphQLList(types.NewGraphQLNonNull(types.GraphQLInt))) // `data` is a function that return values // Note that its uses the expected signature `func() interface{} {...}` data := func() interface{} { return nil } expected := &types.GraphQLResult{ Data: map[string]interface{}{ "nest": nil, }, Errors: []graphqlerrors.GraphQLFormattedError{ graphqlerrors.GraphQLFormattedError{ Message: "Cannot return null for non-nullable field DataType.test.", Locations: []location.SourceLocation{ location.SourceLocation{ Line: 1, Column: 10, }, }, }, }, } checkList(t, ttype, data, expected) }
func TestLists_NullableListOfNonNullObjects_ContainsNull(t *testing.T) { ttype := types.NewGraphQLList(types.NewGraphQLNonNull(types.GraphQLInt)) data := []interface{}{ 1, nil, 2, } expected := &types.GraphQLResult{ Data: map[string]interface{}{ "nest": map[string]interface{}{ "test": nil, }, }, Errors: []graphqlerrors.GraphQLFormattedError{ graphqlerrors.GraphQLFormattedError{ Message: "Cannot return null for non-nullable field DataType.test.", Locations: []location.SourceLocation{ location.SourceLocation{ Line: 1, Column: 10, }, }, }, }, } checkList(t, ttype, data, expected) }
func TestLists_NonNullListOfNonNullArrayOfFunc_ContainsNulls(t *testing.T) { ttype := types.NewGraphQLNonNull(types.NewGraphQLList(types.NewGraphQLNonNull(types.GraphQLInt))) // `data` is a slice of functions that return values // Note that its uses the expected signature `func() interface{} {...}` data := []interface{}{ func() interface{} { return 1 }, func() interface{} { return nil }, func() interface{} { return 2 }, } expected := &types.GraphQLResult{ Data: map[string]interface{}{ "nest": map[string]interface{}{ "test": []interface{}{ 1, nil, 2, }, }, }, } checkList(t, ttype, data, expected) }
func TestTypeSystem_NonNullMustAcceptGraphQLTypes_AcceptsAnTypeAsNullableTypeOfNonNull(t *testing.T) { nullableTypes := []types.GraphQLType{ types.GraphQLString, someScalarType, someObjectType, someUnionType, someInterfaceType, someEnumType, someInputObject, types.NewGraphQLList(types.GraphQLString), types.NewGraphQLList(types.NewGraphQLNonNull(types.GraphQLString)), } for _, ttype := range nullableTypes { result := types.NewGraphQLNonNull(ttype) if result.GetError() != nil { t.Fatalf(`unexpected error: %v for type "%v"`, result.GetError(), ttype) } } }
func TestLists_ListOfNullableObjects_ReturnsNull(t *testing.T) { ttype := types.NewGraphQLList(types.GraphQLInt) expected := &types.GraphQLResult{ Data: map[string]interface{}{ "nest": map[string]interface{}{ "test": nil, }, }, } checkList(t, ttype, nil, expected) }
func TestLists_ListOfNullableObjects_ContainsNull(t *testing.T) { ttype := types.NewGraphQLList(types.GraphQLInt) data := []interface{}{ 1, nil, 2, } expected := &types.GraphQLResult{ Data: map[string]interface{}{ "nest": map[string]interface{}{ "test": []interface{}{ 1, nil, 2, }, }, }, } checkList(t, ttype, data, expected) }
func TestTypeSystem_ListMustAcceptGraphQLTypes_AcceptsAnTypeAsItemTypeOfList(t *testing.T) { testTypes := withModifiers([]types.GraphQLType{ types.GraphQLString, someScalarType, someEnumType, someObjectType, someUnionType, someInterfaceType, }) for _, ttype := range testTypes { result := types.NewGraphQLList(ttype) if result.GetError() != nil { t.Fatalf(`unexpected error: %v for type "%v"`, result.GetError(), ttype) } } }
// Describe [T!]! Array<T> func TestLists_NonNullListOfNonNullObjects_ContainsValues(t *testing.T) { ttype := types.NewGraphQLNonNull(types.NewGraphQLList(types.NewGraphQLNonNull(types.GraphQLInt))) data := []interface{}{ 1, 2, } expected := &types.GraphQLResult{ Data: map[string]interface{}{ "nest": map[string]interface{}{ "test": []interface{}{ 1, 2, }, }, }, } checkList(t, ttype, data, expected) }
func TestLists_NullableListOfNonNullFunc_ReturnsNull(t *testing.T) { ttype := types.NewGraphQLList(types.NewGraphQLNonNull(types.GraphQLInt)) // `data` is a function that return values // Note that its uses the expected signature `func() interface{} {...}` data := func() interface{} { return nil } expected := &types.GraphQLResult{ Data: map[string]interface{}{ "nest": map[string]interface{}{ "test": nil, }, }, } checkList(t, ttype, data, expected) }
func ConnectionDefinitions(config ConnectionConfig) *GraphQLConnectionDefinitions { edgeType := types.NewGraphQLObjectType(types.GraphQLObjectTypeConfig{ Name: config.Name + "Edge", Description: "An edge in a connection", Fields: types.GraphQLFieldConfigMap{ "node": &types.GraphQLFieldConfig{ Type: config.NodeType, Description: "The item at the end of the edge", }, "cursor": &types.GraphQLFieldConfig{ Type: types.NewGraphQLNonNull(types.GraphQLString), Description: " cursor for use in pagination", }, }, }) for fieldName, fieldConfig := range config.EdgeFields { edgeType.AddFieldConfig(fieldName, fieldConfig) } connectionType := types.NewGraphQLObjectType(types.GraphQLObjectTypeConfig{ Name: config.Name + "Connection", Description: "A connection to a list of items.", Fields: types.GraphQLFieldConfigMap{ "pageInfo": &types.GraphQLFieldConfig{ Type: types.NewGraphQLNonNull(pageInfoType), Description: "Information to aid in pagination.", }, "edges": &types.GraphQLFieldConfig{ Type: types.NewGraphQLList(edgeType), Description: "Information to aid in pagination.", }, }, }) for fieldName, fieldConfig := range config.ConnectionFields { connectionType.AddFieldConfig(fieldName, fieldConfig) } return &GraphQLConnectionDefinitions{ EdgeType: edgeType, ConnectionType: connectionType, } }
// Describe [T] Func()Array<T> // equivalent to Promise<Array<T>> func TestLists_ListOfNullableFunc_ContainsValues(t *testing.T) { ttype := types.NewGraphQLList(types.GraphQLInt) // `data` is a function that return values // Note that its uses the expected signature `func() interface{} {...}` data := func() interface{} { return []interface{}{ 1, 2, } } expected := &types.GraphQLResult{ Data: map[string]interface{}{ "nest": map[string]interface{}{ "test": []interface{}{ 1, 2, }, }, }, } checkList(t, ttype, data, expected) }
func TestFailsWhenAnIsTypeOfCheckIsNotMet(t *testing.T) { query := `{ specials { value } }` data := map[string]interface{}{ "specials": []interface{}{ testSpecialType{"foo"}, testNotSpecialType{"bar"}, }, } expected := &types.GraphQLResult{ Data: map[string]interface{}{ "specials": []interface{}{ map[string]interface{}{ "value": "foo", }, nil, }, }, Errors: []graphqlerrors.GraphQLFormattedError{ graphqlerrors.GraphQLFormattedError{ Message: `Expected value of type "SpecialType" but got: executor_test.testNotSpecialType.`, Locations: []location.SourceLocation{}, }, }, } specialType := types.NewGraphQLObjectType(types.GraphQLObjectTypeConfig{ Name: "SpecialType", IsTypeOf: func(value interface{}, info types.GraphQLResolveInfo) bool { if _, ok := value.(testSpecialType); ok { return true } return false }, Fields: types.GraphQLFieldConfigMap{ "value": &types.GraphQLFieldConfig{ Type: types.GraphQLString, Resolve: func(ctx context.Context, p types.GQLFRParams) interface{} { return p.Source.(testSpecialType).Value }, }, }, }) schema, err := types.NewGraphQLSchema(types.GraphQLSchemaConfig{ Query: types.NewGraphQLObjectType(types.GraphQLObjectTypeConfig{ Name: "Query", Fields: types.GraphQLFieldConfigMap{ "specials": &types.GraphQLFieldConfig{ Type: types.NewGraphQLList(specialType), Resolve: func(ctx context.Context, p types.GQLFRParams) interface{} { return p.Source.(map[string]interface{})["specials"] }, }, }, }), }) if err != nil { t.Fatalf("Error in schema %v", err.Error()) } // parse query ast := testutil.Parse(t, query) // execute ep := executor.ExecuteParams{ Schema: schema, AST: ast, Root: data, } result := testutil.Execute(t, ep) if len(result.Errors) == 0 { t.Fatalf("wrong result, unexpected errors: %v", result.Errors) } if !reflect.DeepEqual(expected, result) { t.Fatalf("Unexpected result, Diff: %v", testutil.Diff(expected, result)) } }
func TestExecutesArbitraryCode(t *testing.T) { deepData := map[string]interface{}{} data := map[string]interface{}{ "a": func() interface{} { return "Apple" }, "b": func() interface{} { return "Banana" }, "c": func() interface{} { return "Cookie" }, "d": func() interface{} { return "Donut" }, "e": func() interface{} { return "Egg" }, "f": "Fish", "pic": func(size int) string { return fmt.Sprintf("Pic of size: %v", size) }, "deep": func() interface{} { return deepData }, } data["promise"] = func() interface{} { return data } deepData = map[string]interface{}{ "a": func() interface{} { return "Already Been Done" }, "b": func() interface{} { return "Boring" }, "c": func() interface{} { return []string{"Contrived", "", "Confusing"} }, "deeper": func() interface{} { return []interface{}{data, nil, data} }, } query := ` query Example($size: Int) { a, b, x: c ...c f ...on DataType { pic(size: $size) promise { a } } deep { a b c deeper { a b } } } fragment c on DataType { d e } ` expected := &types.GraphQLResult{ Data: map[string]interface{}{ "b": "Banana", "x": "Cookie", "d": "Donut", "e": "Egg", "promise": map[string]interface{}{ "a": "Apple", }, "a": "Apple", "deep": map[string]interface{}{ "a": "Already Been Done", "b": "Boring", "c": []interface{}{ "Contrived", nil, "Confusing", }, "deeper": []interface{}{ map[string]interface{}{ "a": "Apple", "b": "Banana", }, nil, map[string]interface{}{ "a": "Apple", "b": "Banana", }, }, }, "f": "Fish", "pic": "Pic of size: 100", }, } // Schema Definitions picResolverFn := func(ctx context.Context, p types.GQLFRParams) interface{} { // get and type assert ResolveFn for this field picResolver, ok := p.Source.(map[string]interface{})["pic"].(func(size int) string) if !ok { return nil } // get and type assert argument sizeArg, ok := p.Args["size"].(int) if !ok { return nil } return picResolver(sizeArg) } dataType := types.NewGraphQLObjectType(types.GraphQLObjectTypeConfig{ Name: "DataType", Fields: types.GraphQLFieldConfigMap{ "a": &types.GraphQLFieldConfig{ Type: types.GraphQLString, }, "b": &types.GraphQLFieldConfig{ Type: types.GraphQLString, }, "c": &types.GraphQLFieldConfig{ Type: types.GraphQLString, }, "d": &types.GraphQLFieldConfig{ Type: types.GraphQLString, }, "e": &types.GraphQLFieldConfig{ Type: types.GraphQLString, }, "f": &types.GraphQLFieldConfig{ Type: types.GraphQLString, }, "pic": &types.GraphQLFieldConfig{ Args: types.GraphQLFieldConfigArgumentMap{ "size": &types.GraphQLArgumentConfig{ Type: types.GraphQLInt, }, }, Type: types.GraphQLString, Resolve: picResolverFn, }, }, }) deepDataType := types.NewGraphQLObjectType(types.GraphQLObjectTypeConfig{ Name: "DeepDataType", Fields: types.GraphQLFieldConfigMap{ "a": &types.GraphQLFieldConfig{ Type: types.GraphQLString, }, "b": &types.GraphQLFieldConfig{ Type: types.GraphQLString, }, "c": &types.GraphQLFieldConfig{ Type: types.NewGraphQLList(types.GraphQLString), }, "deeper": &types.GraphQLFieldConfig{ Type: types.NewGraphQLList(dataType), }, }, }) // Exploring a way to have a GraphQLObjectType within itself // in this case DataType has DeepDataType has DataType dataType.AddFieldConfig("deep", &types.GraphQLFieldConfig{ Type: deepDataType, }) // in this case DataType has DataType dataType.AddFieldConfig("promise", &types.GraphQLFieldConfig{ Type: dataType, }) schema, err := types.NewGraphQLSchema(types.GraphQLSchemaConfig{ Query: dataType, }) if err != nil { t.Fatalf("Error in schema %v", err.Error()) } // parse query astDoc := testutil.Parse(t, query) // execute args := map[string]interface{}{ "size": 100, } operationName := "Example" ep := executor.ExecuteParams{ Schema: schema, Root: data, AST: astDoc, OperationName: operationName, Args: args, } result := testutil.Execute(t, ep) if len(result.Errors) > 0 { t.Fatalf("wrong result, unexpected errors: %v", result.Errors) } if !reflect.DeepEqual(expected, result) { t.Fatalf("Unexpected result, Diff: %v", testutil.Diff(expected, result)) } }
func TestUnionIntersectionTypes_GetsExecutionInfoInResolver(t *testing.T) { var encounteredSchema *types.GraphQLSchema var encounteredRootValue interface{} var personType2 *types.GraphQLObjectType namedType2 := types.NewGraphQLInterfaceType(types.GraphQLInterfaceTypeConfig{ Name: "Named", Fields: types.GraphQLFieldConfigMap{ "name": &types.GraphQLFieldConfig{ Type: types.GraphQLString, }, }, ResolveType: func(value interface{}, info types.GraphQLResolveInfo) *types.GraphQLObjectType { encounteredSchema = &info.Schema encounteredRootValue = info.RootValue return personType2 }, }) personType2 = types.NewGraphQLObjectType(types.GraphQLObjectTypeConfig{ Name: "Person", Interfaces: []*types.GraphQLInterfaceType{ namedType2, }, Fields: types.GraphQLFieldConfigMap{ "name": &types.GraphQLFieldConfig{ Type: types.GraphQLString, }, "friends": &types.GraphQLFieldConfig{ Type: types.NewGraphQLList(namedType2), }, }, }) schema2, _ := types.NewGraphQLSchema(types.GraphQLSchemaConfig{ Query: personType2, }) john2 := &testPerson{ Name: "John", Friends: []testNamedType{ liz, }, } doc := `{ name, friends { name } }` expected := &types.GraphQLResult{ Data: map[string]interface{}{ "name": "John", "friends": []interface{}{ map[string]interface{}{ "name": "Liz", }, }, }, } // parse query ast := testutil.Parse(t, doc) // execute ep := executor.ExecuteParams{ Schema: schema2, AST: ast, Root: john2, } result := testutil.Execute(t, ep) if len(result.Errors) != len(expected.Errors) { t.Fatalf("Unexpected errors, Diff: %v", testutil.Diff(expected.Errors, result.Errors)) } if !reflect.DeepEqual(expected, result) { t.Fatalf("Unexpected result, Diff: %v", testutil.Diff(expected, result)) } }
return dogType } return nil }, }) var personType = types.NewGraphQLObjectType(types.GraphQLObjectTypeConfig{ Name: "Person", Interfaces: []*types.GraphQLInterfaceType{ namedType, }, Fields: types.GraphQLFieldConfigMap{ "name": &types.GraphQLFieldConfig{ Type: types.GraphQLString, }, "pets": &types.GraphQLFieldConfig{ Type: types.NewGraphQLList(petType), }, "friends": &types.GraphQLFieldConfig{ Type: types.NewGraphQLList(namedType), }, }, IsTypeOf: func(value interface{}, info types.GraphQLResolveInfo) bool { _, ok := value.(*testPerson) return ok }, }) var unionInterfaceTestSchema, _ = types.NewGraphQLSchema(types.GraphQLSchemaConfig{ Query: personType, })
func TestIntrospection_ExecutesAnInputObject(t *testing.T) { testInputObject := types.NewGraphQLInputObjectType(types.InputObjectConfig{ Name: "TestInputObject", Fields: types.InputObjectConfigFieldMap{ "a": &types.InputObjectFieldConfig{ Type: types.GraphQLString, DefaultValue: "foo", }, "b": &types.InputObjectFieldConfig{ Type: types.NewGraphQLList(types.GraphQLString), }, }, }) testType := types.NewGraphQLObjectType(types.GraphQLObjectTypeConfig{ Name: "TestType", Fields: types.GraphQLFieldConfigMap{ "field": &types.GraphQLFieldConfig{ Type: types.GraphQLString, Args: types.GraphQLFieldConfigArgumentMap{ "complex": &types.GraphQLArgumentConfig{ Type: testInputObject, }, }, Resolve: func(p types.GQLFRParams) interface{} { return p.Args["complex"] }, }, }, }) schema, err := types.NewGraphQLSchema(types.GraphQLSchemaConfig{ Query: testType, }) if err != nil { t.Fatalf("Error creating GraphQLSchema: %v", err.Error()) } query := ` { __schema { types { kind name inputFields { name type { ...TypeRef } defaultValue } } } } fragment TypeRef on __Type { kind name ofType { kind name ofType { kind name ofType { kind name } } } } ` expectedDataSubSet := map[string]interface{}{ "__schema": map[string]interface{}{ "types": []interface{}{ map[string]interface{}{ "kind": "INPUT_OBJECT", "name": "TestInputObject", "inputFields": []interface{}{ map[string]interface{}{ "name": "a", "type": map[string]interface{}{ "kind": "SCALAR", "name": "String", "ofType": nil, }, "defaultValue": `"foo"`, }, map[string]interface{}{ "name": "b", "type": map[string]interface{}{ "kind": "LIST", "name": nil, "ofType": map[string]interface{}{ "kind": "SCALAR", "name": "String", "ofType": nil, }, }, "defaultValue": nil, }, }, }, }, }, } result := graphql(t, gql.GraphqlParams{ Schema: schema, RequestString: query, }) if !testutil.ContainSubset(result.Data.(map[string]interface{}), expectedDataSubSet) { t.Fatalf("unexpected, result does not contain subset of expected data") } }
func TestExecutesUsingAComplexSchema(t *testing.T) { johnSmith = &testAuthor{ Id: 123, Name: "John Smith", Pic: func(width string, height string) *testPic { return getPic(123, width, height) }, RecentArticle: article("1"), } blogImage := types.NewGraphQLObjectType(types.GraphQLObjectTypeConfig{ Name: "Image", Fields: types.GraphQLFieldConfigMap{ "url": &types.GraphQLFieldConfig{ Type: types.GraphQLString, }, "width": &types.GraphQLFieldConfig{ Type: types.GraphQLInt, }, "height": &types.GraphQLFieldConfig{ Type: types.GraphQLInt, }, }, }) blogAuthor := types.NewGraphQLObjectType(types.GraphQLObjectTypeConfig{ Name: "Author", Fields: types.GraphQLFieldConfigMap{ "id": &types.GraphQLFieldConfig{ Type: types.GraphQLString, }, "name": &types.GraphQLFieldConfig{ Type: types.GraphQLString, }, "pic": &types.GraphQLFieldConfig{ Type: blogImage, Args: types.GraphQLFieldConfigArgumentMap{ "width": &types.GraphQLArgumentConfig{ Type: types.GraphQLInt, }, "height": &types.GraphQLArgumentConfig{ Type: types.GraphQLInt, }, }, Resolve: func(ctx context.Context, p types.GQLFRParams) interface{} { if author, ok := p.Source.(*testAuthor); ok { width := fmt.Sprintf("%v", p.Args["width"]) height := fmt.Sprintf("%v", p.Args["height"]) return author.Pic(width, height) } return nil }, }, "recentArticle": &types.GraphQLFieldConfig{}, }, }) blogArticle := types.NewGraphQLObjectType(types.GraphQLObjectTypeConfig{ Name: "Article", Fields: types.GraphQLFieldConfigMap{ "id": &types.GraphQLFieldConfig{ Type: types.NewGraphQLNonNull(types.GraphQLString), }, "isPublished": &types.GraphQLFieldConfig{ Type: types.GraphQLBoolean, }, "author": &types.GraphQLFieldConfig{ Type: blogAuthor, }, "title": &types.GraphQLFieldConfig{ Type: types.GraphQLString, }, "body": &types.GraphQLFieldConfig{ Type: types.GraphQLString, }, "keywords": &types.GraphQLFieldConfig{ Type: types.NewGraphQLList(types.GraphQLString), }, }, }) blogAuthor.AddFieldConfig("recentArticle", &types.GraphQLFieldConfig{ Type: blogArticle, }) blogQuery := types.NewGraphQLObjectType(types.GraphQLObjectTypeConfig{ Name: "Query", Fields: types.GraphQLFieldConfigMap{ "article": &types.GraphQLFieldConfig{ Type: blogArticle, Args: types.GraphQLFieldConfigArgumentMap{ "id": &types.GraphQLArgumentConfig{ Type: types.GraphQLID, }, }, Resolve: func(ctx context.Context, p types.GQLFRParams) interface{} { id := p.Args["id"] return article(id) }, }, "feed": &types.GraphQLFieldConfig{ Type: types.NewGraphQLList(blogArticle), Resolve: func(ctx context.Context, p types.GQLFRParams) interface{} { return []*testArticle{ article(1), article(2), article(3), article(4), article(5), article(6), article(7), article(8), article(9), article(10), } }, }, }, }) blogSchema, err := types.NewGraphQLSchema(types.GraphQLSchemaConfig{ Query: blogQuery, }) if err != nil { t.Fatalf("Error in schema %v", err.Error()) } request := ` { feed { id, title }, article(id: "1") { ...articleFields, author { id, name, pic(width: 640, height: 480) { url, width, height }, recentArticle { ...articleFields, keywords } } } } fragment articleFields on Article { id, isPublished, title, body, hidden, notdefined } ` expected := &types.GraphQLResult{ Data: map[string]interface{}{ "article": map[string]interface{}{ "title": "My Article 1", "body": "This is a post", "author": map[string]interface{}{ "id": "123", "name": "John Smith", "pic": map[string]interface{}{ "url": "cdn://123", "width": 640, "height": 480, }, "recentArticle": map[string]interface{}{ "id": "1", "isPublished": bool(true), "title": "My Article 1", "body": "This is a post", "keywords": []interface{}{ "foo", "bar", "1", "true", nil, }, }, }, "id": "1", "isPublished": bool(true), }, "feed": []interface{}{ map[string]interface{}{ "id": "1", "title": "My Article 1", }, map[string]interface{}{ "id": "2", "title": "My Article 2", }, map[string]interface{}{ "id": "3", "title": "My Article 3", }, map[string]interface{}{ "id": "4", "title": "My Article 4", }, map[string]interface{}{ "id": "5", "title": "My Article 5", }, map[string]interface{}{ "id": "6", "title": "My Article 6", }, map[string]interface{}{ "id": "7", "title": "My Article 7", }, map[string]interface{}{ "id": "8", "title": "My Article 8", }, map[string]interface{}{ "id": "9", "title": "My Article 9", }, map[string]interface{}{ "id": "10", "title": "My Article 10", }, }, }, } // parse query ast := testutil.Parse(t, request) // execute ep := executor.ExecuteParams{ Schema: blogSchema, AST: ast, } result := testutil.Execute(t, ep) if len(result.Errors) > 0 { t.Fatalf("wrong result, unexpected errors: %v", result.Errors) } if !reflect.DeepEqual(expected, result) { t.Fatalf("Unexpected result, Diff: %v", testutil.Diff(expected, result)) } }
switch value.(type) { case *user: return globalIDTestUserType case *photo2: return globalIDTestPhotoType default: panic(fmt.Sprintf("Unknown object type `%v`", value)) } }, }) var globalIDTestQueryType = types.NewGraphQLObjectType(types.GraphQLObjectTypeConfig{ Name: "Query", Fields: types.GraphQLFieldConfigMap{ "node": globalIDTestDef.NodeField, "allObjects": &types.GraphQLFieldConfig{ Type: types.NewGraphQLList(globalIDTestDef.NodeInterface), Resolve: func(p types.GQLFRParams) interface{} { return []interface{}{ globalIDTestUserData["1"], globalIDTestUserData["2"], globalIDTestPhotoData["1"], globalIDTestPhotoData["2"], } }, }, }, }) // becareful not to define schema here, since globalIDTestUserType and globalIDTestPhotoType wouldn't be defined till init() var globalIDTestSchema types.GraphQLSchema
func init() { Luke = StarWarsChar{ Id: "1000", Name: "Luke Skywalker", AppearsIn: []int{4, 5, 6}, HomePlanet: "Tatooine", } Vader = StarWarsChar{ Id: "1001", Name: "Darth Vader", AppearsIn: []int{4, 5, 6}, HomePlanet: "Tatooine", } Han = StarWarsChar{ Id: "1002", Name: "Han Solo", AppearsIn: []int{4, 5, 6}, } Leia = StarWarsChar{ Id: "1003", Name: "Leia Organa", AppearsIn: []int{4, 5, 6}, HomePlanet: "Alderaa", } Tarkin = StarWarsChar{ Id: "1004", Name: "Wilhuff Tarkin", AppearsIn: []int{4}, } Threepio = StarWarsChar{ Id: "2000", Name: "C-3PO", AppearsIn: []int{4, 5, 6}, PrimaryFunction: "Protocol", } Artoo = StarWarsChar{ Id: "2001", Name: "R2-D2", AppearsIn: []int{4, 5, 6}, PrimaryFunction: "Astromech", } Luke.Friends = append(Luke.Friends, []StarWarsChar{Han, Leia, Threepio, Artoo}...) Vader.Friends = append(Luke.Friends, []StarWarsChar{Tarkin}...) Han.Friends = append(Han.Friends, []StarWarsChar{Luke, Leia, Artoo}...) Leia.Friends = append(Leia.Friends, []StarWarsChar{Luke, Han, Threepio, Artoo}...) Tarkin.Friends = append(Tarkin.Friends, []StarWarsChar{Vader}...) Threepio.Friends = append(Threepio.Friends, []StarWarsChar{Luke, Han, Leia, Artoo}...) Artoo.Friends = append(Artoo.Friends, []StarWarsChar{Luke, Han, Leia}...) HumanData = map[int]StarWarsChar{ 1000: Luke, 1001: Vader, 1002: Han, 1003: Leia, 1004: Tarkin, } DroidData = map[int]StarWarsChar{ 2000: Threepio, 2001: Artoo, } episodeEnum := types.NewGraphQLEnumType(types.GraphQLEnumTypeConfig{ Name: "Episode", Description: "One of the films in the Star Wars Trilogy", Values: types.GraphQLEnumValueConfigMap{ "NEWHOPE": &types.GraphQLEnumValueConfig{ Value: 4, Description: "Released in 1977.", }, "EMPIRE": &types.GraphQLEnumValueConfig{ Value: 5, Description: "Released in 1980.", }, "JEDI": &types.GraphQLEnumValueConfig{ Value: 6, Description: "Released in 1983.", }, }, }) characterInterface := types.NewGraphQLInterfaceType(types.GraphQLInterfaceTypeConfig{ Name: "Character", Description: "A character in the Star Wars Trilogy", Fields: types.GraphQLFieldConfigMap{ "id": &types.GraphQLFieldConfig{ Type: types.NewGraphQLNonNull(types.GraphQLString), Description: "The id of the character.", }, "name": &types.GraphQLFieldConfig{ Type: types.GraphQLString, Description: "The name of the character.", }, "appearsIn": &types.GraphQLFieldConfig{ Type: types.NewGraphQLList(episodeEnum), Description: "Which movies they appear in.", }, }, ResolveType: func(value interface{}, info types.GraphQLResolveInfo) *types.GraphQLObjectType { if character, ok := value.(StarWarsChar); ok { id, _ := strconv.Atoi(character.Id) human := GetHuman(id) if human.Id != "" { return humanType } } return droidType }, }) characterInterface.AddFieldConfig("friends", &types.GraphQLFieldConfig{ Type: types.NewGraphQLList(characterInterface), Description: "The friends of the character, or an empty list if they have none.", }) humanType = types.NewGraphQLObjectType(types.GraphQLObjectTypeConfig{ Name: "Human", Description: "A humanoid creature in the Star Wars universe.", Fields: types.GraphQLFieldConfigMap{ "id": &types.GraphQLFieldConfig{ Type: types.NewGraphQLNonNull(types.GraphQLString), Description: "The id of the human.", Resolve: func(ctx context.Context, p types.GQLFRParams) interface{} { if human, ok := p.Source.(StarWarsChar); ok { return human.Id } return nil }, }, "name": &types.GraphQLFieldConfig{ Type: types.GraphQLString, Description: "The name of the human.", Resolve: func(ctx context.Context, p types.GQLFRParams) interface{} { if human, ok := p.Source.(StarWarsChar); ok { return human.Name } return nil }, }, "friends": &types.GraphQLFieldConfig{ Type: types.NewGraphQLList(characterInterface), Description: "The friends of the human, or an empty list if they have none.", Resolve: func(ctx context.Context, p types.GQLFRParams) interface{} { if human, ok := p.Source.(StarWarsChar); ok { return human.Friends } return []interface{}{} }, }, "appearsIn": &types.GraphQLFieldConfig{ Type: types.NewGraphQLList(episodeEnum), Description: "Which movies they appear in.", Resolve: func(ctx context.Context, p types.GQLFRParams) interface{} { if human, ok := p.Source.(StarWarsChar); ok { return human.AppearsIn } return nil }, }, "homePlanet": &types.GraphQLFieldConfig{ Type: types.GraphQLString, Description: "The home planet of the human, or null if unknown.", Resolve: func(ctx context.Context, p types.GQLFRParams) interface{} { if human, ok := p.Source.(StarWarsChar); ok { return human.HomePlanet } return nil }, }, }, Interfaces: []*types.GraphQLInterfaceType{ characterInterface, }, }) droidType = types.NewGraphQLObjectType(types.GraphQLObjectTypeConfig{ Name: "Droid", Description: "A mechanical creature in the Star Wars universe.", Fields: types.GraphQLFieldConfigMap{ "id": &types.GraphQLFieldConfig{ Type: types.NewGraphQLNonNull(types.GraphQLString), Description: "The id of the droid.", Resolve: func(ctx context.Context, p types.GQLFRParams) interface{} { if droid, ok := p.Source.(StarWarsChar); ok { return droid.Id } return nil }, }, "name": &types.GraphQLFieldConfig{ Type: types.GraphQLString, Description: "The name of the droid.", Resolve: func(ctx context.Context, p types.GQLFRParams) interface{} { if droid, ok := p.Source.(StarWarsChar); ok { return droid.Name } return nil }, }, "friends": &types.GraphQLFieldConfig{ Type: types.NewGraphQLList(characterInterface), Description: "The friends of the droid, or an empty list if they have none.", Resolve: func(ctx context.Context, p types.GQLFRParams) interface{} { if droid, ok := p.Source.(StarWarsChar); ok { friends := []map[string]interface{}{} for _, friend := range droid.Friends { friends = append(friends, map[string]interface{}{ "name": friend.Name, "id": friend.Id, }) } return droid.Friends } return []interface{}{} }, }, "appearsIn": &types.GraphQLFieldConfig{ Type: types.NewGraphQLList(episodeEnum), Description: "Which movies they appear in.", Resolve: func(ctx context.Context, p types.GQLFRParams) interface{} { if droid, ok := p.Source.(StarWarsChar); ok { return droid.AppearsIn } return nil }, }, "primaryFunction": &types.GraphQLFieldConfig{ Type: types.GraphQLString, Description: "The primary function of the droid.", Resolve: func(ctx context.Context, p types.GQLFRParams) interface{} { if droid, ok := p.Source.(StarWarsChar); ok { return droid.PrimaryFunction } return nil }, }, }, Interfaces: []*types.GraphQLInterfaceType{ characterInterface, }, }) queryType := types.NewGraphQLObjectType(types.GraphQLObjectTypeConfig{ Name: "Query", Fields: types.GraphQLFieldConfigMap{ "hero": &types.GraphQLFieldConfig{ Type: characterInterface, Args: types.GraphQLFieldConfigArgumentMap{ "episode": &types.GraphQLArgumentConfig{ Description: "If omitted, returns the hero of the whole saga. If " + "provided, returns the hero of that particular episode.", Type: episodeEnum, }, }, Resolve: func(ctx context.Context, p types.GQLFRParams) (r interface{}) { return GetHero(p.Args["episode"]) }, }, "human": &types.GraphQLFieldConfig{ Type: humanType, Args: types.GraphQLFieldConfigArgumentMap{ "id": &types.GraphQLArgumentConfig{ Description: "id of the human", Type: types.NewGraphQLNonNull(types.GraphQLString), }, }, Resolve: func(ctx context.Context, p types.GQLFRParams) (r interface{}) { return GetHuman(p.Args["id"].(int)) }, }, "droid": &types.GraphQLFieldConfig{ Type: droidType, Args: types.GraphQLFieldConfigArgumentMap{ "id": &types.GraphQLArgumentConfig{ Description: "id of the droid", Type: types.NewGraphQLNonNull(types.GraphQLString), }, }, Resolve: func(ctx context.Context, p types.GQLFRParams) (r interface{}) { return GetDroid(p.Args["id"].(int)) }, }, }, }) StarWarsSchema, _ = types.NewGraphQLSchema(types.GraphQLSchemaConfig{ Query: queryType, }) }
}, }, }) var blogQuery = types.NewGraphQLObjectType(types.GraphQLObjectTypeConfig{ Name: "Query", Fields: types.GraphQLFieldConfigMap{ "article": &types.GraphQLFieldConfig{ Type: blogArticle, Args: types.GraphQLFieldConfigArgumentMap{ "id": &types.GraphQLArgumentConfig{ Type: types.GraphQLString, }, }, }, "feed": &types.GraphQLFieldConfig{ Type: types.NewGraphQLList(blogArticle), }, }, }) var blogMutation = types.NewGraphQLObjectType(types.GraphQLObjectTypeConfig{ Name: "Mutation", Fields: types.GraphQLFieldConfigMap{ "writeArticle": &types.GraphQLFieldConfig{ Type: blogArticle, }, }, }) var objectType = types.NewGraphQLObjectType(types.GraphQLObjectTypeConfig{ Name: "Object",
func TestResolveTypeOnUnionYieldsUsefulError(t *testing.T) { humanType := types.NewGraphQLObjectType(types.GraphQLObjectTypeConfig{ Name: "Human", Fields: types.GraphQLFieldConfigMap{ "name": &types.GraphQLFieldConfig{ Type: types.GraphQLString, Resolve: func(p types.GQLFRParams) interface{} { if human, ok := p.Source.(*testHuman); ok { return human.Name } return nil }, }, }, }) dogType := types.NewGraphQLObjectType(types.GraphQLObjectTypeConfig{ Name: "Dog", IsTypeOf: func(value interface{}, info types.GraphQLResolveInfo) bool { _, ok := value.(*testDog) return ok }, Fields: types.GraphQLFieldConfigMap{ "name": &types.GraphQLFieldConfig{ Type: types.GraphQLString, Resolve: func(p types.GQLFRParams) interface{} { if dog, ok := p.Source.(*testDog); ok { return dog.Name } return nil }, }, "woofs": &types.GraphQLFieldConfig{ Type: types.GraphQLBoolean, Resolve: func(p types.GQLFRParams) interface{} { if dog, ok := p.Source.(*testDog); ok { return dog.Woofs } return nil }, }, }, }) catType := types.NewGraphQLObjectType(types.GraphQLObjectTypeConfig{ Name: "Cat", IsTypeOf: func(value interface{}, info types.GraphQLResolveInfo) bool { _, ok := value.(*testCat) return ok }, Fields: types.GraphQLFieldConfigMap{ "name": &types.GraphQLFieldConfig{ Type: types.GraphQLString, Resolve: func(p types.GQLFRParams) interface{} { if cat, ok := p.Source.(*testCat); ok { return cat.Name } return nil }, }, "meows": &types.GraphQLFieldConfig{ Type: types.GraphQLBoolean, Resolve: func(p types.GQLFRParams) interface{} { if cat, ok := p.Source.(*testCat); ok { return cat.Meows } return nil }, }, }, }) petType := types.NewGraphQLUnionType(types.GraphQLUnionTypeConfig{ Name: "Pet", Types: []*types.GraphQLObjectType{ dogType, catType, }, ResolveType: func(value interface{}, info types.GraphQLResolveInfo) *types.GraphQLObjectType { if _, ok := value.(*testCat); ok { return catType } if _, ok := value.(*testDog); ok { return dogType } if _, ok := value.(*testHuman); ok { return humanType } return nil }, }) schema, err := types.NewGraphQLSchema(types.GraphQLSchemaConfig{ Query: types.NewGraphQLObjectType(types.GraphQLObjectTypeConfig{ Name: "Query", Fields: types.GraphQLFieldConfigMap{ "pets": &types.GraphQLFieldConfig{ Type: types.NewGraphQLList(petType), Resolve: func(p types.GQLFRParams) interface{} { return []interface{}{ &testDog{"Odie", true}, &testCat{"Garfield", false}, &testHuman{"Jon"}, } }, }, }, }), }) if err != nil { t.Fatalf("Error in schema %v", err.Error()) } query := `{ pets { name ... on Dog { woofs } ... on Cat { meows } } }` expected := &types.GraphQLResult{ Data: map[string]interface{}{ "pets": []interface{}{ map[string]interface{}{ "name": "Odie", "woofs": bool(true), }, map[string]interface{}{ "name": "Garfield", "meows": bool(false), }, nil, }, }, Errors: []graphqlerrors.GraphQLFormattedError{ graphqlerrors.GraphQLFormattedError{ Message: `Runtime Object type "Human" is not a possible type for "Pet".`, Locations: []location.SourceLocation{}, }, }, } resultChannel := make(chan *types.GraphQLResult) go gql.Graphql(gql.GraphqlParams{ Schema: schema, RequestString: query, }, resultChannel) result := <-resultChannel if len(result.Errors) == 0 { t.Fatalf("wrong result, expected errors: %v, got: %v", len(expected.Errors), len(result.Errors)) } if !reflect.DeepEqual(expected, result) { t.Fatalf("Unexpected result, Diff: %v", testutil.Diff(expected, result)) } }
func TestIsTypeOfUsedToResolveRuntimeTypeForInterface(t *testing.T) { petType := types.NewGraphQLInterfaceType(types.GraphQLInterfaceTypeConfig{ Name: "Pet", Fields: types.GraphQLFieldConfigMap{ "name": &types.GraphQLFieldConfig{ Type: types.GraphQLString, }, }, }) // ie declare that Dog belongs to Pet interface _ = types.NewGraphQLObjectType(types.GraphQLObjectTypeConfig{ Name: "Dog", Interfaces: []*types.GraphQLInterfaceType{ petType, }, IsTypeOf: func(value interface{}, info types.GraphQLResolveInfo) bool { _, ok := value.(*testDog) return ok }, Fields: types.GraphQLFieldConfigMap{ "name": &types.GraphQLFieldConfig{ Type: types.GraphQLString, Resolve: func(p types.GQLFRParams) interface{} { if dog, ok := p.Source.(*testDog); ok { return dog.Name } return nil }, }, "woofs": &types.GraphQLFieldConfig{ Type: types.GraphQLBoolean, Resolve: func(p types.GQLFRParams) interface{} { if dog, ok := p.Source.(*testDog); ok { return dog.Woofs } return nil }, }, }, }) // ie declare that Cat belongs to Pet interface _ = types.NewGraphQLObjectType(types.GraphQLObjectTypeConfig{ Name: "Cat", Interfaces: []*types.GraphQLInterfaceType{ petType, }, IsTypeOf: func(value interface{}, info types.GraphQLResolveInfo) bool { _, ok := value.(*testCat) return ok }, Fields: types.GraphQLFieldConfigMap{ "name": &types.GraphQLFieldConfig{ Type: types.GraphQLString, Resolve: func(p types.GQLFRParams) interface{} { if cat, ok := p.Source.(*testCat); ok { return cat.Name } return nil }, }, "meows": &types.GraphQLFieldConfig{ Type: types.GraphQLBoolean, Resolve: func(p types.GQLFRParams) interface{} { if cat, ok := p.Source.(*testCat); ok { return cat.Meows } return nil }, }, }, }) schema, err := types.NewGraphQLSchema(types.GraphQLSchemaConfig{ Query: types.NewGraphQLObjectType(types.GraphQLObjectTypeConfig{ Name: "Query", Fields: types.GraphQLFieldConfigMap{ "pets": &types.GraphQLFieldConfig{ Type: types.NewGraphQLList(petType), Resolve: func(p types.GQLFRParams) interface{} { return []interface{}{ &testDog{"Odie", true}, &testCat{"Garfield", false}, } }, }, }, }), }) if err != nil { t.Fatalf("Error in schema %v", err.Error()) } query := `{ pets { name ... on Dog { woofs } ... on Cat { meows } } }` expected := &types.GraphQLResult{ Data: map[string]interface{}{ "pets": []interface{}{ map[string]interface{}{ "name": "Odie", "woofs": bool(true), }, map[string]interface{}{ "name": "Garfield", "meows": bool(false), }, }, }, Errors: nil, } resultChannel := make(chan *types.GraphQLResult) go gql.Graphql(gql.GraphqlParams{ Schema: schema, RequestString: query, }, resultChannel) result := <-resultChannel if len(result.Errors) != 0 { t.Fatalf("wrong result, unexpected errors: %v", result.Errors) } if !reflect.DeepEqual(expected, result) { t.Fatalf("Unexpected result, Diff: %v", testutil.Diff(expected, result)) } }
astValue := valueAST.GetValue() if astValue, ok := astValue.(string); ok && astValue == "SerializedValue" { return "DeserializedValue" } return nil }, }) var testInputObject *types.GraphQLInputObjectType = types.NewGraphQLInputObjectType(types.InputObjectConfig{ Name: "TestInputObject", Fields: types.InputObjectConfigFieldMap{ "a": &types.InputObjectFieldConfig{ Type: types.GraphQLString, }, "b": &types.InputObjectFieldConfig{ Type: types.NewGraphQLList(types.GraphQLString), }, "c": &types.InputObjectFieldConfig{ Type: types.NewGraphQLNonNull(types.GraphQLString), }, "d": &types.InputObjectFieldConfig{ Type: testComplexScalar, }, }, }) func inputResolved(p types.GQLFRParams) interface{} { input, ok := p.Args["input"] if !ok { return nil }