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