From fe4cb53eda627081f08bc2e5541c9183a6942b4c Mon Sep 17 00:00:00 2001 From: Vincent Composieux Date: Mon, 29 Mar 2021 11:30:30 +0200 Subject: [PATCH] Fixed duplicated __typename in response (fixes #369) --- gqltesting/testing.go | 19 ++++++++++++++++--- graphql_test.go | 24 ++++++++++++++++++++++++ internal/exec/exec.go | 15 ++++++++++----- 3 files changed, 50 insertions(+), 8 deletions(-) diff --git a/gqltesting/testing.go b/gqltesting/testing.go index b1544fd9..f8b6c9dc 100644 --- a/gqltesting/testing.go +++ b/gqltesting/testing.go @@ -23,6 +23,7 @@ type Test struct { Variables map[string]interface{} ExpectedResult string ExpectedErrors []*errors.QueryError + RawResponse bool } // RunTests runs the given GraphQL test cases as subtests. @@ -57,10 +58,22 @@ func RunTest(t *testing.T, test *Test) { } // Verify JSON to avoid red herring errors. - got, err := formatJSON(result.Data) - if err != nil { - t.Fatalf("got: invalid JSON: %s", err) + var got []byte + + if test.RawResponse { + value, err := result.Data.MarshalJSON() + if err != nil { + t.Fatalf("got: unable to marshal JSON response: %s", err) + } + got = value + } else { + value, err := formatJSON(result.Data) + if err != nil { + t.Fatalf("got: invalid JSON: %s", err) + } + got = value } + want, err := formatJSON([]byte(test.ExpectedResult)) if err != nil { t.Fatalf("want: invalid JSON: %s", err) diff --git a/graphql_test.go b/graphql_test.go index 901d511e..98bedce1 100644 --- a/graphql_test.go +++ b/graphql_test.go @@ -1836,6 +1836,30 @@ func TestTypeName(t *testing.T) { } `, }, + + { + Schema: starwarsSchema, + Query: ` + { + hero { + __typename + name + ... on Character { + ...Droid + name + __typename + } + } + } + + fragment Droid on Droid { + name + __typename + } + `, + RawResponse: true, + ExpectedResult: `{"hero":{"__typename":"Droid","name":"R2-D2"}}`, + }, }) } diff --git a/internal/exec/exec.go b/internal/exec/exec.go index 1e409bb8..7b9895e7 100644 --- a/internal/exec/exec.go +++ b/internal/exec/exec.go @@ -129,12 +129,17 @@ func collectFieldsToResolve(sels []selected.Selection, s *resolvable.Schema, res field.sels = append(field.sels, sel.Sels...) case *selected.TypenameField: - sf := &selected.SchemaField{ - Field: s.Meta.FieldTypename, - Alias: sel.Alias, - FixedResult: reflect.ValueOf(typeOf(sel, resolver)), + _, ok := fieldByAlias[sel.Alias] + if !ok { + sf := &selected.SchemaField{ + Field: s.Meta.FieldTypename, + Alias: sel.Alias, + FixedResult: reflect.ValueOf(typeOf(sel, resolver)), + } + field := &fieldToExec{field: sf, resolver: resolver} + *fields = append(*fields, field) + fieldByAlias[sel.Alias] = field } - *fields = append(*fields, &fieldToExec{field: sf, resolver: resolver}) case *selected.TypeAssertion: out := resolver.Method(sel.MethodIndex).Call(nil)