shurcooL / graphql

Package graphql provides a GraphQL client implementation.

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Fragments Cannot Be Unmarshaled

marcocali opened this issue · comments

Currently having some issues with fragments.

I am able to correctly send a query with fragments, but the response get lost while unmarshalling. From my understanding, the reason is because queries with fragments and responses have different structures. The response cannot be unmarshalled into the original query.

For example, this query with a fragment:

	type query struct {
		TagSearch struct {
			Error struct {
				Message graphql.String
				Type struct {
					Class graphql.String
					ErrorTypeInvalidRequest struct {
						Fields []struct {
							Field graphql.String
							Message graphql.String
						}
					}  `graphql:"... on ErrorTypeInvalidRequest"`
				}
			}
			Tags []Tag
		} `graphql:"tagSearch(contextIds: $contextIds, limit: $limit, primary: $primary, public: $public, query: $query)"`
	}

Can only be marshaled to the following struct:

	type query struct {
		TagSearch struct {
			Error struct {
				Message graphql.String
				Type struct {
					Class graphql.String
					Fields []struct {
						Field graphql.String
						Message graphql.String
					}
				}
			}
			Tags []Tag
		} `graphql:"tagSearch(contextIds: $contextIds, limit: $limit, primary: $primary, public: $public, query: $query)"`
	}

Where the ErrorTypeInvalidRequest struct was removed.

It is strange because in the README two different structs are actually used. One for the query and one for the response, but this is not mentioned and not actually possible from the library.

fmt.Println(q.Hero.PrimaryFunction) would give you a compilation error. fmt.Println(q.Hero.DroidFragment.PrimaryFunction) is available instead.

Never mind... this actually works as expected:

func TestFragment(t *testing.T) {
	type myerror struct {
		Message graphql.String
		Type struct {
			Class graphql.String
			ErrorTypeInvalidRequest struct {
				Fields []struct {
					Field graphql.String
					Message graphql.String
				}
			}  `graphql:"... on ErrorTypeInvalidRequest"`
		}
	}
	type query struct {
		Error myerror
	}
	var got query
	err := jsonutil.UnmarshalGraphQL([]byte(`{
		"error": {
			"message": "Invalid limit",
			"type": {
				"class": "INVALID_REQUEST",
				"fields": [
					{
						"field": "limit",
						"message": "0 is not between the allowed limit of 1 to 50"
					}
				]
			}
		}
	}`), &got)
	if err != nil {
		t.Fatal(err)
	}
	var want query
	want.Error = myerror{
		Message: "Invalid limit",
		Type: struct{Class graphql.String; ErrorTypeInvalidRequest struct{Fields []struct{Field graphql.String; Message graphql.String}} "graphql:\"... on ErrorTypeInvalidRequest\""}{
			Class: "INVALID_REQUEST",
			ErrorTypeInvalidRequest: struct{Fields []struct{Field graphql.String; Message graphql.String}}{
				Fields: []struct{Field graphql.String; Message graphql.String}{
					{"limit", "0 is not between the allowed limit of 1 to 50"},
				},
			},
		},
	}
	if !reflect.DeepEqual(got, want) {
		t.Error("not equal")
	}
}

This test will run ok.

Delve did not let me inspect Type struct, so I thought it would not unmarshall...