mirror of
https://github.com/dolthub/dolt.git
synced 2026-02-11 18:49:14 -06:00
1696 lines
38 KiB
Go
1696 lines
38 KiB
Go
package graphql_test
|
|
|
|
import (
|
|
"encoding/json"
|
|
"errors"
|
|
"fmt"
|
|
"reflect"
|
|
"testing"
|
|
"time"
|
|
|
|
"github.com/attic-labs/graphql"
|
|
"github.com/attic-labs/graphql/gqlerrors"
|
|
"github.com/attic-labs/graphql/language/location"
|
|
"github.com/attic-labs/graphql/testutil"
|
|
"golang.org/x/net/context"
|
|
)
|
|
|
|
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 := &graphql.Result{
|
|
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(p graphql.ResolveParams) (interface{}, error) {
|
|
// get and type assert ResolveFn for this field
|
|
picResolver, ok := p.Source.(map[string]interface{})["pic"].(func(size int) string)
|
|
if !ok {
|
|
return nil, nil
|
|
}
|
|
// get and type assert argument
|
|
sizeArg, ok := p.Args["size"].(int)
|
|
if !ok {
|
|
return nil, nil
|
|
}
|
|
return picResolver(sizeArg), nil
|
|
}
|
|
dataType := graphql.NewObject(graphql.ObjectConfig{
|
|
Name: "DataType",
|
|
Fields: graphql.Fields{
|
|
"a": &graphql.Field{
|
|
Type: graphql.String,
|
|
},
|
|
"b": &graphql.Field{
|
|
Type: graphql.String,
|
|
},
|
|
"c": &graphql.Field{
|
|
Type: graphql.String,
|
|
},
|
|
"d": &graphql.Field{
|
|
Type: graphql.String,
|
|
},
|
|
"e": &graphql.Field{
|
|
Type: graphql.String,
|
|
},
|
|
"f": &graphql.Field{
|
|
Type: graphql.String,
|
|
},
|
|
"pic": &graphql.Field{
|
|
Args: graphql.FieldConfigArgument{
|
|
"size": &graphql.ArgumentConfig{
|
|
Type: graphql.Int,
|
|
},
|
|
},
|
|
Type: graphql.String,
|
|
Resolve: picResolverFn,
|
|
},
|
|
},
|
|
})
|
|
deepDataType := graphql.NewObject(graphql.ObjectConfig{
|
|
Name: "DeepDataType",
|
|
Fields: graphql.Fields{
|
|
"a": &graphql.Field{
|
|
Type: graphql.String,
|
|
},
|
|
"b": &graphql.Field{
|
|
Type: graphql.String,
|
|
},
|
|
"c": &graphql.Field{
|
|
Type: graphql.NewList(graphql.String),
|
|
},
|
|
"deeper": &graphql.Field{
|
|
Type: graphql.NewList(dataType),
|
|
},
|
|
},
|
|
})
|
|
|
|
// Exploring a way to have a Object within itself
|
|
// in this case DataType has DeepDataType has DataType
|
|
dataType.AddFieldConfig("deep", &graphql.Field{
|
|
Type: deepDataType,
|
|
})
|
|
// in this case DataType has DataType
|
|
dataType.AddFieldConfig("promise", &graphql.Field{
|
|
Type: dataType,
|
|
})
|
|
|
|
schema, err := graphql.NewSchema(graphql.SchemaConfig{
|
|
Query: dataType,
|
|
})
|
|
if err != nil {
|
|
t.Fatalf("Error in schema %v", err.Error())
|
|
}
|
|
|
|
// parse query
|
|
astDoc := testutil.TestParse(t, query)
|
|
|
|
// execute
|
|
args := map[string]interface{}{
|
|
"size": 100,
|
|
}
|
|
operationName := "Example"
|
|
ep := graphql.ExecuteParams{
|
|
Schema: schema,
|
|
Root: data,
|
|
AST: astDoc,
|
|
OperationName: operationName,
|
|
Args: args,
|
|
}
|
|
result := testutil.TestExecute(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 TestMergesParallelFragments(t *testing.T) {
|
|
|
|
query := `
|
|
{ a, ...FragOne, ...FragTwo }
|
|
|
|
fragment FragOne on Type {
|
|
b
|
|
deep { b, deeper: deep { b } }
|
|
}
|
|
|
|
fragment FragTwo on Type {
|
|
c
|
|
deep { c, deeper: deep { c } }
|
|
}
|
|
`
|
|
|
|
expected := &graphql.Result{
|
|
Data: map[string]interface{}{
|
|
"a": "Apple",
|
|
"b": "Banana",
|
|
"deep": map[string]interface{}{
|
|
"c": "Cherry",
|
|
"b": "Banana",
|
|
"deeper": map[string]interface{}{
|
|
"b": "Banana",
|
|
"c": "Cherry",
|
|
},
|
|
},
|
|
"c": "Cherry",
|
|
},
|
|
}
|
|
|
|
typeObjectType := graphql.NewObject(graphql.ObjectConfig{
|
|
Name: "Type",
|
|
Fields: graphql.Fields{
|
|
"a": &graphql.Field{
|
|
Type: graphql.String,
|
|
Resolve: func(p graphql.ResolveParams) (interface{}, error) {
|
|
return "Apple", nil
|
|
},
|
|
},
|
|
"b": &graphql.Field{
|
|
Type: graphql.String,
|
|
Resolve: func(p graphql.ResolveParams) (interface{}, error) {
|
|
return "Banana", nil
|
|
},
|
|
},
|
|
"c": &graphql.Field{
|
|
Type: graphql.String,
|
|
Resolve: func(p graphql.ResolveParams) (interface{}, error) {
|
|
return "Cherry", nil
|
|
},
|
|
},
|
|
},
|
|
})
|
|
deepTypeFieldConfig := &graphql.Field{
|
|
Type: typeObjectType,
|
|
Resolve: func(p graphql.ResolveParams) (interface{}, error) {
|
|
return p.Source, nil
|
|
},
|
|
}
|
|
typeObjectType.AddFieldConfig("deep", deepTypeFieldConfig)
|
|
|
|
schema, err := graphql.NewSchema(graphql.SchemaConfig{
|
|
Query: typeObjectType,
|
|
})
|
|
if err != nil {
|
|
t.Fatalf("Error in schema %v", err.Error())
|
|
}
|
|
|
|
// parse query
|
|
ast := testutil.TestParse(t, query)
|
|
|
|
// execute
|
|
ep := graphql.ExecuteParams{
|
|
Schema: schema,
|
|
AST: ast,
|
|
}
|
|
result := testutil.TestExecute(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 TestThreadsSourceCorrectly(t *testing.T) {
|
|
|
|
query := `
|
|
query Example { a }
|
|
`
|
|
|
|
data := map[string]interface{}{
|
|
"key": "value",
|
|
}
|
|
|
|
var resolvedSource map[string]interface{}
|
|
|
|
schema, err := graphql.NewSchema(graphql.SchemaConfig{
|
|
Query: graphql.NewObject(graphql.ObjectConfig{
|
|
Name: "Type",
|
|
Fields: graphql.Fields{
|
|
"a": &graphql.Field{
|
|
Type: graphql.String,
|
|
Resolve: func(p graphql.ResolveParams) (interface{}, error) {
|
|
resolvedSource = p.Source.(map[string]interface{})
|
|
return resolvedSource, nil
|
|
},
|
|
},
|
|
},
|
|
}),
|
|
})
|
|
if err != nil {
|
|
t.Fatalf("Error in schema %v", err.Error())
|
|
}
|
|
|
|
// parse query
|
|
ast := testutil.TestParse(t, query)
|
|
|
|
// execute
|
|
ep := graphql.ExecuteParams{
|
|
Schema: schema,
|
|
Root: data,
|
|
AST: ast,
|
|
}
|
|
result := testutil.TestExecute(t, ep)
|
|
if len(result.Errors) > 0 {
|
|
t.Fatalf("wrong result, unexpected errors: %v", result.Errors)
|
|
}
|
|
|
|
expected := "value"
|
|
if resolvedSource["key"] != expected {
|
|
t.Fatalf("Expected context.key to equal %v, got %v", expected, resolvedSource["key"])
|
|
}
|
|
}
|
|
|
|
func TestCorrectlyThreadsArguments(t *testing.T) {
|
|
|
|
query := `
|
|
query Example {
|
|
b(numArg: 123, stringArg: "foo")
|
|
}
|
|
`
|
|
|
|
var resolvedArgs map[string]interface{}
|
|
|
|
schema, err := graphql.NewSchema(graphql.SchemaConfig{
|
|
Query: graphql.NewObject(graphql.ObjectConfig{
|
|
Name: "Type",
|
|
Fields: graphql.Fields{
|
|
"b": &graphql.Field{
|
|
Args: graphql.FieldConfigArgument{
|
|
"numArg": &graphql.ArgumentConfig{
|
|
Type: graphql.Int,
|
|
},
|
|
"stringArg": &graphql.ArgumentConfig{
|
|
Type: graphql.String,
|
|
},
|
|
},
|
|
Type: graphql.String,
|
|
Resolve: func(p graphql.ResolveParams) (interface{}, error) {
|
|
resolvedArgs = p.Args
|
|
return resolvedArgs, nil
|
|
},
|
|
},
|
|
},
|
|
}),
|
|
})
|
|
if err != nil {
|
|
t.Fatalf("Error in schema %v", err.Error())
|
|
}
|
|
|
|
// parse query
|
|
ast := testutil.TestParse(t, query)
|
|
|
|
// execute
|
|
ep := graphql.ExecuteParams{
|
|
Schema: schema,
|
|
AST: ast,
|
|
}
|
|
result := testutil.TestExecute(t, ep)
|
|
if len(result.Errors) > 0 {
|
|
t.Fatalf("wrong result, unexpected errors: %v", result.Errors)
|
|
}
|
|
|
|
expectedNum := 123
|
|
expectedString := "foo"
|
|
if resolvedArgs["numArg"] != expectedNum {
|
|
t.Fatalf("Expected args.numArg to equal `%v`, got `%v`", expectedNum, resolvedArgs["numArg"])
|
|
}
|
|
if resolvedArgs["stringArg"] != expectedString {
|
|
t.Fatalf("Expected args.stringArg to equal `%v`, got `%v`", expectedNum, resolvedArgs["stringArg"])
|
|
}
|
|
}
|
|
|
|
func TestThreadsRootValueContextCorrectly(t *testing.T) {
|
|
|
|
query := `
|
|
query Example { a }
|
|
`
|
|
|
|
schema, err := graphql.NewSchema(graphql.SchemaConfig{
|
|
Query: graphql.NewObject(graphql.ObjectConfig{
|
|
Name: "Type",
|
|
Fields: graphql.Fields{
|
|
"a": &graphql.Field{
|
|
Type: graphql.String,
|
|
Resolve: func(p graphql.ResolveParams) (interface{}, error) {
|
|
val, _ := p.Info.RootValue.(map[string]interface{})["stringKey"].(string)
|
|
return val, nil
|
|
},
|
|
},
|
|
},
|
|
}),
|
|
})
|
|
if err != nil {
|
|
t.Fatalf("Error in schema %v", err.Error())
|
|
}
|
|
|
|
// parse query
|
|
ast := testutil.TestParse(t, query)
|
|
|
|
// execute
|
|
ep := graphql.ExecuteParams{
|
|
Schema: schema,
|
|
AST: ast,
|
|
Root: map[string]interface{}{
|
|
"stringKey": "stringValue",
|
|
},
|
|
}
|
|
result := testutil.TestExecute(t, ep)
|
|
if len(result.Errors) > 0 {
|
|
t.Fatalf("wrong result, unexpected errors: %v", result.Errors)
|
|
}
|
|
|
|
expected := &graphql.Result{
|
|
Data: map[string]interface{}{
|
|
"a": "stringValue",
|
|
},
|
|
}
|
|
if !reflect.DeepEqual(expected, result) {
|
|
t.Fatalf("Unexpected result, Diff: %v", testutil.Diff(expected, result))
|
|
}
|
|
}
|
|
|
|
func TestThreadsContextCorrectly(t *testing.T) {
|
|
|
|
query := `
|
|
query Example { a }
|
|
`
|
|
|
|
schema, err := graphql.NewSchema(graphql.SchemaConfig{
|
|
Query: graphql.NewObject(graphql.ObjectConfig{
|
|
Name: "Type",
|
|
Fields: graphql.Fields{
|
|
"a": &graphql.Field{
|
|
Type: graphql.String,
|
|
Resolve: func(p graphql.ResolveParams) (interface{}, error) {
|
|
return p.Context.Value("foo"), nil
|
|
},
|
|
},
|
|
},
|
|
}),
|
|
})
|
|
if err != nil {
|
|
t.Fatalf("Error in schema %v", err.Error())
|
|
}
|
|
|
|
// parse query
|
|
ast := testutil.TestParse(t, query)
|
|
|
|
// execute
|
|
ep := graphql.ExecuteParams{
|
|
Schema: schema,
|
|
AST: ast,
|
|
Context: context.WithValue(context.Background(), "foo", "bar"),
|
|
}
|
|
result := testutil.TestExecute(t, ep)
|
|
if len(result.Errors) > 0 {
|
|
t.Fatalf("wrong result, unexpected errors: %v", result.Errors)
|
|
}
|
|
|
|
expected := &graphql.Result{
|
|
Data: map[string]interface{}{
|
|
"a": "bar",
|
|
},
|
|
}
|
|
if !reflect.DeepEqual(expected, result) {
|
|
t.Fatalf("Unexpected result, Diff: %v", testutil.Diff(expected, result))
|
|
}
|
|
}
|
|
|
|
func TestNullsOutErrorSubtrees(t *testing.T) {
|
|
|
|
// TODO: TestNullsOutErrorSubtrees test for go-routines if implemented
|
|
query := `{
|
|
sync,
|
|
syncError,
|
|
}`
|
|
|
|
expectedData := map[string]interface{}{
|
|
"sync": "sync",
|
|
"syncError": nil,
|
|
}
|
|
expectedErrors := []gqlerrors.FormattedError{
|
|
{
|
|
Message: "Error getting syncError",
|
|
Locations: []location.SourceLocation{
|
|
{
|
|
Line: 3, Column: 7,
|
|
},
|
|
},
|
|
},
|
|
}
|
|
|
|
data := map[string]interface{}{
|
|
"sync": func() interface{} {
|
|
return "sync"
|
|
},
|
|
"syncError": func() interface{} {
|
|
panic("Error getting syncError")
|
|
},
|
|
}
|
|
schema, err := graphql.NewSchema(graphql.SchemaConfig{
|
|
Query: graphql.NewObject(graphql.ObjectConfig{
|
|
Name: "Type",
|
|
Fields: graphql.Fields{
|
|
"sync": &graphql.Field{
|
|
Type: graphql.String,
|
|
},
|
|
"syncError": &graphql.Field{
|
|
Type: graphql.String,
|
|
},
|
|
},
|
|
}),
|
|
})
|
|
if err != nil {
|
|
t.Fatalf("Error in schema %v", err.Error())
|
|
}
|
|
|
|
// parse query
|
|
ast := testutil.TestParse(t, query)
|
|
|
|
// execute
|
|
ep := graphql.ExecuteParams{
|
|
Schema: schema,
|
|
AST: ast,
|
|
Root: data,
|
|
}
|
|
result := testutil.TestExecute(t, ep)
|
|
if len(result.Errors) == 0 {
|
|
t.Fatalf("wrong result, expected errors, got %v", len(result.Errors))
|
|
}
|
|
if !reflect.DeepEqual(expectedData, result.Data) {
|
|
t.Fatalf("Unexpected result, Diff: %v", testutil.Diff(expectedData, result.Data))
|
|
}
|
|
if !reflect.DeepEqual(expectedErrors, result.Errors) {
|
|
t.Fatalf("Unexpected result, Diff: %v", testutil.Diff(expectedErrors, result.Errors))
|
|
}
|
|
}
|
|
|
|
func TestUsesTheInlineOperationIfNoOperationNameIsProvided(t *testing.T) {
|
|
|
|
doc := `{ a }`
|
|
data := map[string]interface{}{
|
|
"a": "b",
|
|
}
|
|
|
|
expected := &graphql.Result{
|
|
Data: map[string]interface{}{
|
|
"a": "b",
|
|
},
|
|
}
|
|
|
|
schema, err := graphql.NewSchema(graphql.SchemaConfig{
|
|
Query: graphql.NewObject(graphql.ObjectConfig{
|
|
Name: "Type",
|
|
Fields: graphql.Fields{
|
|
"a": &graphql.Field{
|
|
Type: graphql.String,
|
|
},
|
|
},
|
|
}),
|
|
})
|
|
if err != nil {
|
|
t.Fatalf("Error in schema %v", err.Error())
|
|
}
|
|
|
|
// parse query
|
|
ast := testutil.TestParse(t, doc)
|
|
|
|
// execute
|
|
ep := graphql.ExecuteParams{
|
|
Schema: schema,
|
|
AST: ast,
|
|
Root: data,
|
|
}
|
|
result := testutil.TestExecute(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 TestUsesTheOnlyOperationIfNoOperationNameIsProvided(t *testing.T) {
|
|
|
|
doc := `query Example { a }`
|
|
data := map[string]interface{}{
|
|
"a": "b",
|
|
}
|
|
|
|
expected := &graphql.Result{
|
|
Data: map[string]interface{}{
|
|
"a": "b",
|
|
},
|
|
}
|
|
|
|
schema, err := graphql.NewSchema(graphql.SchemaConfig{
|
|
Query: graphql.NewObject(graphql.ObjectConfig{
|
|
Name: "Type",
|
|
Fields: graphql.Fields{
|
|
"a": &graphql.Field{
|
|
Type: graphql.String,
|
|
},
|
|
},
|
|
}),
|
|
})
|
|
if err != nil {
|
|
t.Fatalf("Error in schema %v", err.Error())
|
|
}
|
|
|
|
// parse query
|
|
ast := testutil.TestParse(t, doc)
|
|
|
|
// execute
|
|
ep := graphql.ExecuteParams{
|
|
Schema: schema,
|
|
AST: ast,
|
|
Root: data,
|
|
}
|
|
result := testutil.TestExecute(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 TestUsesTheNamedOperationIfOperationNameIsProvided(t *testing.T) {
|
|
|
|
doc := `query Example { first: a } query OtherExample { second: a }`
|
|
data := map[string]interface{}{
|
|
"a": "b",
|
|
}
|
|
|
|
expected := &graphql.Result{
|
|
Data: map[string]interface{}{
|
|
"second": "b",
|
|
},
|
|
}
|
|
schema, err := graphql.NewSchema(graphql.SchemaConfig{
|
|
Query: graphql.NewObject(graphql.ObjectConfig{
|
|
Name: "Type",
|
|
Fields: graphql.Fields{
|
|
"a": &graphql.Field{
|
|
Type: graphql.String,
|
|
},
|
|
},
|
|
}),
|
|
})
|
|
if err != nil {
|
|
t.Fatalf("Error in schema %v", err.Error())
|
|
}
|
|
|
|
// parse query
|
|
ast := testutil.TestParse(t, doc)
|
|
|
|
// execute
|
|
ep := graphql.ExecuteParams{
|
|
Schema: schema,
|
|
AST: ast,
|
|
Root: data,
|
|
OperationName: "OtherExample",
|
|
}
|
|
result := testutil.TestExecute(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 TestThrowsIfNoOperationIsProvided(t *testing.T) {
|
|
|
|
doc := `fragment Example on Type { a }`
|
|
data := map[string]interface{}{
|
|
"a": "b",
|
|
}
|
|
|
|
expectedErrors := []gqlerrors.FormattedError{
|
|
{
|
|
Message: "Must provide an operation.",
|
|
Locations: []location.SourceLocation{},
|
|
},
|
|
}
|
|
|
|
schema, err := graphql.NewSchema(graphql.SchemaConfig{
|
|
Query: graphql.NewObject(graphql.ObjectConfig{
|
|
Name: "Type",
|
|
Fields: graphql.Fields{
|
|
"a": &graphql.Field{
|
|
Type: graphql.String,
|
|
},
|
|
},
|
|
}),
|
|
})
|
|
if err != nil {
|
|
t.Fatalf("Error in schema %v", err.Error())
|
|
}
|
|
|
|
// parse query
|
|
ast := testutil.TestParse(t, doc)
|
|
|
|
// execute
|
|
ep := graphql.ExecuteParams{
|
|
Schema: schema,
|
|
AST: ast,
|
|
Root: data,
|
|
}
|
|
result := testutil.TestExecute(t, ep)
|
|
if len(result.Errors) != 1 {
|
|
t.Fatalf("wrong result, expected len(1) unexpected len: %v", len(result.Errors))
|
|
}
|
|
if result.Data != nil {
|
|
t.Fatalf("wrong result, expected nil result.Data, got %v", result.Data)
|
|
}
|
|
if !reflect.DeepEqual(expectedErrors, result.Errors) {
|
|
t.Fatalf("unexpected result, Diff: %v", testutil.Diff(expectedErrors, result.Errors))
|
|
}
|
|
}
|
|
func TestThrowsIfNoOperationNameIsProvidedWithMultipleOperations(t *testing.T) {
|
|
|
|
doc := `query Example { a } query OtherExample { a }`
|
|
data := map[string]interface{}{
|
|
"a": "b",
|
|
}
|
|
|
|
expectedErrors := []gqlerrors.FormattedError{
|
|
{
|
|
Message: "Must provide operation name if query contains multiple operations.",
|
|
Locations: []location.SourceLocation{},
|
|
},
|
|
}
|
|
|
|
schema, err := graphql.NewSchema(graphql.SchemaConfig{
|
|
Query: graphql.NewObject(graphql.ObjectConfig{
|
|
Name: "Type",
|
|
Fields: graphql.Fields{
|
|
"a": &graphql.Field{
|
|
Type: graphql.String,
|
|
},
|
|
},
|
|
}),
|
|
})
|
|
if err != nil {
|
|
t.Fatalf("Error in schema %v", err.Error())
|
|
}
|
|
|
|
// parse query
|
|
ast := testutil.TestParse(t, doc)
|
|
|
|
// execute
|
|
ep := graphql.ExecuteParams{
|
|
Schema: schema,
|
|
AST: ast,
|
|
Root: data,
|
|
}
|
|
result := testutil.TestExecute(t, ep)
|
|
if len(result.Errors) != 1 {
|
|
t.Fatalf("wrong result, expected len(1) unexpected len: %v", len(result.Errors))
|
|
}
|
|
if result.Data != nil {
|
|
t.Fatalf("wrong result, expected nil result.Data, got %v", result.Data)
|
|
}
|
|
if !reflect.DeepEqual(expectedErrors, result.Errors) {
|
|
t.Fatalf("unexpected result, Diff: %v", testutil.Diff(expectedErrors, result.Errors))
|
|
}
|
|
}
|
|
|
|
func TestThrowsIfUnknownOperationNameIsProvided(t *testing.T) {
|
|
|
|
doc := `query Example { a } query OtherExample { a }`
|
|
data := map[string]interface{}{
|
|
"a": "b",
|
|
}
|
|
|
|
expectedErrors := []gqlerrors.FormattedError{
|
|
{
|
|
Message: `Unknown operation named "UnknownExample".`,
|
|
Locations: []location.SourceLocation{},
|
|
},
|
|
}
|
|
|
|
schema, err := graphql.NewSchema(graphql.SchemaConfig{
|
|
Query: graphql.NewObject(graphql.ObjectConfig{
|
|
Name: "Type",
|
|
Fields: graphql.Fields{
|
|
"a": &graphql.Field{
|
|
Type: graphql.String,
|
|
},
|
|
},
|
|
}),
|
|
})
|
|
if err != nil {
|
|
t.Fatalf("Error in schema %v", err.Error())
|
|
}
|
|
|
|
// parse query
|
|
ast := testutil.TestParse(t, doc)
|
|
|
|
// execute
|
|
ep := graphql.ExecuteParams{
|
|
Schema: schema,
|
|
AST: ast,
|
|
Root: data,
|
|
OperationName: "UnknownExample",
|
|
}
|
|
result := testutil.TestExecute(t, ep)
|
|
if result.Data != nil {
|
|
t.Fatalf("wrong result, expected nil result.Data, got %v", result.Data)
|
|
}
|
|
if !reflect.DeepEqual(expectedErrors, result.Errors) {
|
|
t.Fatalf("unexpected result, Diff: %v", testutil.Diff(expectedErrors, result.Errors))
|
|
}
|
|
}
|
|
func TestUsesTheQuerySchemaForQueries(t *testing.T) {
|
|
|
|
doc := `query Q { a } mutation M { c } subscription S { a }`
|
|
data := map[string]interface{}{
|
|
"a": "b",
|
|
"c": "d",
|
|
}
|
|
|
|
expected := &graphql.Result{
|
|
Data: map[string]interface{}{
|
|
"a": "b",
|
|
},
|
|
}
|
|
|
|
schema, err := graphql.NewSchema(graphql.SchemaConfig{
|
|
Query: graphql.NewObject(graphql.ObjectConfig{
|
|
Name: "Q",
|
|
Fields: graphql.Fields{
|
|
"a": &graphql.Field{
|
|
Type: graphql.String,
|
|
},
|
|
},
|
|
}),
|
|
Mutation: graphql.NewObject(graphql.ObjectConfig{
|
|
Name: "M",
|
|
Fields: graphql.Fields{
|
|
"c": &graphql.Field{
|
|
Type: graphql.String,
|
|
},
|
|
},
|
|
}),
|
|
Subscription: graphql.NewObject(graphql.ObjectConfig{
|
|
Name: "S",
|
|
Fields: graphql.Fields{
|
|
"a": &graphql.Field{
|
|
Type: graphql.String,
|
|
},
|
|
},
|
|
}),
|
|
})
|
|
if err != nil {
|
|
t.Fatalf("Error in schema %v", err.Error())
|
|
}
|
|
|
|
// parse query
|
|
ast := testutil.TestParse(t, doc)
|
|
|
|
// execute
|
|
ep := graphql.ExecuteParams{
|
|
Schema: schema,
|
|
AST: ast,
|
|
Root: data,
|
|
OperationName: "Q",
|
|
}
|
|
result := testutil.TestExecute(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 TestUsesTheMutationSchemaForMutations(t *testing.T) {
|
|
|
|
doc := `query Q { a } mutation M { c }`
|
|
data := map[string]interface{}{
|
|
"a": "b",
|
|
"c": "d",
|
|
}
|
|
|
|
expected := &graphql.Result{
|
|
Data: map[string]interface{}{
|
|
"c": "d",
|
|
},
|
|
}
|
|
|
|
schema, err := graphql.NewSchema(graphql.SchemaConfig{
|
|
Query: graphql.NewObject(graphql.ObjectConfig{
|
|
Name: "Q",
|
|
Fields: graphql.Fields{
|
|
"a": &graphql.Field{
|
|
Type: graphql.String,
|
|
},
|
|
},
|
|
}),
|
|
Mutation: graphql.NewObject(graphql.ObjectConfig{
|
|
Name: "M",
|
|
Fields: graphql.Fields{
|
|
"c": &graphql.Field{
|
|
Type: graphql.String,
|
|
},
|
|
},
|
|
}),
|
|
})
|
|
if err != nil {
|
|
t.Fatalf("Error in schema %v", err.Error())
|
|
}
|
|
|
|
// parse query
|
|
ast := testutil.TestParse(t, doc)
|
|
|
|
// execute
|
|
ep := graphql.ExecuteParams{
|
|
Schema: schema,
|
|
AST: ast,
|
|
Root: data,
|
|
OperationName: "M",
|
|
}
|
|
result := testutil.TestExecute(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 TestUsesTheSubscriptionSchemaForSubscriptions(t *testing.T) {
|
|
|
|
doc := `query Q { a } subscription S { a }`
|
|
data := map[string]interface{}{
|
|
"a": "b",
|
|
"c": "d",
|
|
}
|
|
|
|
expected := &graphql.Result{
|
|
Data: map[string]interface{}{
|
|
"a": "b",
|
|
},
|
|
}
|
|
|
|
schema, err := graphql.NewSchema(graphql.SchemaConfig{
|
|
Query: graphql.NewObject(graphql.ObjectConfig{
|
|
Name: "Q",
|
|
Fields: graphql.Fields{
|
|
"a": &graphql.Field{
|
|
Type: graphql.String,
|
|
},
|
|
},
|
|
}),
|
|
Subscription: graphql.NewObject(graphql.ObjectConfig{
|
|
Name: "S",
|
|
Fields: graphql.Fields{
|
|
"a": &graphql.Field{
|
|
Type: graphql.String,
|
|
},
|
|
},
|
|
}),
|
|
})
|
|
if err != nil {
|
|
t.Fatalf("Error in schema %v", err.Error())
|
|
}
|
|
|
|
// parse query
|
|
ast := testutil.TestParse(t, doc)
|
|
|
|
// execute
|
|
ep := graphql.ExecuteParams{
|
|
Schema: schema,
|
|
AST: ast,
|
|
Root: data,
|
|
OperationName: "S",
|
|
}
|
|
result := testutil.TestExecute(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 TestCorrectFieldOrderingDespiteExecutionOrder(t *testing.T) {
|
|
|
|
doc := `
|
|
{
|
|
b,
|
|
a,
|
|
c,
|
|
d,
|
|
e
|
|
}
|
|
`
|
|
data := map[string]interface{}{
|
|
"a": func() interface{} { return "a" },
|
|
"b": func() interface{} { return "b" },
|
|
"c": func() interface{} { return "c" },
|
|
"d": func() interface{} { return "d" },
|
|
"e": func() interface{} { return "e" },
|
|
}
|
|
|
|
expected := &graphql.Result{
|
|
Data: map[string]interface{}{
|
|
"a": "a",
|
|
"b": "b",
|
|
"c": "c",
|
|
"d": "d",
|
|
"e": "e",
|
|
},
|
|
}
|
|
|
|
schema, err := graphql.NewSchema(graphql.SchemaConfig{
|
|
Query: graphql.NewObject(graphql.ObjectConfig{
|
|
Name: "Type",
|
|
Fields: graphql.Fields{
|
|
"a": &graphql.Field{
|
|
Type: graphql.String,
|
|
},
|
|
"b": &graphql.Field{
|
|
Type: graphql.String,
|
|
},
|
|
"c": &graphql.Field{
|
|
Type: graphql.String,
|
|
},
|
|
"d": &graphql.Field{
|
|
Type: graphql.String,
|
|
},
|
|
"e": &graphql.Field{
|
|
Type: graphql.String,
|
|
},
|
|
},
|
|
}),
|
|
})
|
|
if err != nil {
|
|
t.Fatalf("Error in schema %v", err.Error())
|
|
}
|
|
|
|
// parse query
|
|
ast := testutil.TestParse(t, doc)
|
|
|
|
// execute
|
|
ep := graphql.ExecuteParams{
|
|
Schema: schema,
|
|
AST: ast,
|
|
Root: data,
|
|
}
|
|
result := testutil.TestExecute(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))
|
|
}
|
|
|
|
// TODO: test to ensure key ordering
|
|
// The following does not work
|
|
// - iterating over result.Data map
|
|
// Note that golang's map iteration order is randomized
|
|
// So, iterating over result.Data won't do it for a test
|
|
// - Marshal the result.Data to json string and assert it
|
|
// json.Marshal seems to re-sort the keys automatically
|
|
//
|
|
t.Skipf("TODO: Ensure key ordering")
|
|
}
|
|
|
|
func TestAvoidsRecursion(t *testing.T) {
|
|
|
|
doc := `
|
|
query Q {
|
|
a
|
|
...Frag
|
|
...Frag
|
|
}
|
|
|
|
fragment Frag on Type {
|
|
a,
|
|
...Frag
|
|
}
|
|
`
|
|
data := map[string]interface{}{
|
|
"a": "b",
|
|
}
|
|
|
|
expected := &graphql.Result{
|
|
Data: map[string]interface{}{
|
|
"a": "b",
|
|
},
|
|
}
|
|
|
|
schema, err := graphql.NewSchema(graphql.SchemaConfig{
|
|
Query: graphql.NewObject(graphql.ObjectConfig{
|
|
Name: "Type",
|
|
Fields: graphql.Fields{
|
|
"a": &graphql.Field{
|
|
Type: graphql.String,
|
|
},
|
|
},
|
|
}),
|
|
})
|
|
if err != nil {
|
|
t.Fatalf("Error in schema %v", err.Error())
|
|
}
|
|
|
|
// parse query
|
|
ast := testutil.TestParse(t, doc)
|
|
|
|
// execute
|
|
ep := graphql.ExecuteParams{
|
|
Schema: schema,
|
|
AST: ast,
|
|
Root: data,
|
|
OperationName: "Q",
|
|
}
|
|
result := testutil.TestExecute(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 TestDoesNotIncludeIllegalFieldsInOutput(t *testing.T) {
|
|
|
|
doc := `mutation M {
|
|
thisIsIllegalDontIncludeMe
|
|
}`
|
|
|
|
expected := &graphql.Result{
|
|
Data: map[string]interface{}{},
|
|
}
|
|
|
|
schema, err := graphql.NewSchema(graphql.SchemaConfig{
|
|
Query: graphql.NewObject(graphql.ObjectConfig{
|
|
Name: "Q",
|
|
Fields: graphql.Fields{
|
|
"a": &graphql.Field{
|
|
Type: graphql.String,
|
|
},
|
|
},
|
|
}),
|
|
Mutation: graphql.NewObject(graphql.ObjectConfig{
|
|
Name: "M",
|
|
Fields: graphql.Fields{
|
|
"c": &graphql.Field{
|
|
Type: graphql.String,
|
|
},
|
|
},
|
|
}),
|
|
})
|
|
if err != nil {
|
|
t.Fatalf("Error in schema %v", err.Error())
|
|
}
|
|
|
|
// parse query
|
|
ast := testutil.TestParse(t, doc)
|
|
|
|
// execute
|
|
ep := graphql.ExecuteParams{
|
|
Schema: schema,
|
|
AST: ast,
|
|
}
|
|
result := testutil.TestExecute(t, ep)
|
|
if len(result.Errors) != 0 {
|
|
t.Fatalf("wrong result, expected len(%v) errors, got len(%v)", len(expected.Errors), len(result.Errors))
|
|
}
|
|
if !reflect.DeepEqual(expected, result) {
|
|
t.Fatalf("Unexpected result, Diff: %v", testutil.Diff(expected, result))
|
|
}
|
|
}
|
|
|
|
func TestDoesNotIncludeArgumentsThatWereNotSet(t *testing.T) {
|
|
|
|
doc := `{ field(a: true, c: false, e: 0) }`
|
|
|
|
expected := &graphql.Result{
|
|
Data: map[string]interface{}{
|
|
"field": `{"a":true,"c":false,"e":0}`,
|
|
},
|
|
}
|
|
|
|
schema, err := graphql.NewSchema(graphql.SchemaConfig{
|
|
Query: graphql.NewObject(graphql.ObjectConfig{
|
|
Name: "Type",
|
|
Fields: graphql.Fields{
|
|
"field": &graphql.Field{
|
|
Type: graphql.String,
|
|
Args: graphql.FieldConfigArgument{
|
|
"a": &graphql.ArgumentConfig{
|
|
Type: graphql.Boolean,
|
|
},
|
|
"b": &graphql.ArgumentConfig{
|
|
Type: graphql.Boolean,
|
|
},
|
|
"c": &graphql.ArgumentConfig{
|
|
Type: graphql.Boolean,
|
|
},
|
|
"d": &graphql.ArgumentConfig{
|
|
Type: graphql.Int,
|
|
},
|
|
"e": &graphql.ArgumentConfig{
|
|
Type: graphql.Int,
|
|
},
|
|
},
|
|
Resolve: func(p graphql.ResolveParams) (interface{}, error) {
|
|
args, _ := json.Marshal(p.Args)
|
|
return string(args), nil
|
|
},
|
|
},
|
|
},
|
|
}),
|
|
})
|
|
if err != nil {
|
|
t.Fatalf("Error in schema %v", err.Error())
|
|
}
|
|
|
|
// parse query
|
|
ast := testutil.TestParse(t, doc)
|
|
|
|
// execute
|
|
ep := graphql.ExecuteParams{
|
|
Schema: schema,
|
|
AST: ast,
|
|
}
|
|
result := testutil.TestExecute(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))
|
|
}
|
|
}
|
|
|
|
type testSpecialType struct {
|
|
Value string
|
|
}
|
|
type testNotSpecialType struct {
|
|
Value string
|
|
}
|
|
|
|
func TestFailsWhenAnIsTypeOfCheckIsNotMet(t *testing.T) {
|
|
|
|
query := `{ specials { value } }`
|
|
|
|
data := map[string]interface{}{
|
|
"specials": []interface{}{
|
|
testSpecialType{"foo"},
|
|
testNotSpecialType{"bar"},
|
|
},
|
|
}
|
|
|
|
expected := &graphql.Result{
|
|
Data: map[string]interface{}{
|
|
"specials": []interface{}{
|
|
map[string]interface{}{
|
|
"value": "foo",
|
|
},
|
|
nil,
|
|
},
|
|
},
|
|
Errors: []gqlerrors.FormattedError{
|
|
{
|
|
Message: `Expected value of type "SpecialType" but got: graphql_test.testNotSpecialType.`,
|
|
Locations: []location.SourceLocation{},
|
|
},
|
|
},
|
|
}
|
|
|
|
specialType := graphql.NewObject(graphql.ObjectConfig{
|
|
Name: "SpecialType",
|
|
IsTypeOf: func(p graphql.IsTypeOfParams) bool {
|
|
if _, ok := p.Value.(testSpecialType); ok {
|
|
return true
|
|
}
|
|
return false
|
|
},
|
|
Fields: graphql.Fields{
|
|
"value": &graphql.Field{
|
|
Type: graphql.String,
|
|
Resolve: func(p graphql.ResolveParams) (interface{}, error) {
|
|
return p.Source.(testSpecialType).Value, nil
|
|
},
|
|
},
|
|
},
|
|
})
|
|
schema, err := graphql.NewSchema(graphql.SchemaConfig{
|
|
Query: graphql.NewObject(graphql.ObjectConfig{
|
|
Name: "Query",
|
|
Fields: graphql.Fields{
|
|
"specials": &graphql.Field{
|
|
Type: graphql.NewList(specialType),
|
|
Resolve: func(p graphql.ResolveParams) (interface{}, error) {
|
|
return p.Source.(map[string]interface{})["specials"], nil
|
|
},
|
|
},
|
|
},
|
|
}),
|
|
})
|
|
if err != nil {
|
|
t.Fatalf("Error in schema %v", err.Error())
|
|
}
|
|
|
|
// parse query
|
|
ast := testutil.TestParse(t, query)
|
|
|
|
// execute
|
|
ep := graphql.ExecuteParams{
|
|
Schema: schema,
|
|
AST: ast,
|
|
Root: data,
|
|
}
|
|
result := testutil.TestExecute(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 TestFailsToExecuteQueryContainingATypeDefinition(t *testing.T) {
|
|
|
|
query := `
|
|
{ foo }
|
|
|
|
type Query { foo: String }
|
|
`
|
|
expected := &graphql.Result{
|
|
Data: nil,
|
|
Errors: []gqlerrors.FormattedError{
|
|
{
|
|
Message: "GraphQL cannot execute a request containing a ObjectDefinition",
|
|
Locations: []location.SourceLocation{},
|
|
},
|
|
},
|
|
}
|
|
|
|
schema, err := graphql.NewSchema(graphql.SchemaConfig{
|
|
Query: graphql.NewObject(graphql.ObjectConfig{
|
|
Name: "Query",
|
|
Fields: graphql.Fields{
|
|
"foo": &graphql.Field{
|
|
Type: graphql.String,
|
|
},
|
|
},
|
|
}),
|
|
})
|
|
if err != nil {
|
|
t.Fatalf("Error in schema %v", err.Error())
|
|
}
|
|
|
|
// parse query
|
|
ast := testutil.TestParse(t, query)
|
|
|
|
// execute
|
|
ep := graphql.ExecuteParams{
|
|
Schema: schema,
|
|
AST: ast,
|
|
}
|
|
result := testutil.TestExecute(t, ep)
|
|
if len(result.Errors) != 1 {
|
|
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 TestQuery_ExecutionAddsErrorsFromFieldResolveFn(t *testing.T) {
|
|
qError := errors.New("queryError")
|
|
q := graphql.NewObject(graphql.ObjectConfig{
|
|
Name: "Query",
|
|
Fields: graphql.Fields{
|
|
"a": &graphql.Field{
|
|
Type: graphql.String,
|
|
Resolve: func(p graphql.ResolveParams) (interface{}, error) {
|
|
return nil, qError
|
|
},
|
|
},
|
|
"b": &graphql.Field{
|
|
Type: graphql.String,
|
|
Resolve: func(p graphql.ResolveParams) (interface{}, error) {
|
|
return "ok", nil
|
|
},
|
|
},
|
|
},
|
|
})
|
|
blogSchema, err := graphql.NewSchema(graphql.SchemaConfig{
|
|
Query: q,
|
|
})
|
|
if err != nil {
|
|
t.Fatalf("unexpected error, got: %v", err)
|
|
}
|
|
query := "{ a }"
|
|
result := graphql.Do(graphql.Params{
|
|
Schema: blogSchema,
|
|
RequestString: query,
|
|
})
|
|
if len(result.Errors) == 0 {
|
|
t.Fatal("wrong result, expected errors, got no errors")
|
|
}
|
|
if result.Errors[0].Error() != qError.Error() {
|
|
t.Fatalf("wrong result, unexpected error, got: %v, expected: %v", result.Errors[0], qError)
|
|
}
|
|
}
|
|
|
|
func TestQuery_ExecutionDoesNotAddErrorsFromFieldResolveFn(t *testing.T) {
|
|
qError := errors.New("queryError")
|
|
q := graphql.NewObject(graphql.ObjectConfig{
|
|
Name: "Query",
|
|
Fields: graphql.Fields{
|
|
"a": &graphql.Field{
|
|
Type: graphql.String,
|
|
Resolve: func(p graphql.ResolveParams) (interface{}, error) {
|
|
return nil, qError
|
|
},
|
|
},
|
|
"b": &graphql.Field{
|
|
Type: graphql.String,
|
|
Resolve: func(p graphql.ResolveParams) (interface{}, error) {
|
|
return "ok", nil
|
|
},
|
|
},
|
|
},
|
|
})
|
|
blogSchema, err := graphql.NewSchema(graphql.SchemaConfig{
|
|
Query: q,
|
|
})
|
|
if err != nil {
|
|
t.Fatalf("unexpected error, got: %v", err)
|
|
}
|
|
query := "{ b }"
|
|
result := graphql.Do(graphql.Params{
|
|
Schema: blogSchema,
|
|
RequestString: query,
|
|
})
|
|
if len(result.Errors) != 0 {
|
|
t.Fatalf("wrong result, unexpected errors: %+v", result.Errors)
|
|
}
|
|
}
|
|
|
|
func TestMutation_ExecutionAddsErrorsFromFieldResolveFn(t *testing.T) {
|
|
mError := errors.New("mutationError")
|
|
q := graphql.NewObject(graphql.ObjectConfig{
|
|
Name: "Query",
|
|
Fields: graphql.Fields{
|
|
"a": &graphql.Field{
|
|
Type: graphql.String,
|
|
},
|
|
},
|
|
})
|
|
m := graphql.NewObject(graphql.ObjectConfig{
|
|
Name: "Mutation",
|
|
Fields: graphql.Fields{
|
|
"foo": &graphql.Field{
|
|
Type: graphql.String,
|
|
Args: graphql.FieldConfigArgument{
|
|
"f": &graphql.ArgumentConfig{
|
|
Type: graphql.String,
|
|
},
|
|
},
|
|
Resolve: func(p graphql.ResolveParams) (interface{}, error) {
|
|
return nil, mError
|
|
},
|
|
},
|
|
"bar": &graphql.Field{
|
|
Type: graphql.String,
|
|
Args: graphql.FieldConfigArgument{
|
|
"b": &graphql.ArgumentConfig{
|
|
Type: graphql.String,
|
|
},
|
|
},
|
|
Resolve: func(p graphql.ResolveParams) (interface{}, error) {
|
|
return "ok", nil
|
|
},
|
|
},
|
|
},
|
|
})
|
|
schema, err := graphql.NewSchema(graphql.SchemaConfig{
|
|
Query: q,
|
|
Mutation: m,
|
|
})
|
|
if err != nil {
|
|
t.Fatalf("unexpected error, got: %v", err)
|
|
}
|
|
query := "mutation _ { newFoo: foo(f:\"title\") }"
|
|
result := graphql.Do(graphql.Params{
|
|
Schema: schema,
|
|
RequestString: query,
|
|
})
|
|
if len(result.Errors) == 0 {
|
|
t.Fatal("wrong result, expected errors, got no errors")
|
|
}
|
|
if result.Errors[0].Error() != mError.Error() {
|
|
t.Fatalf("wrong result, unexpected error, got: %v, expected: %v", result.Errors[0], mError)
|
|
}
|
|
}
|
|
|
|
func TestMutation_ExecutionDoesNotAddErrorsFromFieldResolveFn(t *testing.T) {
|
|
mError := errors.New("mutationError")
|
|
q := graphql.NewObject(graphql.ObjectConfig{
|
|
Name: "Query",
|
|
Fields: graphql.Fields{
|
|
"a": &graphql.Field{
|
|
Type: graphql.String,
|
|
},
|
|
},
|
|
})
|
|
m := graphql.NewObject(graphql.ObjectConfig{
|
|
Name: "Mutation",
|
|
Fields: graphql.Fields{
|
|
"foo": &graphql.Field{
|
|
Type: graphql.String,
|
|
Args: graphql.FieldConfigArgument{
|
|
"f": &graphql.ArgumentConfig{
|
|
Type: graphql.String,
|
|
},
|
|
},
|
|
Resolve: func(p graphql.ResolveParams) (interface{}, error) {
|
|
return nil, mError
|
|
},
|
|
},
|
|
"bar": &graphql.Field{
|
|
Type: graphql.String,
|
|
Args: graphql.FieldConfigArgument{
|
|
"b": &graphql.ArgumentConfig{
|
|
Type: graphql.String,
|
|
},
|
|
},
|
|
Resolve: func(p graphql.ResolveParams) (interface{}, error) {
|
|
return "ok", nil
|
|
},
|
|
},
|
|
},
|
|
})
|
|
schema, err := graphql.NewSchema(graphql.SchemaConfig{
|
|
Query: q,
|
|
Mutation: m,
|
|
})
|
|
if err != nil {
|
|
t.Fatalf("unexpected error, got: %v", err)
|
|
}
|
|
query := "mutation _ { newBar: bar(b:\"title\") }"
|
|
result := graphql.Do(graphql.Params{
|
|
Schema: schema,
|
|
RequestString: query,
|
|
})
|
|
if len(result.Errors) != 0 {
|
|
t.Fatalf("wrong result, unexpected errors: %+v", result.Errors)
|
|
}
|
|
}
|
|
|
|
func TestGraphqlTag(t *testing.T) {
|
|
typeObjectType := graphql.NewObject(graphql.ObjectConfig{
|
|
Name: "Type",
|
|
Fields: graphql.Fields{
|
|
"fooBar": &graphql.Field{Type: graphql.String},
|
|
},
|
|
})
|
|
var baz = &graphql.Field{
|
|
Type: typeObjectType,
|
|
Description: "typeObjectType",
|
|
Resolve: func(p graphql.ResolveParams) (interface{}, error) {
|
|
t := struct {
|
|
FooBar string `graphql:"fooBar"`
|
|
}{"foo bar value"}
|
|
return t, nil
|
|
},
|
|
}
|
|
q := graphql.NewObject(graphql.ObjectConfig{
|
|
Name: "Query",
|
|
Fields: graphql.Fields{
|
|
"baz": baz,
|
|
},
|
|
})
|
|
schema, err := graphql.NewSchema(graphql.SchemaConfig{
|
|
Query: q,
|
|
})
|
|
if err != nil {
|
|
t.Fatalf("unexpected error, got: %v", err)
|
|
}
|
|
query := "{ baz { fooBar } }"
|
|
result := graphql.Do(graphql.Params{
|
|
Schema: schema,
|
|
RequestString: query,
|
|
})
|
|
if len(result.Errors) != 0 {
|
|
t.Fatalf("wrong result, unexpected errors: %+v", result.Errors)
|
|
}
|
|
expectedData := map[string]interface{}{
|
|
"baz": map[string]interface{}{
|
|
"fooBar": "foo bar value",
|
|
},
|
|
}
|
|
if !reflect.DeepEqual(result.Data, expectedData) {
|
|
t.Fatalf("unexpected result, got: %+v, expected: %+v", expectedData, result.Data)
|
|
}
|
|
}
|
|
|
|
func TestContextDeadline(t *testing.T) {
|
|
timeout := time.Millisecond * time.Duration(100)
|
|
acceptableDelay := time.Millisecond * time.Duration(10)
|
|
expectedErrors := []gqlerrors.FormattedError{
|
|
{
|
|
Message: context.DeadlineExceeded.Error(),
|
|
Locations: []location.SourceLocation{},
|
|
},
|
|
}
|
|
|
|
// Query type includes a field that won't resolve within the deadline
|
|
var queryType = graphql.NewObject(
|
|
graphql.ObjectConfig{
|
|
Name: "Query",
|
|
Fields: graphql.Fields{
|
|
"hello": &graphql.Field{
|
|
Type: graphql.String,
|
|
Resolve: func(p graphql.ResolveParams) (interface{}, error) {
|
|
time.Sleep(2 * time.Second)
|
|
return "world", nil
|
|
},
|
|
},
|
|
},
|
|
})
|
|
schema, err := graphql.NewSchema(graphql.SchemaConfig{
|
|
Query: queryType,
|
|
})
|
|
if err != nil {
|
|
t.Fatalf("unexpected error, got: %v", err)
|
|
}
|
|
|
|
ctx, cancel := context.WithTimeout(context.Background(), timeout)
|
|
defer cancel()
|
|
|
|
startTime := time.Now()
|
|
result := graphql.Do(graphql.Params{
|
|
Schema: schema,
|
|
RequestString: "{hello}",
|
|
Context: ctx,
|
|
})
|
|
duration := time.Since(startTime)
|
|
|
|
if duration > timeout+acceptableDelay {
|
|
t.Fatalf("graphql.Do completed in %s, should have completed in %s", duration, timeout)
|
|
}
|
|
if !result.HasErrors() || len(result.Errors) == 0 {
|
|
t.Fatalf("Result should include errors when deadline is exceeded")
|
|
}
|
|
if !reflect.DeepEqual(expectedErrors, result.Errors) {
|
|
t.Fatalf("Unexpected result, Diff: %v", testutil.Diff(expectedErrors, result.Errors))
|
|
}
|
|
}
|