mirror of
https://github.com/dolthub/dolt.git
synced 2026-02-21 10:09:35 -06:00
588 lines
13 KiB
Go
588 lines
13 KiB
Go
package graphql_test
|
|
|
|
import (
|
|
"reflect"
|
|
"testing"
|
|
|
|
"github.com/attic-labs/graphql"
|
|
"github.com/attic-labs/graphql/testutil"
|
|
"golang.org/x/net/context"
|
|
)
|
|
|
|
type testNamedType interface {
|
|
}
|
|
type testPet interface {
|
|
}
|
|
type testDog2 struct {
|
|
Name string `json:"name"`
|
|
Barks bool `json:"barks"`
|
|
}
|
|
|
|
type testCat2 struct {
|
|
Name string `json:"name"`
|
|
Meows bool `json:"meows"`
|
|
}
|
|
|
|
type testPerson struct {
|
|
Name string `json:"name"`
|
|
Pets []testPet `json:"pets"`
|
|
Friends []testNamedType `json:"friends"`
|
|
}
|
|
|
|
var namedType = graphql.NewInterface(graphql.InterfaceConfig{
|
|
Name: "Named",
|
|
Fields: graphql.Fields{
|
|
"name": &graphql.Field{
|
|
Type: graphql.String,
|
|
},
|
|
},
|
|
})
|
|
var dogType = graphql.NewObject(graphql.ObjectConfig{
|
|
Name: "Dog",
|
|
Interfaces: []*graphql.Interface{
|
|
namedType,
|
|
},
|
|
Fields: graphql.Fields{
|
|
"name": &graphql.Field{
|
|
Type: graphql.String,
|
|
},
|
|
"barks": &graphql.Field{
|
|
Type: graphql.Boolean,
|
|
},
|
|
},
|
|
IsTypeOf: func(p graphql.IsTypeOfParams) bool {
|
|
_, ok := p.Value.(*testDog2)
|
|
return ok
|
|
},
|
|
})
|
|
var catType = graphql.NewObject(graphql.ObjectConfig{
|
|
Name: "Cat",
|
|
Interfaces: []*graphql.Interface{
|
|
namedType,
|
|
},
|
|
Fields: graphql.Fields{
|
|
"name": &graphql.Field{
|
|
Type: graphql.String,
|
|
},
|
|
"meows": &graphql.Field{
|
|
Type: graphql.Boolean,
|
|
},
|
|
},
|
|
IsTypeOf: func(p graphql.IsTypeOfParams) bool {
|
|
_, ok := p.Value.(*testCat2)
|
|
return ok
|
|
},
|
|
})
|
|
var petType = graphql.NewUnion(graphql.UnionConfig{
|
|
Name: "Pet",
|
|
Types: []*graphql.Object{
|
|
dogType, catType,
|
|
},
|
|
ResolveType: func(p graphql.ResolveTypeParams) *graphql.Object {
|
|
if _, ok := p.Value.(*testCat2); ok {
|
|
return catType
|
|
}
|
|
if _, ok := p.Value.(*testDog2); ok {
|
|
return dogType
|
|
}
|
|
return nil
|
|
},
|
|
})
|
|
var personType = graphql.NewObject(graphql.ObjectConfig{
|
|
Name: "Person",
|
|
Interfaces: []*graphql.Interface{
|
|
namedType,
|
|
},
|
|
Fields: graphql.Fields{
|
|
"name": &graphql.Field{
|
|
Type: graphql.String,
|
|
},
|
|
"pets": &graphql.Field{
|
|
Type: graphql.NewList(petType),
|
|
},
|
|
"friends": &graphql.Field{
|
|
Type: graphql.NewList(namedType),
|
|
},
|
|
},
|
|
IsTypeOf: func(p graphql.IsTypeOfParams) bool {
|
|
_, ok := p.Value.(*testPerson)
|
|
return ok
|
|
},
|
|
})
|
|
|
|
var unionInterfaceTestSchema, _ = graphql.NewSchema(graphql.SchemaConfig{
|
|
Query: personType,
|
|
Types: []graphql.Type{petType},
|
|
})
|
|
|
|
var garfield = &testCat2{"Garfield", false}
|
|
var odie = &testDog2{"Odie", true}
|
|
var liz = &testPerson{
|
|
Name: "Liz",
|
|
}
|
|
var john = &testPerson{
|
|
Name: "John",
|
|
Pets: []testPet{
|
|
garfield, odie,
|
|
},
|
|
Friends: []testNamedType{
|
|
liz, odie,
|
|
},
|
|
}
|
|
|
|
func TestUnionIntersectionTypes_CanIntrospectOnUnionAndIntersectionTypes(t *testing.T) {
|
|
doc := `
|
|
{
|
|
Named: __type(name: "Named") {
|
|
kind
|
|
name
|
|
fields { name }
|
|
interfaces { name }
|
|
possibleTypes { name }
|
|
enumValues { name }
|
|
inputFields { name }
|
|
}
|
|
Pet: __type(name: "Pet") {
|
|
kind
|
|
name
|
|
fields { name }
|
|
interfaces { name }
|
|
possibleTypes { name }
|
|
enumValues { name }
|
|
inputFields { name }
|
|
}
|
|
}
|
|
`
|
|
expected := &graphql.Result{
|
|
Data: map[string]interface{}{
|
|
"Named": map[string]interface{}{
|
|
"kind": "INTERFACE",
|
|
"name": "Named",
|
|
"fields": []interface{}{
|
|
map[string]interface{}{
|
|
"name": "name",
|
|
},
|
|
},
|
|
"interfaces": nil,
|
|
"possibleTypes": []interface{}{
|
|
map[string]interface{}{
|
|
"name": "Dog",
|
|
},
|
|
map[string]interface{}{
|
|
"name": "Cat",
|
|
},
|
|
map[string]interface{}{
|
|
"name": "Person",
|
|
},
|
|
},
|
|
"enumValues": nil,
|
|
"inputFields": nil,
|
|
},
|
|
"Pet": map[string]interface{}{
|
|
"kind": "UNION",
|
|
"name": "Pet",
|
|
"fields": nil,
|
|
"interfaces": nil,
|
|
"possibleTypes": []interface{}{
|
|
map[string]interface{}{
|
|
"name": "Dog",
|
|
},
|
|
map[string]interface{}{
|
|
"name": "Cat",
|
|
},
|
|
},
|
|
"enumValues": nil,
|
|
"inputFields": nil,
|
|
},
|
|
},
|
|
}
|
|
// parse query
|
|
ast := testutil.TestParse(t, doc)
|
|
|
|
// execute
|
|
ep := graphql.ExecuteParams{
|
|
Schema: unionInterfaceTestSchema,
|
|
AST: ast,
|
|
}
|
|
result := testutil.TestExecute(t, ep)
|
|
if len(result.Errors) != len(expected.Errors) {
|
|
t.Fatalf("Unexpected errors, Diff: %v", testutil.Diff(expected.Errors, result.Errors))
|
|
}
|
|
if !testutil.ContainSubset(expected.Data.(map[string]interface{}), result.Data.(map[string]interface{})) {
|
|
t.Fatalf("Unexpected result, Diff: %v", testutil.Diff(expected.Data, result.Data))
|
|
}
|
|
}
|
|
func TestUnionIntersectionTypes_ExecutesUsingUnionTypes(t *testing.T) {
|
|
// NOTE: This is an *invalid* query, but it should be an *executable* query.
|
|
doc := `
|
|
{
|
|
__typename
|
|
name
|
|
pets {
|
|
__typename
|
|
name
|
|
barks
|
|
meows
|
|
}
|
|
}
|
|
`
|
|
expected := &graphql.Result{
|
|
Data: map[string]interface{}{
|
|
"__typename": "Person",
|
|
"name": "John",
|
|
"pets": []interface{}{
|
|
map[string]interface{}{
|
|
"__typename": "Cat",
|
|
"name": "Garfield",
|
|
"meows": false,
|
|
},
|
|
map[string]interface{}{
|
|
"__typename": "Dog",
|
|
"name": "Odie",
|
|
"barks": true,
|
|
},
|
|
},
|
|
},
|
|
}
|
|
// parse query
|
|
ast := testutil.TestParse(t, doc)
|
|
|
|
// execute
|
|
ep := graphql.ExecuteParams{
|
|
Schema: unionInterfaceTestSchema,
|
|
AST: ast,
|
|
Root: john,
|
|
}
|
|
result := testutil.TestExecute(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))
|
|
}
|
|
}
|
|
func TestUnionIntersectionTypes_ExecutesUnionTypesWithInlineFragments(t *testing.T) {
|
|
// This is the valid version of the query in the above test.
|
|
doc := `
|
|
{
|
|
__typename
|
|
name
|
|
pets {
|
|
__typename
|
|
... on Dog {
|
|
name
|
|
barks
|
|
}
|
|
... on Cat {
|
|
name
|
|
meows
|
|
}
|
|
}
|
|
}
|
|
`
|
|
expected := &graphql.Result{
|
|
Data: map[string]interface{}{
|
|
"__typename": "Person",
|
|
"name": "John",
|
|
"pets": []interface{}{
|
|
map[string]interface{}{
|
|
"__typename": "Cat",
|
|
"name": "Garfield",
|
|
"meows": false,
|
|
},
|
|
map[string]interface{}{
|
|
"__typename": "Dog",
|
|
"name": "Odie",
|
|
"barks": true,
|
|
},
|
|
},
|
|
},
|
|
}
|
|
// parse query
|
|
ast := testutil.TestParse(t, doc)
|
|
|
|
// execute
|
|
ep := graphql.ExecuteParams{
|
|
Schema: unionInterfaceTestSchema,
|
|
AST: ast,
|
|
Root: john,
|
|
}
|
|
result := testutil.TestExecute(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))
|
|
}
|
|
}
|
|
func TestUnionIntersectionTypes_ExecutesUsingInterfaceTypes(t *testing.T) {
|
|
|
|
// NOTE: This is an *invalid* query, but it should be an *executable* query.
|
|
doc := `
|
|
{
|
|
__typename
|
|
name
|
|
friends {
|
|
__typename
|
|
name
|
|
barks
|
|
meows
|
|
}
|
|
}
|
|
`
|
|
expected := &graphql.Result{
|
|
Data: map[string]interface{}{
|
|
"__typename": "Person",
|
|
"name": "John",
|
|
"friends": []interface{}{
|
|
map[string]interface{}{
|
|
"__typename": "Person",
|
|
"name": "Liz",
|
|
},
|
|
map[string]interface{}{
|
|
"__typename": "Dog",
|
|
"name": "Odie",
|
|
"barks": true,
|
|
},
|
|
},
|
|
},
|
|
}
|
|
// parse query
|
|
ast := testutil.TestParse(t, doc)
|
|
|
|
// execute
|
|
ep := graphql.ExecuteParams{
|
|
Schema: unionInterfaceTestSchema,
|
|
AST: ast,
|
|
Root: john,
|
|
}
|
|
result := testutil.TestExecute(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))
|
|
}
|
|
}
|
|
func TestUnionIntersectionTypes_ExecutesInterfaceTypesWithInlineFragments(t *testing.T) {
|
|
|
|
// This is the valid version of the query in the above test.
|
|
doc := `
|
|
{
|
|
__typename
|
|
name
|
|
friends {
|
|
__typename
|
|
name
|
|
... on Dog {
|
|
barks
|
|
}
|
|
... on Cat {
|
|
meows
|
|
}
|
|
}
|
|
}
|
|
`
|
|
expected := &graphql.Result{
|
|
Data: map[string]interface{}{
|
|
"__typename": "Person",
|
|
"name": "John",
|
|
"friends": []interface{}{
|
|
map[string]interface{}{
|
|
"__typename": "Person",
|
|
"name": "Liz",
|
|
},
|
|
map[string]interface{}{
|
|
"__typename": "Dog",
|
|
"name": "Odie",
|
|
"barks": true,
|
|
},
|
|
},
|
|
},
|
|
}
|
|
// parse query
|
|
ast := testutil.TestParse(t, doc)
|
|
|
|
// execute
|
|
ep := graphql.ExecuteParams{
|
|
Schema: unionInterfaceTestSchema,
|
|
AST: ast,
|
|
Root: john,
|
|
}
|
|
result := testutil.TestExecute(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))
|
|
}
|
|
}
|
|
|
|
func TestUnionIntersectionTypes_AllowsFragmentConditionsToBeAbstractTypes(t *testing.T) {
|
|
|
|
doc := `
|
|
{
|
|
__typename
|
|
name
|
|
pets { ...PetFields }
|
|
friends { ...FriendFields }
|
|
}
|
|
|
|
fragment PetFields on Pet {
|
|
__typename
|
|
... on Dog {
|
|
name
|
|
barks
|
|
}
|
|
... on Cat {
|
|
name
|
|
meows
|
|
}
|
|
}
|
|
|
|
fragment FriendFields on Named {
|
|
__typename
|
|
name
|
|
... on Dog {
|
|
barks
|
|
}
|
|
... on Cat {
|
|
meows
|
|
}
|
|
}
|
|
`
|
|
expected := &graphql.Result{
|
|
Data: map[string]interface{}{
|
|
"__typename": "Person",
|
|
"name": "John",
|
|
"friends": []interface{}{
|
|
map[string]interface{}{
|
|
"__typename": "Person",
|
|
"name": "Liz",
|
|
},
|
|
map[string]interface{}{
|
|
"__typename": "Dog",
|
|
"name": "Odie",
|
|
"barks": true,
|
|
},
|
|
},
|
|
"pets": []interface{}{
|
|
map[string]interface{}{
|
|
"__typename": "Cat",
|
|
"name": "Garfield",
|
|
"meows": false,
|
|
},
|
|
map[string]interface{}{
|
|
"__typename": "Dog",
|
|
"name": "Odie",
|
|
"barks": true,
|
|
},
|
|
},
|
|
},
|
|
}
|
|
// parse query
|
|
ast := testutil.TestParse(t, doc)
|
|
|
|
// execute
|
|
ep := graphql.ExecuteParams{
|
|
Schema: unionInterfaceTestSchema,
|
|
AST: ast,
|
|
Root: john,
|
|
}
|
|
result := testutil.TestExecute(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))
|
|
}
|
|
}
|
|
func TestUnionIntersectionTypes_GetsExecutionInfoInResolver(t *testing.T) {
|
|
|
|
var encounteredContextValue string
|
|
var encounteredSchema graphql.Schema
|
|
var encounteredRootValue string
|
|
var personType2 *graphql.Object
|
|
|
|
namedType2 := graphql.NewInterface(graphql.InterfaceConfig{
|
|
Name: "Named",
|
|
Fields: graphql.Fields{
|
|
"name": &graphql.Field{
|
|
Type: graphql.String,
|
|
},
|
|
},
|
|
ResolveType: func(p graphql.ResolveTypeParams) *graphql.Object {
|
|
encounteredSchema = p.Info.Schema
|
|
encounteredContextValue, _ = p.Context.Value("authToken").(string)
|
|
encounteredRootValue = p.Info.RootValue.(*testPerson).Name
|
|
return personType2
|
|
},
|
|
})
|
|
|
|
personType2 = graphql.NewObject(graphql.ObjectConfig{
|
|
Name: "Person",
|
|
Interfaces: []*graphql.Interface{
|
|
namedType2,
|
|
},
|
|
Fields: graphql.Fields{
|
|
"name": &graphql.Field{
|
|
Type: graphql.String,
|
|
},
|
|
"friends": &graphql.Field{
|
|
Type: graphql.NewList(namedType2),
|
|
},
|
|
},
|
|
})
|
|
|
|
schema2, _ := graphql.NewSchema(graphql.SchemaConfig{
|
|
Query: personType2,
|
|
})
|
|
|
|
john2 := &testPerson{
|
|
Name: "John",
|
|
Friends: []testNamedType{
|
|
liz,
|
|
},
|
|
}
|
|
|
|
doc := `{ name, friends { name } }`
|
|
expected := &graphql.Result{
|
|
Data: map[string]interface{}{
|
|
"name": "John",
|
|
"friends": []interface{}{
|
|
map[string]interface{}{
|
|
"name": "Liz",
|
|
},
|
|
},
|
|
},
|
|
}
|
|
// parse query
|
|
ast := testutil.TestParse(t, doc)
|
|
|
|
// create context
|
|
ctx := context.Background()
|
|
ctx = context.WithValue(ctx, "authToken", "contextStringValue123")
|
|
|
|
// execute
|
|
ep := graphql.ExecuteParams{
|
|
Schema: schema2,
|
|
AST: ast,
|
|
Root: john2,
|
|
Context: ctx,
|
|
}
|
|
result := testutil.TestExecute(t, ep)
|
|
|
|
if !reflect.DeepEqual(expected, result) {
|
|
t.Fatalf("Unexpected result, Diff: %v", testutil.Diff(expected, result))
|
|
}
|
|
if !reflect.DeepEqual("contextStringValue123", encounteredContextValue) {
|
|
t.Fatalf("Unexpected result, Diff: %v", testutil.Diff("contextStringValue123", encounteredContextValue))
|
|
}
|
|
if !reflect.DeepEqual("John", encounteredRootValue) {
|
|
t.Fatalf("Unexpected result, Diff: %v", testutil.Diff("John", encounteredRootValue))
|
|
}
|
|
if !reflect.DeepEqual(schema2, encounteredSchema) {
|
|
t.Fatalf("Unexpected result, Diff: %v", testutil.Diff(schema2, encounteredSchema))
|
|
}
|
|
}
|