diff --git a/internal/schema/schema.go b/internal/schema/schema.go index 569b26b2..68fedcf9 100644 --- a/internal/schema/schema.go +++ b/internal/schema/schema.go @@ -291,6 +291,11 @@ func (s *Schema) Parse(schemaString string, useStringDescriptions bool) error { if !ok { return errors.Errorf("type %q is not an interface", intfName) } + for _, f := range intf.Fields.Names() { + if obj.Fields.Get(f) == nil { + return errors.Errorf("interface %q expects field %q but %q does not provide it", intfName, f, obj.Name) + } + } obj.Interfaces[i] = intf intf.PossibleTypes = append(intf.PossibleTypes, obj) } diff --git a/internal/schema/schema_test.go b/internal/schema/schema_test.go index 5ee5156d..e1239c25 100644 --- a/internal/schema/schema_test.go +++ b/internal/schema/schema_test.go @@ -3,6 +3,7 @@ package schema_test import ( "testing" + "github.com/graph-gophers/graphql-go/errors" "github.com/graph-gophers/graphql-go/internal/schema" ) @@ -89,3 +90,25 @@ func TestParse(t *testing.T) { }) } } + +func TestInvalidInterfaceImpl(t *testing.T) { + var tests = []parseTestCase{{ + description: "Parses type Welcome that implements interface Greeting without providing required fields", + sdl: "interface Greeting { message: String! } type Welcome implements Greeting {}", + err: errors.Errorf(`interface "Greeting" expects field "message" but "Welcome" does not provide it`), + }} + + setup := func(t *testing.T) *schema.Schema { + t.Helper() + return schema.New() + } + for _, test := range tests { + t.Run(test.description, func(t *testing.T) { + schema := setup(t) + err := schema.Parse(test.sdl, false) + if err == nil || err.Error() != test.err.Error() { + t.Fatal(err) + } + }) + } +}