1package graphql_test
2
3import (
4	"testing"
5
6	"github.com/graphql-go/graphql"
7	"github.com/graphql-go/graphql/language/ast"
8)
9
10var someScalarType = graphql.NewScalar(graphql.ScalarConfig{
11	Name: "SomeScalar",
12	Serialize: func(value interface{}) interface{} {
13		return nil
14	},
15	ParseValue: func(value interface{}) interface{} {
16		return nil
17	},
18	ParseLiteral: func(valueAST ast.Value) interface{} {
19		return nil
20	},
21})
22var someObjectType = graphql.NewObject(graphql.ObjectConfig{
23	Name: "SomeObject",
24	Fields: graphql.Fields{
25		"f": &graphql.Field{
26			Type: graphql.String,
27		},
28	},
29})
30var objectWithIsTypeOf = graphql.NewObject(graphql.ObjectConfig{
31	Name: "ObjectWithIsTypeOf",
32	IsTypeOf: func(p graphql.IsTypeOfParams) bool {
33		return true
34	},
35	Fields: graphql.Fields{
36		"f": &graphql.Field{
37			Type: graphql.String,
38		},
39	},
40})
41var someUnionType = graphql.NewUnion(graphql.UnionConfig{
42	Name: "SomeUnion",
43	ResolveType: func(p graphql.ResolveTypeParams) *graphql.Object {
44		return nil
45	},
46	Types: []*graphql.Object{
47		someObjectType,
48	},
49})
50var someInterfaceType = graphql.NewInterface(graphql.InterfaceConfig{
51	Name: "SomeInterface",
52	ResolveType: func(p graphql.ResolveTypeParams) *graphql.Object {
53		return nil
54	},
55	Fields: graphql.Fields{
56		"f": &graphql.Field{
57			Type: graphql.String,
58		},
59	},
60})
61var someEnumType = graphql.NewEnum(graphql.EnumConfig{
62	Name: "SomeEnum",
63	Values: graphql.EnumValueConfigMap{
64		"ONLY": &graphql.EnumValueConfig{},
65	},
66})
67var someInputObject = graphql.NewInputObject(graphql.InputObjectConfig{
68	Name: "SomeInputObject",
69	Fields: graphql.InputObjectConfigFieldMap{
70		"f": &graphql.InputObjectFieldConfig{
71			Type:         graphql.String,
72			DefaultValue: "Hello",
73		},
74	},
75})
76
77func withModifiers(ttypes []graphql.Type) []graphql.Type {
78	res := ttypes
79	for _, ttype := range ttypes {
80		res = append(res, graphql.NewList(ttype))
81	}
82	for _, ttype := range ttypes {
83		res = append(res, graphql.NewNonNull(ttype))
84	}
85	for _, ttype := range ttypes {
86		res = append(res, graphql.NewNonNull(graphql.NewList(ttype)))
87	}
88	return res
89}
90
91var outputTypes = withModifiers([]graphql.Type{
92	graphql.String,
93	someScalarType,
94	someEnumType,
95	someObjectType,
96	someUnionType,
97	someInterfaceType,
98})
99var inputTypes = withModifiers([]graphql.Type{
100	graphql.String,
101	someScalarType,
102	someEnumType,
103	someInputObject,
104})
105
106func schemaWithFieldType(ttype graphql.Output) (graphql.Schema, error) {
107	return graphql.NewSchema(graphql.SchemaConfig{
108		Query: graphql.NewObject(graphql.ObjectConfig{
109			Name: "Query",
110			Fields: graphql.Fields{
111				"f": &graphql.Field{
112					Type: ttype,
113				},
114			},
115		}),
116		Types: []graphql.Type{ttype},
117	})
118}
119func schemaWithInputObject(ttype graphql.Input) (graphql.Schema, error) {
120	return graphql.NewSchema(graphql.SchemaConfig{
121		Query: graphql.NewObject(graphql.ObjectConfig{
122			Name: "Query",
123			Fields: graphql.Fields{
124				"f": &graphql.Field{
125					Type: graphql.String,
126					Args: graphql.FieldConfigArgument{
127						"args": &graphql.ArgumentConfig{
128							Type: ttype,
129						},
130					},
131				},
132			},
133		}),
134	})
135}
136func schemaWithObjectFieldOfType(fieldType graphql.Input) (graphql.Schema, error) {
137
138	badObjectType := graphql.NewObject(graphql.ObjectConfig{
139		Name: "BadObject",
140		Fields: graphql.Fields{
141			"badField": &graphql.Field{
142				Type: fieldType,
143			},
144		},
145	})
146	return graphql.NewSchema(graphql.SchemaConfig{
147		Query: graphql.NewObject(graphql.ObjectConfig{
148			Name: "Query",
149			Fields: graphql.Fields{
150				"f": &graphql.Field{
151					Type: badObjectType,
152				},
153			},
154		}),
155	})
156}
157func schemaWithObjectImplementingType(implementedType *graphql.Interface) (graphql.Schema, error) {
158
159	badObjectType := graphql.NewObject(graphql.ObjectConfig{
160		Name:       "BadObject",
161		Interfaces: []*graphql.Interface{implementedType},
162		Fields: graphql.Fields{
163			"f": &graphql.Field{
164				Type: graphql.String,
165			},
166		},
167	})
168	return graphql.NewSchema(graphql.SchemaConfig{
169		Query: graphql.NewObject(graphql.ObjectConfig{
170			Name: "Query",
171			Fields: graphql.Fields{
172				"f": &graphql.Field{
173					Type: badObjectType,
174				},
175			},
176		}),
177		Types: []graphql.Type{badObjectType},
178	})
179}
180func schemaWithUnionOfType(ttype *graphql.Object) (graphql.Schema, error) {
181
182	badObjectType := graphql.NewUnion(graphql.UnionConfig{
183		Name: "BadUnion",
184		ResolveType: func(p graphql.ResolveTypeParams) *graphql.Object {
185			return nil
186		},
187		Types: []*graphql.Object{ttype},
188	})
189	return graphql.NewSchema(graphql.SchemaConfig{
190		Query: graphql.NewObject(graphql.ObjectConfig{
191			Name: "Query",
192			Fields: graphql.Fields{
193				"f": &graphql.Field{
194					Type: badObjectType,
195				},
196			},
197		}),
198	})
199}
200func schemaWithInterfaceFieldOfType(ttype graphql.Type) (graphql.Schema, error) {
201
202	badInterfaceType := graphql.NewInterface(graphql.InterfaceConfig{
203		Name: "BadInterface",
204		Fields: graphql.Fields{
205			"badField": &graphql.Field{
206				Type: ttype,
207			},
208		},
209	})
210	return graphql.NewSchema(graphql.SchemaConfig{
211		Query: graphql.NewObject(graphql.ObjectConfig{
212			Name: "Query",
213			Fields: graphql.Fields{
214				"f": &graphql.Field{
215					Type: badInterfaceType,
216				},
217			},
218		}),
219	})
220}
221func schemaWithArgOfType(ttype graphql.Type) (graphql.Schema, error) {
222
223	badObject := graphql.NewObject(graphql.ObjectConfig{
224		Name: "BadObject",
225		Fields: graphql.Fields{
226			"badField": &graphql.Field{
227				Type: graphql.String,
228				Args: graphql.FieldConfigArgument{
229					"badArg": &graphql.ArgumentConfig{
230						Type: ttype,
231					},
232				},
233			},
234		},
235	})
236	return graphql.NewSchema(graphql.SchemaConfig{
237		Query: graphql.NewObject(graphql.ObjectConfig{
238			Name: "Query",
239			Fields: graphql.Fields{
240				"f": &graphql.Field{
241					Type: badObject,
242				},
243			},
244		}),
245	})
246}
247func schemaWithInputFieldOfType(ttype graphql.Type) (graphql.Schema, error) {
248
249	badInputObject := graphql.NewInputObject(graphql.InputObjectConfig{
250		Name: "BadInputObject",
251		Fields: graphql.InputObjectConfigFieldMap{
252			"badField": &graphql.InputObjectFieldConfig{
253				Type: ttype,
254			},
255		},
256	})
257	return graphql.NewSchema(graphql.SchemaConfig{
258		Query: graphql.NewObject(graphql.ObjectConfig{
259			Name: "Query",
260			Fields: graphql.Fields{
261				"f": &graphql.Field{
262					Type: graphql.String,
263					Args: graphql.FieldConfigArgument{
264						"badArg": &graphql.ArgumentConfig{
265							Type: badInputObject,
266						},
267					},
268				},
269			},
270		}),
271	})
272}
273
274func TestTypeSystem_SchemaMustHaveObjectRootTypes_AcceptsASchemaWhoseQueryTypeIsAnObjectType(t *testing.T) {
275	_, err := graphql.NewSchema(graphql.SchemaConfig{
276		Query: someObjectType,
277	})
278	if err != nil {
279		t.Fatalf("unexpected error: %v", err)
280	}
281}
282func TestTypeSystem_SchemaMustHaveObjectRootTypes_AcceptsASchemaWhoseQueryAndMutationTypesAreObjectType(t *testing.T) {
283	mutationObject := graphql.NewObject(graphql.ObjectConfig{
284		Name: "Mutation",
285		Fields: graphql.Fields{
286			"edit": &graphql.Field{
287				Type: graphql.String,
288			},
289		},
290	})
291	_, err := graphql.NewSchema(graphql.SchemaConfig{
292		Query:    someObjectType,
293		Mutation: mutationObject,
294	})
295	if err != nil {
296		t.Fatalf("unexpected error: %v", err)
297	}
298}
299func TestTypeSystem_SchemaMustHaveObjectRootTypes_AcceptsASchemaWhoseQueryAndSubscriptionTypesAreObjectType(t *testing.T) {
300	subscriptionType := graphql.NewObject(graphql.ObjectConfig{
301		Name: "Subscription",
302		Fields: graphql.Fields{
303			"subscribe": &graphql.Field{
304				Type: graphql.String,
305			},
306		},
307	})
308	_, err := graphql.NewSchema(graphql.SchemaConfig{
309		Query:    someObjectType,
310		Mutation: subscriptionType,
311	})
312	if err != nil {
313		t.Fatalf("unexpected error: %v", err)
314	}
315}
316func TestTypeSystem_SchemaMustHaveObjectRootTypes_RejectsASchemaWithoutAQueryType(t *testing.T) {
317	_, err := graphql.NewSchema(graphql.SchemaConfig{})
318	expectedError := "Schema query must be Object Type but got: nil."
319	if err == nil || err.Error() != expectedError {
320		t.Fatalf("Expected error: %v, got %v", expectedError, err)
321	}
322}
323
324func TestTypeSystem_SchemaMustContainUniquelyNamedTypes_RejectsASchemaWhichRedefinesABuiltInType(t *testing.T) {
325
326	fakeString := graphql.NewScalar(graphql.ScalarConfig{
327		Name: "String",
328		Serialize: func(value interface{}) interface{} {
329			return nil
330		},
331	})
332	queryType := graphql.NewObject(graphql.ObjectConfig{
333		Name: "Query",
334		Fields: graphql.Fields{
335			"normal": &graphql.Field{
336				Type: graphql.String,
337			},
338			"fake": &graphql.Field{
339				Type: fakeString,
340			},
341		},
342	})
343	_, err := graphql.NewSchema(graphql.SchemaConfig{
344		Query: queryType,
345	})
346	expectedError := `Schema must contain unique named types but contains multiple types named "String".`
347	if err == nil || err.Error() != expectedError {
348		t.Fatalf("Expected error: %v, got %v", expectedError, err)
349	}
350}
351func TestTypeSystem_SchemaMustContainUniquelyNamedTypes_RejectsASchemaWhichDefinesAnObjectTypeTwice(t *testing.T) {
352
353	a := graphql.NewObject(graphql.ObjectConfig{
354		Name: "SameName",
355		Fields: graphql.Fields{
356			"f": &graphql.Field{
357				Type: graphql.String,
358			},
359		},
360	})
361	b := graphql.NewObject(graphql.ObjectConfig{
362		Name: "SameName",
363		Fields: graphql.Fields{
364			"f": &graphql.Field{
365				Type: graphql.String,
366			},
367		},
368	})
369	queryType := graphql.NewObject(graphql.ObjectConfig{
370		Name: "Query",
371		Fields: graphql.Fields{
372			"a": &graphql.Field{
373				Type: a,
374			},
375			"b": &graphql.Field{
376				Type: b,
377			},
378		},
379	})
380	_, err := graphql.NewSchema(graphql.SchemaConfig{
381		Query: queryType,
382	})
383	expectedError := `Schema must contain unique named types but contains multiple types named "SameName".`
384	if err == nil || err.Error() != expectedError {
385		t.Fatalf("Expected error: %v, got %v", expectedError, err)
386	}
387}
388func TestTypeSystem_SchemaMustContainUniquelyNamedTypes_RejectsASchemaWhichHaveSameNamedObjectsImplementingAnInterface(t *testing.T) {
389
390	anotherInterface := graphql.NewInterface(graphql.InterfaceConfig{
391		Name: "AnotherInterface",
392		ResolveType: func(p graphql.ResolveTypeParams) *graphql.Object {
393			return nil
394		},
395		Fields: graphql.Fields{
396			"f": &graphql.Field{
397				Type: graphql.String,
398			},
399		},
400	})
401	FirstBadObject := graphql.NewObject(graphql.ObjectConfig{
402		Name: "BadObject",
403		Interfaces: []*graphql.Interface{
404			anotherInterface,
405		},
406		Fields: graphql.Fields{
407			"f": &graphql.Field{
408				Type: graphql.String,
409			},
410		},
411	})
412	SecondBadObject := graphql.NewObject(graphql.ObjectConfig{
413		Name: "BadObject",
414		Interfaces: []*graphql.Interface{
415			anotherInterface,
416		},
417		Fields: graphql.Fields{
418			"f": &graphql.Field{
419				Type: graphql.String,
420			},
421		},
422	})
423	queryType := graphql.NewObject(graphql.ObjectConfig{
424		Name: "Query",
425		Fields: graphql.Fields{
426			"iface": &graphql.Field{
427				Type: anotherInterface,
428			},
429		},
430	})
431	_, err := graphql.NewSchema(graphql.SchemaConfig{
432		Query: queryType,
433		Types: []graphql.Type{FirstBadObject, SecondBadObject},
434	})
435	expectedError := `Schema must contain unique named types but contains multiple types named "BadObject".`
436	if err == nil || err.Error() != expectedError {
437		t.Fatalf("Expected error: %v, got %v", expectedError, err)
438	}
439}
440
441func TestTypeSystem_ObjectsMustHaveFields_AcceptsAnObjectTypeWithFieldsObject(t *testing.T) {
442	_, err := schemaWithFieldType(graphql.NewObject(graphql.ObjectConfig{
443		Name: "SomeObject",
444		Fields: graphql.Fields{
445			"f": &graphql.Field{
446				Type: graphql.String,
447			},
448		},
449	}))
450	if err != nil {
451		t.Fatalf("unexpected error: %v", err)
452	}
453}
454func TestTypeSystem_ObjectsMustHaveFields_RejectsAnObjectTypeWithMissingFields(t *testing.T) {
455	badObject := graphql.NewObject(graphql.ObjectConfig{
456		Name: "SomeObject",
457	})
458	_, err := schemaWithFieldType(badObject)
459	expectedError := `SomeObject fields must be an object with field names as keys or a function which return such an object.`
460	if err == nil || err.Error() != expectedError {
461		t.Fatalf("Expected error: %v, got %v", expectedError, err)
462	}
463}
464func TestTypeSystem_ObjectsMustHaveFields_RejectsAnObjectTypeWithIncorrectlyNamedFields(t *testing.T) {
465	badObject := graphql.NewObject(graphql.ObjectConfig{
466		Name: "SomeObject",
467		Fields: graphql.Fields{
468			"bad-name-with-dashes": &graphql.Field{
469				Type: graphql.String,
470			},
471		},
472	})
473	_, err := schemaWithFieldType(badObject)
474	expectedError := `Names must match /^[_a-zA-Z][_a-zA-Z0-9]*$/ but "bad-name-with-dashes" does not.`
475	if err == nil || err.Error() != expectedError {
476		t.Fatalf("Expected error: %v, got %v", expectedError, err)
477	}
478}
479func TestTypeSystem_ObjectsMustHaveFields_RejectsAnObjectTypeWithEmptyFields(t *testing.T) {
480	badObject := graphql.NewObject(graphql.ObjectConfig{
481		Name:   "SomeObject",
482		Fields: graphql.Fields{},
483	})
484	_, err := schemaWithFieldType(badObject)
485	expectedError := `SomeObject fields must be an object with field names as keys or a function which return such an object.`
486	if err == nil || err.Error() != expectedError {
487		t.Fatalf("Expected error: %v, got %v", expectedError, err)
488	}
489}
490
491func TestTypeSystem_FieldsArgsMustBeProperlyNamed_AcceptsFieldArgsWithValidNames(t *testing.T) {
492	_, err := schemaWithFieldType(graphql.NewObject(graphql.ObjectConfig{
493		Name: "SomeObject",
494		Fields: graphql.Fields{
495			"goodField": &graphql.Field{
496				Type: graphql.String,
497				Args: graphql.FieldConfigArgument{
498					"goodArgs": &graphql.ArgumentConfig{
499						Type: graphql.String,
500					},
501				},
502			},
503		},
504	}))
505	if err != nil {
506		t.Fatalf("unexpected error: %v", err)
507	}
508}
509func TestTypeSystem_FieldsArgsMustBeProperlyNamed_RejectsFieldArgWithInvalidNames(t *testing.T) {
510	_, err := schemaWithFieldType(graphql.NewObject(graphql.ObjectConfig{
511		Name: "SomeObject",
512		Fields: graphql.Fields{
513			"badField": &graphql.Field{
514				Type: graphql.String,
515				Args: graphql.FieldConfigArgument{
516					"bad-name-with-dashes": &graphql.ArgumentConfig{
517						Type: graphql.String,
518					},
519				},
520			},
521		},
522	}))
523	expectedError := `Names must match /^[_a-zA-Z][_a-zA-Z0-9]*$/ but "bad-name-with-dashes" does not.`
524	if err == nil || err.Error() != expectedError {
525		t.Fatalf("Expected error: %v, got %v", expectedError, err)
526	}
527}
528
529func TestTypeSystem_FieldsArgsMustBeObjects_AcceptsAnObjectTypeWithFieldArgs(t *testing.T) {
530	_, err := schemaWithFieldType(graphql.NewObject(graphql.ObjectConfig{
531		Name: "SomeObject",
532		Fields: graphql.Fields{
533			"goodField": &graphql.Field{
534				Type: graphql.String,
535				Args: graphql.FieldConfigArgument{
536					"goodArgs": &graphql.ArgumentConfig{
537						Type: graphql.String,
538					},
539				},
540			},
541		},
542	}))
543	if err != nil {
544		t.Fatalf("unexpected error: %v", err)
545	}
546}
547
548func TestTypeSystem_ObjectInterfacesMustBeArray_AcceptsAnObjectTypeWithArrayInterfaces(t *testing.T) {
549	anotherInterfaceType := graphql.NewInterface(graphql.InterfaceConfig{
550		Name: "AnotherInterface",
551		ResolveType: func(p graphql.ResolveTypeParams) *graphql.Object {
552			return nil
553		},
554		Fields: graphql.Fields{
555			"f": &graphql.Field{
556				Type: graphql.String,
557			},
558		},
559	})
560	_, err := schemaWithFieldType(graphql.NewObject(graphql.ObjectConfig{
561		Name: "SomeObject",
562		Interfaces: (graphql.InterfacesThunk)(func() []*graphql.Interface {
563			return []*graphql.Interface{anotherInterfaceType}
564		}),
565		Fields: graphql.Fields{
566			"f": &graphql.Field{
567				Type: graphql.String,
568			},
569		},
570	}))
571	if err != nil {
572		t.Fatalf("unexpected error: %v", err)
573	}
574}
575
576func TestTypeSystem_ObjectInterfacesMustBeArray_AcceptsAnObjectTypeWithInterfacesAsFunctionReturningAnArray(t *testing.T) {
577	anotherInterfaceType := graphql.NewInterface(graphql.InterfaceConfig{
578		Name: "AnotherInterface",
579		ResolveType: func(p graphql.ResolveTypeParams) *graphql.Object {
580			return nil
581		},
582		Fields: graphql.Fields{
583			"f": &graphql.Field{
584				Type: graphql.String,
585			},
586		},
587	})
588	_, err := schemaWithFieldType(graphql.NewObject(graphql.ObjectConfig{
589		Name:       "SomeObject",
590		Interfaces: []*graphql.Interface{anotherInterfaceType},
591		Fields: graphql.Fields{
592			"f": &graphql.Field{
593				Type: graphql.String,
594			},
595		},
596	}))
597	if err != nil {
598		t.Fatalf("unexpected error: %v", err)
599	}
600}
601
602func TestTypeSystem_UnionTypesMustBeArray_AcceptsAUnionTypeWithArrayTypes(t *testing.T) {
603	_, err := schemaWithFieldType(graphql.NewUnion(graphql.UnionConfig{
604		Name: "SomeUnion",
605		ResolveType: func(p graphql.ResolveTypeParams) *graphql.Object {
606			return nil
607		},
608		Types: []*graphql.Object{
609			someObjectType,
610		},
611	}))
612	if err != nil {
613		t.Fatalf("unexpected error: %v", err)
614	}
615}
616func TestTypeSystem_UnionTypesMustBeArray_RejectsAUnionTypeWithoutTypes(t *testing.T) {
617	_, err := schemaWithFieldType(graphql.NewUnion(graphql.UnionConfig{
618		Name: "SomeUnion",
619		ResolveType: func(p graphql.ResolveTypeParams) *graphql.Object {
620			return nil
621		},
622	}))
623	expectedError := "Must provide Array of types for Union SomeUnion."
624	if err == nil || err.Error() != expectedError {
625		t.Fatalf("Expected error: %v, got %v", expectedError, err)
626	}
627}
628func TestTypeSystem_UnionTypesMustBeArray_RejectsAUnionTypeWithEmptyTypes(t *testing.T) {
629	_, err := schemaWithFieldType(graphql.NewUnion(graphql.UnionConfig{
630		Name: "SomeUnion",
631		ResolveType: func(p graphql.ResolveTypeParams) *graphql.Object {
632			return nil
633		},
634		Types: []*graphql.Object{},
635	}))
636	expectedError := "Must provide Array of types for Union SomeUnion."
637	if err == nil || err.Error() != expectedError {
638		t.Fatalf("Expected error: %v, got %v", expectedError, err)
639	}
640}
641
642func TestTypeSystem_InputObjectsMustHaveFields_AcceptsAnInputObjectTypeWithFields(t *testing.T) {
643	_, err := schemaWithInputObject(graphql.NewInputObject(graphql.InputObjectConfig{
644		Name: "SomeInputObject",
645		Fields: graphql.InputObjectConfigFieldMap{
646			"f": &graphql.InputObjectFieldConfig{
647				Type: graphql.String,
648			},
649		},
650	}))
651	if err != nil {
652		t.Fatalf("unexpected error: %v", err)
653	}
654}
655
656func TestTypeSystem_InputObjectsMustHaveFields_AcceptsAnInputObjectTypeWithAFieldFunction(t *testing.T) {
657	_, err := schemaWithInputObject(graphql.NewInputObject(graphql.InputObjectConfig{
658		Name: "SomeInputObject",
659		Fields: (graphql.InputObjectConfigFieldMapThunk)(func() graphql.InputObjectConfigFieldMap {
660			return graphql.InputObjectConfigFieldMap{
661				"f": &graphql.InputObjectFieldConfig{
662					Type: graphql.String,
663				},
664			}
665		}),
666	}))
667	if err != nil {
668		t.Fatalf("unexpected error: %v", err)
669	}
670}
671
672func TestTypeSystem_InputObjectsMustHaveFields_RejectsAnInputObjectTypeWithMissingFields(t *testing.T) {
673	_, err := schemaWithInputObject(graphql.NewInputObject(graphql.InputObjectConfig{
674		Name: "SomeInputObject",
675	}))
676	expectedError := "SomeInputObject fields must be an object with field names as keys or a function which return such an object."
677	if err == nil || err.Error() != expectedError {
678		t.Fatalf("Expected error: %v, got %v", expectedError, err)
679	}
680}
681func TestTypeSystem_InputObjectsMustHaveFields_RejectsAnInputObjectTypeWithEmptyFields(t *testing.T) {
682	_, err := schemaWithInputObject(graphql.NewInputObject(graphql.InputObjectConfig{
683		Name:   "SomeInputObject",
684		Fields: graphql.InputObjectConfigFieldMap{},
685	}))
686	expectedError := "SomeInputObject fields must be an object with field names as keys or a function which return such an object."
687	if err == nil || err.Error() != expectedError {
688		t.Fatalf("Expected error: %v, got %v", expectedError, err)
689	}
690}
691
692func TestTypeSystem_ObjectTypesMustBeAssertable_AcceptsAnObjectTypeWithAnIsTypeOfFunction(t *testing.T) {
693	_, err := schemaWithFieldType(graphql.NewObject(graphql.ObjectConfig{
694		Name: "AnotherObject",
695		IsTypeOf: func(p graphql.IsTypeOfParams) bool {
696			return true
697		},
698		Fields: graphql.Fields{
699			"f": &graphql.Field{
700				Type: graphql.String,
701			},
702		},
703	}))
704	if err != nil {
705		t.Fatalf("unexpected error: %v", err)
706	}
707}
708
709func TestTypeSystem_InterfaceTypesMustBeResolvable_AcceptsAnInterfaceTypeDefiningResolveType(t *testing.T) {
710
711	anotherInterfaceType := graphql.NewInterface(graphql.InterfaceConfig{
712		Name: "AnotherInterface",
713		ResolveType: func(p graphql.ResolveTypeParams) *graphql.Object {
714			return nil
715		},
716		Fields: graphql.Fields{
717			"f": &graphql.Field{
718				Type: graphql.String,
719			},
720		},
721	})
722	_, err := schemaWithFieldType(graphql.NewObject(graphql.ObjectConfig{
723		Name:       "SomeObject",
724		Interfaces: []*graphql.Interface{anotherInterfaceType},
725		Fields: graphql.Fields{
726			"f": &graphql.Field{
727				Type: graphql.String,
728			},
729		},
730	}))
731	if err != nil {
732		t.Fatalf("unexpected error: %v", err)
733	}
734}
735func TestTypeSystem_InterfaceTypesMustBeResolvable_AcceptsAnInterfaceWithImplementingTypeDefiningIsTypeOf(t *testing.T) {
736
737	anotherInterfaceType := graphql.NewInterface(graphql.InterfaceConfig{
738		Name: "AnotherInterface",
739		Fields: graphql.Fields{
740			"f": &graphql.Field{
741				Type: graphql.String,
742			},
743		},
744	})
745	_, err := schemaWithFieldType(graphql.NewObject(graphql.ObjectConfig{
746		Name:       "SomeObject",
747		Interfaces: []*graphql.Interface{anotherInterfaceType},
748		IsTypeOf: func(p graphql.IsTypeOfParams) bool {
749			return true
750		},
751		Fields: graphql.Fields{
752			"f": &graphql.Field{
753				Type: graphql.String,
754			},
755		},
756	}))
757	if err != nil {
758		t.Fatalf("unexpected error: %v", err)
759	}
760}
761
762func TestTypeSystem_InterfaceTypesMustBeResolvable_AcceptsAnInterfaceTypeDefiningResolveTypeWithImplementingTypeDefiningIsTypeOf(t *testing.T) {
763
764	anotherInterfaceType := graphql.NewInterface(graphql.InterfaceConfig{
765		Name: "AnotherInterface",
766		ResolveType: func(p graphql.ResolveTypeParams) *graphql.Object {
767			return nil
768		},
769		Fields: graphql.Fields{
770			"f": &graphql.Field{
771				Type: graphql.String,
772			},
773		},
774	})
775	_, err := schemaWithFieldType(graphql.NewObject(graphql.ObjectConfig{
776		Name:       "SomeObject",
777		Interfaces: []*graphql.Interface{anotherInterfaceType},
778		IsTypeOf: func(p graphql.IsTypeOfParams) bool {
779			return true
780		},
781		Fields: graphql.Fields{
782			"f": &graphql.Field{
783				Type: graphql.String,
784			},
785		},
786	}))
787	if err != nil {
788		t.Fatalf("unexpected error: %v", err)
789	}
790}
791
792func TestTypeSystem_UnionTypesMustBeResolvable_AcceptsAUnionTypeDefiningResolveType(t *testing.T) {
793
794	_, err := schemaWithFieldType(graphql.NewUnion(graphql.UnionConfig{
795		Name:  "SomeUnion",
796		Types: []*graphql.Object{someObjectType},
797		ResolveType: func(p graphql.ResolveTypeParams) *graphql.Object {
798			return nil
799		},
800	}))
801	if err != nil {
802		t.Fatalf("unexpected error: %v", err)
803	}
804}
805func TestTypeSystem_UnionTypesMustBeResolvable_AcceptsAUnionOfObjectTypesDefiningIsTypeOf(t *testing.T) {
806
807	_, err := schemaWithFieldType(graphql.NewUnion(graphql.UnionConfig{
808		Name:  "SomeUnion",
809		Types: []*graphql.Object{objectWithIsTypeOf},
810	}))
811	if err != nil {
812		t.Fatalf("unexpected error: %v", err)
813	}
814}
815func TestTypeSystem_UnionTypesMustBeResolvable_AcceptsAUnionTypeDefiningResolveTypeOfObjectTypesDefiningIsTypeOf(t *testing.T) {
816
817	_, err := schemaWithFieldType(graphql.NewUnion(graphql.UnionConfig{
818		Name:  "SomeUnion",
819		Types: []*graphql.Object{objectWithIsTypeOf},
820		ResolveType: func(p graphql.ResolveTypeParams) *graphql.Object {
821			return nil
822		},
823	}))
824	if err != nil {
825		t.Fatalf("unexpected error: %v", err)
826	}
827}
828func TestTypeSystem_UnionTypesMustBeResolvable_RejectsAUnionTypeNotDefiningResolveTypeOfObjectTypesNotDefiningIsTypeOf(t *testing.T) {
829
830	_, err := schemaWithFieldType(graphql.NewUnion(graphql.UnionConfig{
831		Name:  "SomeUnion",
832		Types: []*graphql.Object{someObjectType},
833	}))
834	expectedError := `Union Type SomeUnion does not provide a "resolveType" function and ` +
835		`possible Type SomeObject does not provide a "isTypeOf" function. ` +
836		`There is no way to resolve this possible type during execution.`
837	if err == nil || err.Error() != expectedError {
838		t.Fatalf("Expected error: %v, got %v", expectedError, err)
839	}
840}
841
842func TestTypeSystem_ScalarTypesMustBeSerializable_AcceptsAScalarTypeDefiningSerialize(t *testing.T) {
843
844	_, err := schemaWithFieldType(graphql.NewScalar(graphql.ScalarConfig{
845		Name: "SomeScalar",
846		Serialize: func(value interface{}) interface{} {
847			return nil
848		},
849	}))
850	if err != nil {
851		t.Fatalf("unexpected error: %v", err)
852	}
853}
854func TestTypeSystem_ScalarTypesMustBeSerializable_RejectsAScalarTypeNotDefiningSerialize(t *testing.T) {
855
856	_, err := schemaWithFieldType(graphql.NewScalar(graphql.ScalarConfig{
857		Name: "SomeScalar",
858	}))
859	expectedError := `SomeScalar must provide "serialize" function. If this custom Scalar ` +
860		`is also used as an input type, ensure "parseValue" and "parseLiteral" ` +
861		`functions are also provided.`
862	if err == nil || err.Error() != expectedError {
863		t.Fatalf("Expected error: %v, got %v", expectedError, err)
864	}
865}
866func TestTypeSystem_ScalarTypesMustBeSerializable_AcceptsAScalarTypeDefiningParseValueAndParseLiteral(t *testing.T) {
867
868	_, err := schemaWithFieldType(graphql.NewScalar(graphql.ScalarConfig{
869		Name: "SomeScalar",
870		Serialize: func(value interface{}) interface{} {
871			return nil
872		},
873		ParseValue: func(value interface{}) interface{} {
874			return nil
875		},
876		ParseLiteral: func(valueAST ast.Value) interface{} {
877			return nil
878		},
879	}))
880	if err != nil {
881		t.Fatalf("unexpected error: %v", err)
882	}
883}
884func TestTypeSystem_ScalarTypesMustBeSerializable_RejectsAScalarTypeDefiningParseValueButNotParseLiteral(t *testing.T) {
885
886	_, err := schemaWithFieldType(graphql.NewScalar(graphql.ScalarConfig{
887		Name: "SomeScalar",
888		Serialize: func(value interface{}) interface{} {
889			return nil
890		},
891		ParseValue: func(value interface{}) interface{} {
892			return nil
893		},
894	}))
895	expectedError := `SomeScalar must provide both "parseValue" and "parseLiteral" functions.`
896	if err == nil || err.Error() != expectedError {
897		t.Fatalf("Expected error: %v, got %v", expectedError, err)
898	}
899}
900func TestTypeSystem_ScalarTypesMustBeSerializable_RejectsAScalarTypeDefiningParseLiteralButNotParseValue(t *testing.T) {
901
902	_, err := schemaWithFieldType(graphql.NewScalar(graphql.ScalarConfig{
903		Name: "SomeScalar",
904		Serialize: func(value interface{}) interface{} {
905			return nil
906		},
907		ParseLiteral: func(valueAST ast.Value) interface{} {
908			return nil
909		},
910	}))
911	expectedError := `SomeScalar must provide both "parseValue" and "parseLiteral" functions.`
912	if err == nil || err.Error() != expectedError {
913		t.Fatalf("Expected error: %v, got %v", expectedError, err)
914	}
915}
916
917func TestTypeSystem_EnumTypesMustBeWellDefined_AcceptsAWellDefinedEnumTypeWithEmptyValueDefinition(t *testing.T) {
918
919	_, err := schemaWithFieldType(graphql.NewEnum(graphql.EnumConfig{
920		Name: "SomeEnum",
921		Values: graphql.EnumValueConfigMap{
922			"FOO": &graphql.EnumValueConfig{},
923			"BAR": &graphql.EnumValueConfig{},
924		},
925	}))
926	if err != nil {
927		t.Fatalf("unexpected error: %v", err)
928	}
929}
930func TestTypeSystem_EnumTypesMustBeWellDefined_AcceptsAWellDefinedEnumTypeWithInternalValueDefinition(t *testing.T) {
931
932	_, err := schemaWithFieldType(graphql.NewEnum(graphql.EnumConfig{
933		Name: "SomeEnum",
934		Values: graphql.EnumValueConfigMap{
935			"FOO": &graphql.EnumValueConfig{
936				Value: 10,
937			},
938			"BAR": &graphql.EnumValueConfig{
939				Value: 20,
940			},
941		},
942	}))
943	if err != nil {
944		t.Fatalf("unexpected error: %v", err)
945	}
946}
947func TestTypeSystem_EnumTypesMustBeWellDefined_RejectsAnEnumTypeWithoutValues(t *testing.T) {
948
949	_, err := schemaWithFieldType(graphql.NewEnum(graphql.EnumConfig{
950		Name: "SomeEnum",
951	}))
952	expectedError := `SomeEnum values must be an object with value names as keys.`
953	if err == nil || err.Error() != expectedError {
954		t.Fatalf("Expected error: %v, got %v", expectedError, err)
955	}
956}
957func TestTypeSystem_EnumTypesMustBeWellDefined_RejectsAnEnumTypeWithEmptyValues(t *testing.T) {
958
959	_, err := schemaWithFieldType(graphql.NewEnum(graphql.EnumConfig{
960		Name:   "SomeEnum",
961		Values: graphql.EnumValueConfigMap{},
962	}))
963	expectedError := `SomeEnum values must be an object with value names as keys.`
964	if err == nil || err.Error() != expectedError {
965		t.Fatalf("Expected error: %v, got %v", expectedError, err)
966	}
967}
968
969func TestTypeSystem_ObjectFieldsMustHaveOutputTypes_AcceptAnOutputTypeAsAnObjectFieldType(t *testing.T) {
970	for _, ttype := range outputTypes {
971		_, err := schemaWithObjectFieldOfType(ttype)
972		if err != nil {
973			t.Fatalf(`unexpected error: %v for type "%v"`, err, ttype)
974		}
975	}
976}
977func TestTypeSystem_ObjectFieldsMustHaveOutputTypes_RejectsAnEmptyObjectFieldType(t *testing.T) {
978	_, err := schemaWithObjectFieldOfType(nil)
979	expectedError := `BadObject.badField field type must be Output Type but got: <nil>.`
980	if err == nil || err.Error() != expectedError {
981		t.Fatalf("Expected error: %v, got %v", expectedError, err)
982	}
983}
984
985func TestTypeSystem_ObjectsCanOnlyImplementInterfaces_AcceptsAnObjectImplementingAnInterface(t *testing.T) {
986	anotherInterfaceType := graphql.NewInterface(graphql.InterfaceConfig{
987		Name: "AnotherInterface",
988		ResolveType: func(p graphql.ResolveTypeParams) *graphql.Object {
989			return nil
990		},
991		Fields: graphql.Fields{
992			"f": &graphql.Field{
993				Type: graphql.String,
994			},
995		},
996	})
997	_, err := schemaWithObjectImplementingType(anotherInterfaceType)
998	if err != nil {
999		t.Fatalf(`unexpected error: %v"`, err)
1000	}
1001}
1002func TestTypeSystem_ObjectsCanOnlyImplementInterfaces_RejectsAnObjectImplementingANonInterfaceType(t *testing.T) {
1003	_, err := schemaWithObjectImplementingType(nil)
1004	expectedError := `BadObject may only implement Interface types, it cannot implement: <nil>.`
1005	if err == nil || err.Error() != expectedError {
1006		t.Fatalf("Expected error: %v, got %v", expectedError, err)
1007	}
1008}
1009
1010func TestTypeSystem_UnionsMustRepresentObjectTypes_AcceptsAUnionOfAnObjectType(t *testing.T) {
1011	_, err := schemaWithUnionOfType(someObjectType)
1012	if err != nil {
1013		t.Fatalf(`unexpected error: %v"`, err)
1014	}
1015}
1016func TestTypeSystem_UnionsMustRepresentObjectTypes_RejectsAUnionOfNonObjectTypes(t *testing.T) {
1017	_, err := schemaWithUnionOfType(nil)
1018	expectedError := `BadUnion may only contain Object types, it cannot contain: <nil>.`
1019	if err == nil || err.Error() != expectedError {
1020		t.Fatalf("Expected error: %v, got %v", expectedError, err)
1021	}
1022}
1023
1024func TestTypeSystem_InterfaceFieldsMustHaveOutputTypes_AcceptsAnOutputTypeAsAnInterfaceFieldType(t *testing.T) {
1025	for _, ttype := range outputTypes {
1026		_, err := schemaWithInterfaceFieldOfType(ttype)
1027		if err != nil {
1028			t.Fatalf(`unexpected error: %v for type "%v"`, err, ttype)
1029		}
1030	}
1031}
1032func TestTypeSystem_InterfaceFieldsMustHaveOutputTypes_RejectsAnEmptyInterfaceFieldType(t *testing.T) {
1033	_, err := schemaWithInterfaceFieldOfType(nil)
1034	expectedError := `BadInterface.badField field type must be Output Type but got: <nil>.`
1035	if err == nil || err.Error() != expectedError {
1036		t.Fatalf("Expected error: %v, got %v", expectedError, err)
1037	}
1038}
1039
1040func TestTypeSystem_FieldArgumentsMustHaveInputTypes_AcceptsAnInputTypeAsFieldArgType(t *testing.T) {
1041	for _, ttype := range inputTypes {
1042		_, err := schemaWithArgOfType(ttype)
1043		if err != nil {
1044			t.Fatalf(`unexpected error: %v for type "%v"`, err, ttype)
1045		}
1046	}
1047}
1048func TestTypeSystem_FieldArgumentsMustHaveInputTypes_RejectsAnEmptyFieldArgType(t *testing.T) {
1049	_, err := schemaWithArgOfType(nil)
1050	expectedError := `BadObject.badField(badArg:) argument type must be Input Type but got: <nil>.`
1051	if err == nil || err.Error() != expectedError {
1052		t.Fatalf("Expected error: %v, got %v", expectedError, err)
1053	}
1054}
1055
1056func TestTypeSystem_InputObjectFieldsMustHaveInputTypes_AcceptsAnInputTypeAsInputFieldType(t *testing.T) {
1057	for _, ttype := range inputTypes {
1058		_, err := schemaWithInputFieldOfType(ttype)
1059		if err != nil {
1060			t.Fatalf(`unexpected error: %v for type "%v"`, err, ttype)
1061		}
1062	}
1063}
1064func TestTypeSystem_InputObjectFieldsMustHaveInputTypes_RejectsAnEmptyInputFieldType(t *testing.T) {
1065	_, err := schemaWithInputFieldOfType(nil)
1066	expectedError := `BadInputObject.badField field type must be Input Type but got: <nil>.`
1067	if err == nil || err.Error() != expectedError {
1068		t.Fatalf("Expected error: %v, got %v", expectedError, err)
1069	}
1070}
1071
1072func TestTypeSystem_ListMustAcceptGraphQLTypes_AcceptsAnTypeAsItemTypeOfList(t *testing.T) {
1073	testTypes := withModifiers([]graphql.Type{
1074		graphql.String,
1075		someScalarType,
1076		someEnumType,
1077		someObjectType,
1078		someUnionType,
1079		someInterfaceType,
1080	})
1081	for _, ttype := range testTypes {
1082		result := graphql.NewList(ttype)
1083		if result.Error() != nil {
1084			t.Fatalf(`unexpected error: %v for type "%v"`, result.Error(), ttype)
1085		}
1086	}
1087}
1088func TestTypeSystem_ListMustAcceptGraphQLTypes_RejectsANilTypeAsItemTypeOfList(t *testing.T) {
1089	result := graphql.NewList(nil)
1090	expectedError := `Can only create List of a Type but got: <nil>.`
1091	if result.Error() == nil || result.Error().Error() != expectedError {
1092		t.Fatalf("Expected error: %v, got %v", expectedError, result.Error())
1093	}
1094}
1095
1096func TestTypeSystem_NonNullMustAcceptGraphQLTypes_AcceptsAnTypeAsNullableTypeOfNonNull(t *testing.T) {
1097	nullableTypes := []graphql.Type{
1098		graphql.String,
1099		someScalarType,
1100		someObjectType,
1101		someUnionType,
1102		someInterfaceType,
1103		someEnumType,
1104		someInputObject,
1105		graphql.NewList(graphql.String),
1106		graphql.NewList(graphql.NewNonNull(graphql.String)),
1107	}
1108	for _, ttype := range nullableTypes {
1109		result := graphql.NewNonNull(ttype)
1110		if result.Error() != nil {
1111			t.Fatalf(`unexpected error: %v for type "%v"`, result.Error(), ttype)
1112		}
1113	}
1114}
1115func TestTypeSystem_NonNullMustAcceptGraphQLTypes_RejectsNilAsNonNullableType(t *testing.T) {
1116	result := graphql.NewNonNull(nil)
1117	expectedError := `Can only create NonNull of a Nullable Type but got: <nil>.`
1118	if result.Error() == nil || result.Error().Error() != expectedError {
1119		t.Fatalf("Expected error: %v, got %v", expectedError, result.Error())
1120	}
1121}
1122
1123func TestTypeSystem_ObjectsMustAdhereToInterfaceTheyImplement_AcceptsAnObjectWhichImplementsAnInterface(t *testing.T) {
1124	anotherInterface := graphql.NewInterface(graphql.InterfaceConfig{
1125		Name: "AnotherInterface",
1126		ResolveType: func(p graphql.ResolveTypeParams) *graphql.Object {
1127			return nil
1128		},
1129		Fields: graphql.Fields{
1130			"field": &graphql.Field{
1131				Type: graphql.String,
1132				Args: graphql.FieldConfigArgument{
1133					"input": &graphql.ArgumentConfig{
1134						Type: graphql.String,
1135					},
1136				},
1137			},
1138		},
1139	})
1140	anotherObject := graphql.NewObject(graphql.ObjectConfig{
1141		Name:       "AnotherObject",
1142		Interfaces: []*graphql.Interface{anotherInterface},
1143		Fields: graphql.Fields{
1144			"field": &graphql.Field{
1145				Type: graphql.String,
1146				Args: graphql.FieldConfigArgument{
1147					"input": &graphql.ArgumentConfig{
1148						Type: graphql.String,
1149					},
1150				},
1151			},
1152		},
1153	})
1154	_, err := schemaWithObjectFieldOfType(anotherObject)
1155	if err != nil {
1156		t.Fatalf(`unexpected error: %v for type "%v"`, err, anotherObject)
1157	}
1158}
1159func TestTypeSystem_ObjectsMustAdhereToInterfaceTheyImplement_AcceptsAnObjectWhichImplementsAnInterfaceAlongWithMoreFields(t *testing.T) {
1160	anotherInterface := graphql.NewInterface(graphql.InterfaceConfig{
1161		Name: "AnotherInterface",
1162		ResolveType: func(p graphql.ResolveTypeParams) *graphql.Object {
1163			return nil
1164		},
1165		Fields: graphql.Fields{
1166			"field": &graphql.Field{
1167				Type: graphql.String,
1168				Args: graphql.FieldConfigArgument{
1169					"input": &graphql.ArgumentConfig{
1170						Type: graphql.String,
1171					},
1172				},
1173			},
1174		},
1175	})
1176	anotherObject := graphql.NewObject(graphql.ObjectConfig{
1177		Name:       "AnotherObject",
1178		Interfaces: []*graphql.Interface{anotherInterface},
1179		Fields: graphql.Fields{
1180			"field": &graphql.Field{
1181				Type: graphql.String,
1182				Args: graphql.FieldConfigArgument{
1183					"input": &graphql.ArgumentConfig{
1184						Type: graphql.String,
1185					},
1186				},
1187			},
1188			"anotherfield": &graphql.Field{
1189				Type: graphql.String,
1190			},
1191		},
1192	})
1193	_, err := schemaWithObjectFieldOfType(anotherObject)
1194	if err != nil {
1195		t.Fatalf(`unexpected error: %v for type "%v"`, err, anotherObject)
1196	}
1197}
1198func TestTypeSystem_ObjectsMustAdhereToInterfaceTheyImplement_AcceptsAnObjectWhichImpementsAnInterfaceFieldAlongWithAdditionalOptionalArguments(t *testing.T) {
1199	anotherInterface := graphql.NewInterface(graphql.InterfaceConfig{
1200		Name: "AnotherInterface",
1201		ResolveType: func(p graphql.ResolveTypeParams) *graphql.Object {
1202			return nil
1203		},
1204		Fields: graphql.Fields{
1205			"field": &graphql.Field{
1206				Type: graphql.String,
1207				Args: graphql.FieldConfigArgument{
1208					"input": &graphql.ArgumentConfig{
1209						Type: graphql.String,
1210					},
1211				},
1212			},
1213		},
1214	})
1215	anotherObject := graphql.NewObject(graphql.ObjectConfig{
1216		Name:       "AnotherObject",
1217		Interfaces: []*graphql.Interface{anotherInterface},
1218		Fields: graphql.Fields{
1219			"field": &graphql.Field{
1220				Type: graphql.String,
1221				Args: graphql.FieldConfigArgument{
1222					"input": &graphql.ArgumentConfig{
1223						Type: graphql.String,
1224					},
1225					"anotherInput": &graphql.ArgumentConfig{
1226						Type: graphql.String,
1227					},
1228				},
1229			},
1230		},
1231	})
1232	_, err := schemaWithObjectFieldOfType(anotherObject)
1233	if err != nil {
1234		t.Fatalf(`unexpected error: %v for type "%v"`, err, anotherObject)
1235	}
1236}
1237func TestTypeSystem_ObjectsMustAdhereToInterfaceTheyImplement_RejectsAnObjectWhichImplementsAnInterfaceFieldAlongWithAdditionalRequiredArguments(t *testing.T) {
1238	anotherInterface := graphql.NewInterface(graphql.InterfaceConfig{
1239		Name: "AnotherInterface",
1240		ResolveType: func(p graphql.ResolveTypeParams) *graphql.Object {
1241			return nil
1242		},
1243		Fields: graphql.Fields{
1244			"field": &graphql.Field{
1245				Type: graphql.String,
1246				Args: graphql.FieldConfigArgument{
1247					"input": &graphql.ArgumentConfig{
1248						Type: graphql.String,
1249					},
1250				},
1251			},
1252		},
1253	})
1254	anotherObject := graphql.NewObject(graphql.ObjectConfig{
1255		Name:       "AnotherObject",
1256		Interfaces: []*graphql.Interface{anotherInterface},
1257		Fields: graphql.Fields{
1258			"field": &graphql.Field{
1259				Type: graphql.String,
1260				Args: graphql.FieldConfigArgument{
1261					"input": &graphql.ArgumentConfig{
1262						Type: graphql.String,
1263					},
1264					"anotherInput": &graphql.ArgumentConfig{
1265						Type: graphql.NewNonNull(graphql.String),
1266					},
1267				},
1268			},
1269		},
1270	})
1271	_, err := schemaWithObjectFieldOfType(anotherObject)
1272	expectedError := `AnotherObject.field(anotherInput:) is of required type "String!" but is not also provided by the interface AnotherInterface.field.`
1273	if err == nil || err.Error() != expectedError {
1274		t.Fatalf("Expected error: %v, got %v", expectedError, err)
1275	}
1276}
1277func TestTypeSystem_ObjectsMustAdhereToInterfaceTheyImplement_RejectsAnObjectMissingAnInterfaceField(t *testing.T) {
1278	anotherInterface := graphql.NewInterface(graphql.InterfaceConfig{
1279		Name: "AnotherInterface",
1280		ResolveType: func(p graphql.ResolveTypeParams) *graphql.Object {
1281			return nil
1282		},
1283		Fields: graphql.Fields{
1284			"field": &graphql.Field{
1285				Type: graphql.String,
1286				Args: graphql.FieldConfigArgument{
1287					"input": &graphql.ArgumentConfig{
1288						Type: graphql.String,
1289					},
1290				},
1291			},
1292		},
1293	})
1294	anotherObject := graphql.NewObject(graphql.ObjectConfig{
1295		Name:       "AnotherObject",
1296		Interfaces: []*graphql.Interface{anotherInterface},
1297		Fields: graphql.Fields{
1298			"anotherfield": &graphql.Field{
1299				Type: graphql.String,
1300			},
1301		},
1302	})
1303	_, err := schemaWithObjectFieldOfType(anotherObject)
1304	expectedError := `"AnotherInterface" expects field "field" but "AnotherObject" does not provide it.`
1305	if err == nil || err.Error() != expectedError {
1306		t.Fatalf("Expected error: %v, got %v", expectedError, err)
1307	}
1308}
1309
1310func TestTypeSystem_ObjectsMustAdhereToInterfaceTheyImplement_RejectsAnObjectWithAnIncorrectlyTypedInterfaceField(t *testing.T) {
1311	anotherInterface := graphql.NewInterface(graphql.InterfaceConfig{
1312		Name: "AnotherInterface",
1313		ResolveType: func(p graphql.ResolveTypeParams) *graphql.Object {
1314			return nil
1315		},
1316		Fields: graphql.Fields{
1317			"field": &graphql.Field{
1318				Type: graphql.String,
1319			},
1320		},
1321	})
1322	anotherObject := graphql.NewObject(graphql.ObjectConfig{
1323		Name:       "AnotherObject",
1324		Interfaces: []*graphql.Interface{anotherInterface},
1325		Fields: graphql.Fields{
1326			"field": &graphql.Field{
1327				Type: someScalarType,
1328			},
1329		},
1330	})
1331	_, err := schemaWithObjectFieldOfType(anotherObject)
1332	expectedError := `AnotherInterface.field expects type "String" but AnotherObject.field provides type "SomeScalar".`
1333	if err == nil || err.Error() != expectedError {
1334		t.Fatalf("Expected error: %v, got %v", expectedError, err)
1335	}
1336}
1337
1338func TestTypeSystem_ObjectsMustAdhereToInterfaceTheyImplement_RejectsAnObjectWithADifferentlyTypeInterfaceField(t *testing.T) {
1339
1340	typeA := graphql.NewObject(graphql.ObjectConfig{
1341		Name: "A",
1342		Fields: graphql.Fields{
1343			"foo": &graphql.Field{
1344				Type: graphql.String,
1345			},
1346		},
1347	})
1348	typeB := graphql.NewObject(graphql.ObjectConfig{
1349		Name: "B",
1350		Fields: graphql.Fields{
1351			"foo": &graphql.Field{
1352				Type: graphql.String,
1353			},
1354		},
1355	})
1356
1357	anotherInterface := graphql.NewInterface(graphql.InterfaceConfig{
1358		Name: "AnotherInterface",
1359		ResolveType: func(p graphql.ResolveTypeParams) *graphql.Object {
1360			return nil
1361		},
1362		Fields: graphql.Fields{
1363			"field": &graphql.Field{
1364				Type: typeA,
1365			},
1366		},
1367	})
1368	anotherObject := graphql.NewObject(graphql.ObjectConfig{
1369		Name:       "AnotherObject",
1370		Interfaces: []*graphql.Interface{anotherInterface},
1371		Fields: graphql.Fields{
1372			"field": &graphql.Field{
1373				Type: typeB,
1374			},
1375		},
1376	})
1377	_, err := schemaWithObjectFieldOfType(anotherObject)
1378	expectedError := `AnotherInterface.field expects type "A" but AnotherObject.field provides type "B".`
1379	if err == nil || err.Error() != expectedError {
1380		t.Fatalf("Expected error: %v, got %v", expectedError, err)
1381	}
1382}
1383
1384func TestTypeSystem_ObjectsMustAdhereToInterfaceTheyImplement_AcceptsAnObjectWithASubtypedInterfaceField_Interface(t *testing.T) {
1385	var anotherInterface *graphql.Interface
1386	anotherInterface = graphql.NewInterface(graphql.InterfaceConfig{
1387		Name: "AnotherInterface",
1388		ResolveType: func(p graphql.ResolveTypeParams) *graphql.Object {
1389			return nil
1390		},
1391		Fields: (graphql.FieldsThunk)(func() graphql.Fields {
1392			return graphql.Fields{
1393				"field": &graphql.Field{
1394					Type: anotherInterface,
1395				},
1396			}
1397		}),
1398	})
1399	var anotherObject *graphql.Object
1400	anotherObject = graphql.NewObject(graphql.ObjectConfig{
1401		Name:       "AnotherObject",
1402		Interfaces: []*graphql.Interface{anotherInterface},
1403		Fields: (graphql.FieldsThunk)(func() graphql.Fields {
1404			return graphql.Fields{
1405				"field": &graphql.Field{
1406					Type: anotherObject,
1407				},
1408			}
1409		}),
1410	})
1411	_, err := schemaWithFieldType(anotherObject)
1412	if err != nil {
1413		t.Fatalf(`unexpected error: %v for type "%v"`, err, anotherObject)
1414	}
1415}
1416func TestTypeSystem_ObjectsMustAdhereToInterfaceTheyImplement_AcceptsAnObjectWithASubtypedInterfaceField_Union(t *testing.T) {
1417	anotherInterface := graphql.NewInterface(graphql.InterfaceConfig{
1418		Name: "AnotherInterface",
1419		ResolveType: func(p graphql.ResolveTypeParams) *graphql.Object {
1420			return nil
1421		},
1422		Fields: graphql.Fields{
1423			"field": &graphql.Field{
1424				Type: someUnionType,
1425			},
1426		},
1427	})
1428	anotherObject := graphql.NewObject(graphql.ObjectConfig{
1429		Name:       "AnotherObject",
1430		Interfaces: []*graphql.Interface{anotherInterface},
1431		Fields: graphql.Fields{
1432			"field": &graphql.Field{
1433				Type: someObjectType,
1434			},
1435		},
1436	})
1437	_, err := schemaWithFieldType(anotherObject)
1438	if err != nil {
1439		t.Fatalf(`unexpected error: %v for type "%v"`, err, anotherObject)
1440	}
1441}
1442func TestTypeSystem_ObjectsMustAdhereToInterfaceTheyImplement_RejectsAnObjectMissingAnInterfaceArgument(t *testing.T) {
1443	anotherInterface := graphql.NewInterface(graphql.InterfaceConfig{
1444		Name: "AnotherInterface",
1445		ResolveType: func(p graphql.ResolveTypeParams) *graphql.Object {
1446			return nil
1447		},
1448		Fields: graphql.Fields{
1449			"field": &graphql.Field{
1450				Type: graphql.String,
1451				Args: graphql.FieldConfigArgument{
1452					"input": &graphql.ArgumentConfig{
1453						Type: graphql.String,
1454					},
1455				},
1456			},
1457		},
1458	})
1459	anotherObject := graphql.NewObject(graphql.ObjectConfig{
1460		Name:       "AnotherObject",
1461		Interfaces: []*graphql.Interface{anotherInterface},
1462		Fields: graphql.Fields{
1463			"field": &graphql.Field{
1464				Type: graphql.String,
1465			},
1466		},
1467	})
1468	_, err := schemaWithObjectFieldOfType(anotherObject)
1469	expectedError := `AnotherInterface.field expects argument "input" but AnotherObject.field does not provide it.`
1470	if err == nil || err.Error() != expectedError {
1471		t.Fatalf("Expected error: %v, got %v", expectedError, err)
1472	}
1473}
1474func TestTypeSystem_ObjectsMustAdhereToInterfaceTheyImplement_RejectsAnObjectWithAnIncorrectlyTypedInterfaceArgument(t *testing.T) {
1475	anotherInterface := graphql.NewInterface(graphql.InterfaceConfig{
1476		Name: "AnotherInterface",
1477		ResolveType: func(p graphql.ResolveTypeParams) *graphql.Object {
1478			return nil
1479		},
1480		Fields: graphql.Fields{
1481			"field": &graphql.Field{
1482				Type: graphql.String,
1483				Args: graphql.FieldConfigArgument{
1484					"input": &graphql.ArgumentConfig{
1485						Type: graphql.String,
1486					},
1487				},
1488			},
1489		},
1490	})
1491	anotherObject := graphql.NewObject(graphql.ObjectConfig{
1492		Name:       "AnotherObject",
1493		Interfaces: []*graphql.Interface{anotherInterface},
1494		Fields: graphql.Fields{
1495			"field": &graphql.Field{
1496				Type: graphql.String,
1497				Args: graphql.FieldConfigArgument{
1498					"input": &graphql.ArgumentConfig{
1499						Type: someScalarType,
1500					},
1501				},
1502			},
1503		},
1504	})
1505	_, err := schemaWithObjectFieldOfType(anotherObject)
1506	expectedError := `AnotherInterface.field(input:) expects type "String" but AnotherObject.field(input:) provides type "SomeScalar".`
1507	if err == nil || err.Error() != expectedError {
1508		t.Fatalf("Expected error: %v, got %v", expectedError, err)
1509	}
1510}
1511func TestTypeSystem_ObjectsMustAdhereToInterfaceTheyImplement_AcceptsAnObjectWithAnEquivalentlyModifiedInterfaceField(t *testing.T) {
1512	anotherInterface := graphql.NewInterface(graphql.InterfaceConfig{
1513		Name: "AnotherInterface",
1514		ResolveType: func(p graphql.ResolveTypeParams) *graphql.Object {
1515			return nil
1516		},
1517		Fields: graphql.Fields{
1518			"field": &graphql.Field{
1519				Type: graphql.NewNonNull(graphql.NewList(graphql.String)),
1520			},
1521		},
1522	})
1523	anotherObject := graphql.NewObject(graphql.ObjectConfig{
1524		Name:       "AnotherObject",
1525		Interfaces: []*graphql.Interface{anotherInterface},
1526		Fields: graphql.Fields{
1527			"field": &graphql.Field{
1528				Type: graphql.NewNonNull(graphql.NewList(graphql.String)),
1529			},
1530		},
1531	})
1532	_, err := schemaWithObjectFieldOfType(anotherObject)
1533	if err != nil {
1534		t.Fatalf(`unexpected error: %v for type "%v"`, err, anotherObject)
1535	}
1536}
1537func TestTypeSystem_ObjectsMustAdhereToInterfaceTheyImplement_RejectsAnObjectWithANonListInterfaceFieldListType(t *testing.T) {
1538	anotherInterface := graphql.NewInterface(graphql.InterfaceConfig{
1539		Name: "AnotherInterface",
1540		ResolveType: func(p graphql.ResolveTypeParams) *graphql.Object {
1541			return nil
1542		},
1543		Fields: graphql.Fields{
1544			"field": &graphql.Field{
1545				Type: graphql.NewList(graphql.String),
1546			},
1547		},
1548	})
1549	anotherObject := graphql.NewObject(graphql.ObjectConfig{
1550		Name:       "AnotherObject",
1551		Interfaces: []*graphql.Interface{anotherInterface},
1552		Fields: graphql.Fields{
1553			"field": &graphql.Field{
1554				Type: graphql.String,
1555			},
1556		},
1557	})
1558	_, err := schemaWithFieldType(anotherObject)
1559	expectedError := `AnotherInterface.field expects type "[String]" but AnotherObject.field provides type "String".`
1560	if err == nil || err.Error() != expectedError {
1561		t.Fatalf("Expected error: %v, got %v", expectedError, err)
1562	}
1563}
1564
1565func TestTypeSystem_ObjectsMustAdhereToInterfaceTheyImplement_RejectsAnObjectWithAListInterfaceFieldNonListType(t *testing.T) {
1566	anotherInterface := graphql.NewInterface(graphql.InterfaceConfig{
1567		Name: "AnotherInterface",
1568		ResolveType: func(p graphql.ResolveTypeParams) *graphql.Object {
1569			return nil
1570		},
1571		Fields: graphql.Fields{
1572			"field": &graphql.Field{
1573				Type: graphql.String,
1574			},
1575		},
1576	})
1577	anotherObject := graphql.NewObject(graphql.ObjectConfig{
1578		Name:       "AnotherObject",
1579		Interfaces: []*graphql.Interface{anotherInterface},
1580		Fields: graphql.Fields{
1581			"field": &graphql.Field{
1582				Type: graphql.NewList(graphql.String),
1583			},
1584		},
1585	})
1586	_, err := schemaWithFieldType(anotherObject)
1587	expectedError := `AnotherInterface.field expects type "String" but AnotherObject.field provides type "[String]".`
1588	if err == nil || err.Error() != expectedError {
1589		t.Fatalf("Expected error: %v, got %v", expectedError, err)
1590	}
1591}
1592
1593func TestTypeSystem_ObjectsMustAdhereToInterfaceTheyImplement_AcceptsAnObjectWithSubsetNonNullInterfaceFieldType(t *testing.T) {
1594	anotherInterface := graphql.NewInterface(graphql.InterfaceConfig{
1595		Name: "AnotherInterface",
1596		ResolveType: func(p graphql.ResolveTypeParams) *graphql.Object {
1597			return nil
1598		},
1599		Fields: graphql.Fields{
1600			"field": &graphql.Field{
1601				Type: graphql.String,
1602			},
1603		},
1604	})
1605	anotherObject := graphql.NewObject(graphql.ObjectConfig{
1606		Name:       "AnotherObject",
1607		Interfaces: []*graphql.Interface{anotherInterface},
1608		Fields: graphql.Fields{
1609			"field": &graphql.Field{
1610				Type: graphql.NewNonNull(graphql.String),
1611			},
1612		},
1613	})
1614	_, err := schemaWithFieldType(anotherObject)
1615	if err != nil {
1616		t.Fatalf(`unexpected error: %v for type "%v"`, err, anotherObject)
1617	}
1618}
1619
1620func TestTypeSystem_ObjectsMustAdhereToInterfaceTheyImplement_RejectsAnObjectWithASupersetNullableInterfaceFieldType(t *testing.T) {
1621	anotherInterface := graphql.NewInterface(graphql.InterfaceConfig{
1622		Name: "AnotherInterface",
1623		ResolveType: func(p graphql.ResolveTypeParams) *graphql.Object {
1624			return nil
1625		},
1626		Fields: graphql.Fields{
1627			"field": &graphql.Field{
1628				Type: graphql.NewNonNull(graphql.String),
1629			},
1630		},
1631	})
1632	anotherObject := graphql.NewObject(graphql.ObjectConfig{
1633		Name:       "AnotherObject",
1634		Interfaces: []*graphql.Interface{anotherInterface},
1635		Fields: graphql.Fields{
1636			"field": &graphql.Field{
1637				Type: graphql.String,
1638			},
1639		},
1640	})
1641	_, err := schemaWithFieldType(anotherObject)
1642	expectedError := `AnotherInterface.field expects type "String!" but AnotherObject.field provides type "String".`
1643	if err == nil || err.Error() != expectedError {
1644		t.Fatalf("Expected error: %v, got %v", expectedError, err)
1645	}
1646}
1647