diff --git a/validator/schema.go b/validator/schema.go index a979bc41..d49ff93b 100644 --- a/validator/schema.go +++ b/validator/schema.go @@ -34,6 +34,8 @@ func ValidateSchemaDocument(ast *SchemaDocument) (*Schema, *gqlerror.Error) { schema.Types[def.Name] = ast.Definitions[i] } + defs := append(DefinitionList{}, ast.Definitions...) + for _, ext := range ast.Extensions { def := schema.Types[ext.Name] if def == nil { @@ -43,6 +45,7 @@ func ValidateSchemaDocument(ast *SchemaDocument) (*Schema, *gqlerror.Error) { Position: ext.Position, } def = schema.Types[ext.Name] + defs = append(defs, def) } if def.Kind != ext.Kind { @@ -56,7 +59,7 @@ func ValidateSchemaDocument(ast *SchemaDocument) (*Schema, *gqlerror.Error) { def.EnumValues = append(def.EnumValues, ext.EnumValues...) } - for _, def := range ast.Definitions { + for _, def := range defs { switch def.Kind { case Union: for _, t := range def.Types { diff --git a/validator/schema_test.yml b/validator/schema_test.yml index 5bbf2ada..a5d8bb49 100644 --- a/validator/schema_test.yml +++ b/validator/schema_test.yml @@ -418,6 +418,36 @@ unions: message: "UNION type \"Baz\" must be OBJECT." locations: [{line: 1, column: 7}] + - name: unions of pure type extensions are valid + input: | + + type Review { + body: String! + author: User! @provides(fields: "username") + product: Product! + } + + extend type User @key(fields: "id") { + id: ID! @external + reviews: [Review] + } + + extend type Product @key(fields: "upc") { + upc: String! @external + reviews: [Review] + } + + union Foo = User | Product + scalar _Any + scalar _FieldSet + directive @external on FIELD_DEFINITION + directive @requires(fields: _FieldSet!) on FIELD_DEFINITION + directive @provides(fields: _FieldSet!) on FIELD_DEFINITION + directive @key(fields: _FieldSet!) on OBJECT | INTERFACE + directive @extends on OBJECT + + + type extensions: - name: can extend non existant types input: | diff --git a/validator/validator_test.go b/validator/validator_test.go new file mode 100644 index 00000000..b8b77bdd --- /dev/null +++ b/validator/validator_test.go @@ -0,0 +1,41 @@ +package validator_test + +import ( + "testing" + + "github.com/stretchr/testify/require" + "github.com/vektah/gqlparser" + "github.com/vektah/gqlparser/ast" + "github.com/vektah/gqlparser/parser" + "github.com/vektah/gqlparser/validator" +) + +func TestExtendingNonExistantTypes(t *testing.T) { + s := gqlparser.MustLoadSchema( + &ast.Source{Name: "graph/schema.graphqls", Input: ` +extend type User { + id: ID! +} + +extend type Product { + upc: String! +} + +union _Entity = Product | User + +extend type Query { + entity: _Entity +} +`, BuiltIn: false}, + ) + + q, err := parser.ParseQuery(&ast.Source{Name: "ff", Input: `{ + entity { + ... on User { + id + } + } + }`}) + require.Nil(t, err) + require.Nil(t, validator.Validate(s, q)) +}