Skip to content

Commit

Permalink
Merge pull request #409 from sourcegraph/fix-union-interface-inline-f…
Browse files Browse the repository at this point in the history
…ragments

fix #241
  • Loading branch information
pavelnikolov committed Nov 13, 2020
2 parents 9c36bba + 653514d commit beb923f
Show file tree
Hide file tree
Showing 5 changed files with 164 additions and 17 deletions.
38 changes: 38 additions & 0 deletions example/social/introspect.json
Original file line number Diff line number Diff line change
Expand Up @@ -214,6 +214,39 @@
"name": "Pagination",
"possibleTypes": null
},
{
"description": null,
"enumValues": null,
"fields": [
{
"args": [],
"deprecationReason": null,
"description": null,
"isDeprecated": false,
"name": "name",
"type": {
"kind": "NON_NULL",
"name": null,
"ofType": {
"kind": "SCALAR",
"name": "String",
"ofType": null
}
}
}
],
"inputFields": null,
"interfaces": null,
"kind": "INTERFACE",
"name": "Person",
"possibleTypes": [
{
"kind": "OBJECT",
"name": "User",
"ofType": null
}
]
},
{
"description": null,
"enumValues": null,
Expand Down Expand Up @@ -545,6 +578,11 @@
"kind": "INTERFACE",
"name": "Admin",
"ofType": null
},
{
"kind": "INTERFACE",
"name": "Person",
"ofType": null
}
],
"kind": "OBJECT",
Expand Down
21 changes: 17 additions & 4 deletions example/social/social.go
Original file line number Diff line number Diff line change
Expand Up @@ -27,9 +27,13 @@ const Schema = `
role: Role!
}
interface Person {
name: String!
}
scalar Time
type User implements Admin {
type User implements Admin & Person {
id: ID!
name: String!
email: String!
Expand Down Expand Up @@ -64,6 +68,15 @@ type admin interface {
Role() string
}

type adminResolver struct {
admin
}

func (r *adminResolver) ToUser() (*user, bool) {
n, ok := r.admin.(user)
return &n, ok
}

type searchResult struct {
result interface{}
}
Expand Down Expand Up @@ -189,14 +202,14 @@ type Resolver struct{}
func (r *Resolver) Admin(ctx context.Context, args struct {
ID string
Role string
}) (admin, error) {
}) (*adminResolver, error) {
if usr, ok := usersMap[args.ID]; ok {
if usr.RoleField == args.Role {
return *usr, nil
return &adminResolver{*usr}, nil
}
}
err := fmt.Errorf("user with id=%s and role=%s does not exist", args.ID, args.Role)
return user{}, err
return nil, err
}

func (r *Resolver) User(ctx context.Context, args struct{ Id string }) (user, error) {
Expand Down
79 changes: 75 additions & 4 deletions graphql_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -1703,6 +1703,77 @@ func TestInlineFragments(t *testing.T) {
}
`,
},

{
Schema: starwarsSchema,
Query: `
query CharacterSearch {
search(text: "C-3PO") {
... on Character {
name
}
}
}
`,
ExpectedResult: `
{
"search": [
{
"name": "C-3PO"
}
]
}
`,
},

{
Schema: starwarsSchema,
Query: `
query CharacterSearch {
hero {
... on Character {
... on Human {
name
}
... on Droid {
name
}
}
}
}
`,
ExpectedResult: `
{
"hero": {
"name": "R2-D2"
}
}
`,
},

{
Schema: socialSchema,
Query: `
query {
admin(id: "0x01") {
... on User {
email
}
... on Person {
name
}
}
}
`,
ExpectedResult: `
{
"admin": {
"email": "Albus@hogwarts.com",
"name": "Albus Dumbledore"
}
}
`,
},
})
}

Expand Down Expand Up @@ -2946,27 +3017,27 @@ type helloInputMismatch struct {
World string
}

func (r *inputArgumentsHello) Hello(args struct { Input *helloInput }) string {
func (r *inputArgumentsHello) Hello(args struct{ Input *helloInput }) string {
return "Hello " + args.Input.Name + "!"
}

func (r *inputArgumentsScalarMismatch1) Hello(name string) string {
return "Hello " + name + "!"
}

func (r *inputArgumentsScalarMismatch2) Hello(args struct { World string }) string {
func (r *inputArgumentsScalarMismatch2) Hello(args struct{ World string }) string {
return "Hello " + args.World + "!"
}

func (r *inputArgumentsObjectMismatch1) Hello(in helloInput) string {
return "Hello " + in.Name + "!"
}

func (r *inputArgumentsObjectMismatch2) Hello(args struct { Input *helloInputMismatch }) string {
func (r *inputArgumentsObjectMismatch2) Hello(args struct{ Input *helloInputMismatch }) string {
return "Hello " + args.Input.World + "!"
}

func (r *inputArgumentsObjectMismatch3) Hello(args struct { Input *struct { Thing string } }) string {
func (r *inputArgumentsObjectMismatch3) Hello(args struct{ Input *struct{ Thing string } }) string {
return "Hello " + args.Input.Thing + "!"
}

Expand Down
39 changes: 31 additions & 8 deletions internal/exec/selected/selected.go
Original file line number Diff line number Diff line change
Expand Up @@ -173,16 +173,39 @@ func applySelectionSet(r *Request, s *resolvable.Schema, e *resolvable.Object, s
}

func applyFragment(r *Request, s *resolvable.Schema, e *resolvable.Object, frag *query.Fragment) []Selection {
if frag.On.Name != "" && frag.On.Name != e.Name {
a, ok := e.TypeAssertions[frag.On.Name]
if !ok {
panic(fmt.Errorf("%q does not implement %q", frag.On, e.Name)) // TODO proper error handling
if frag.On.Name != e.Name {
t := r.Schema.Resolve(frag.On.Name)
face, ok := t.(*schema.Interface)
if !ok && frag.On.Name != "" {
a, ok := e.TypeAssertions[frag.On.Name]
if !ok {
panic(fmt.Errorf("%q does not implement %q", frag.On, e.Name)) // TODO proper error handling
}

return []Selection{&TypeAssertion{
TypeAssertion: *a,
Sels: applySelectionSet(r, s, a.TypeExec.(*resolvable.Object), frag.Selections),
}}
}
if ok && len(face.PossibleTypes) > 0 {
sels := []Selection{}
for _, t := range face.PossibleTypes {
if t.Name == e.Name {
return applySelectionSet(r, s, e, frag.Selections)
}

return []Selection{&TypeAssertion{
TypeAssertion: *a,
Sels: applySelectionSet(r, s, a.TypeExec.(*resolvable.Object), frag.Selections),
}}
if a, ok := e.TypeAssertions[t.Name]; ok {
sels = append(sels, &TypeAssertion{
TypeAssertion: *a,
Sels: applySelectionSet(r, s, a.TypeExec.(*resolvable.Object), frag.Selections),
})
}
}
if len(sels) == 0 {
panic(fmt.Errorf("%q does not implement %q", e.Name, frag.On)) // TODO proper error handling
}
return sels
}
}
return applySelectionSet(r, s, e, frag.Selections)
}
Expand Down
4 changes: 3 additions & 1 deletion introspection_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,8 @@ import (
"github.com/graph-gophers/graphql-go/example/starwars"
)

var socialSchema = graphql.MustParseSchema(social.Schema, &social.Resolver{}, graphql.UseFieldResolvers())

func TestSchema_ToJSON(t *testing.T) {
t.Parallel()

Expand All @@ -27,7 +29,7 @@ func TestSchema_ToJSON(t *testing.T) {
}{
{
Name: "Social Schema",
Args: args{Schema: graphql.MustParseSchema(social.Schema, &social.Resolver{}, graphql.UseFieldResolvers())},
Args: args{Schema: socialSchema},
Want: want{JSON: mustReadFile("example/social/introspect.json")},
},
{
Expand Down

0 comments on commit beb923f

Please sign in to comment.