Skip to content

Commit

Permalink
Merge pull request #369 from vetcher/master
Browse files Browse the repository at this point in the history
reverse errors and data order in response
  • Loading branch information
vektah committed Oct 15, 2018
2 parents 3eab22a + f1f043b commit 20a5b6c
Show file tree
Hide file tree
Showing 2 changed files with 13 additions and 10 deletions.
5 changes: 4 additions & 1 deletion graphql/response.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,9 +8,12 @@ import (
"github.com/vektah/gqlparser/gqlerror"
)

// Errors are intentionally serialized first based on the advice in
// https://github.com/facebook/graphql/commit/7b40390d48680b15cb93e02d46ac5eb249689876#diff-757cea6edf0288677a9eea4cfc801d87R107
// and https://github.com/facebook/graphql/pull/384
type Response struct {
Data json.RawMessage `json:"data"`
Errors gqlerror.List `json:"errors,omitempty"`
Data json.RawMessage `json:"data"`
Extensions map[string]interface{} `json:"extensions,omitempty"`
}

Expand Down
18 changes: 9 additions & 9 deletions handler/graphql_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -45,31 +45,31 @@ func TestHandlerPOST(t *testing.T) {
t.Run("decode failure", func(t *testing.T) {
resp := doRequest(h, "POST", "/graphql", "notjson")
assert.Equal(t, http.StatusBadRequest, resp.Code)
assert.Equal(t, `{"data":null,"errors":[{"message":"json body could not be decoded: invalid character 'o' in literal null (expecting 'u')"}]}`, resp.Body.String())
assert.Equal(t, `{"errors":[{"message":"json body could not be decoded: invalid character 'o' in literal null (expecting 'u')"}],"data":null}`, resp.Body.String())
})

t.Run("parse failure", func(t *testing.T) {
resp := doRequest(h, "POST", "/graphql", `{"query": "!"}`)
assert.Equal(t, http.StatusUnprocessableEntity, resp.Code)
assert.Equal(t, `{"data":null,"errors":[{"message":"Unexpected !","locations":[{"line":1,"column":1}]}]}`, resp.Body.String())
assert.Equal(t, `{"errors":[{"message":"Unexpected !","locations":[{"line":1,"column":1}]}],"data":null}`, resp.Body.String())
})

t.Run("validation failure", func(t *testing.T) {
resp := doRequest(h, "POST", "/graphql", `{"query": "{ me { title }}"}`)
assert.Equal(t, http.StatusUnprocessableEntity, resp.Code)
assert.Equal(t, `{"data":null,"errors":[{"message":"Cannot query field \"title\" on type \"User\".","locations":[{"line":1,"column":8}]}]}`, resp.Body.String())
assert.Equal(t, `{"errors":[{"message":"Cannot query field \"title\" on type \"User\".","locations":[{"line":1,"column":8}]}],"data":null}`, resp.Body.String())
})

t.Run("invalid variable", func(t *testing.T) {
resp := doRequest(h, "POST", "/graphql", `{"query": "query($id:Int!){user(id:$id){name}}","variables":{"id":false}}`)
assert.Equal(t, http.StatusUnprocessableEntity, resp.Code)
assert.Equal(t, `{"data":null,"errors":[{"message":"cannot use bool as Int","path":["variable","id"]}]}`, resp.Body.String())
assert.Equal(t, `{"errors":[{"message":"cannot use bool as Int","path":["variable","id"]}],"data":null}`, resp.Body.String())
})

t.Run("execution failure", func(t *testing.T) {
resp := doRequest(h, "POST", "/graphql", `{"query": "mutation { me { name } }"}`)
assert.Equal(t, http.StatusOK, resp.Code)
assert.Equal(t, `{"data":null,"errors":[{"message":"mutations are not supported"}]}`, resp.Body.String())
assert.Equal(t, `{"errors":[{"message":"mutations are not supported"}],"data":null}`, resp.Body.String())
})
}

Expand All @@ -85,25 +85,25 @@ func TestHandlerGET(t *testing.T) {
t.Run("decode failure", func(t *testing.T) {
resp := doRequest(h, "GET", "/graphql?query=me{id}&variables=notjson", "")
assert.Equal(t, http.StatusBadRequest, resp.Code)
assert.Equal(t, `{"data":null,"errors":[{"message":"variables could not be decoded"}]}`, resp.Body.String())
assert.Equal(t, `{"errors":[{"message":"variables could not be decoded"}],"data":null}`, resp.Body.String())
})

t.Run("invalid variable", func(t *testing.T) {
resp := doRequest(h, "GET", `/graphql?query=query($id:Int!){user(id:$id){name}}&variables={"id":false}`, "")
assert.Equal(t, http.StatusUnprocessableEntity, resp.Code)
assert.Equal(t, `{"data":null,"errors":[{"message":"cannot use bool as Int","path":["variable","id"]}]}`, resp.Body.String())
assert.Equal(t, `{"errors":[{"message":"cannot use bool as Int","path":["variable","id"]}],"data":null}`, resp.Body.String())
})

t.Run("parse failure", func(t *testing.T) {
resp := doRequest(h, "GET", "/graphql?query=!", "")
assert.Equal(t, http.StatusUnprocessableEntity, resp.Code)
assert.Equal(t, `{"data":null,"errors":[{"message":"Unexpected !","locations":[{"line":1,"column":1}]}]}`, resp.Body.String())
assert.Equal(t, `{"errors":[{"message":"Unexpected !","locations":[{"line":1,"column":1}]}],"data":null}`, resp.Body.String())
})

t.Run("no mutations", func(t *testing.T) {
resp := doRequest(h, "GET", "/graphql?query=mutation{me{name}}", "")
assert.Equal(t, http.StatusUnprocessableEntity, resp.Code)
assert.Equal(t, `{"data":null,"errors":[{"message":"GET requests only allow query operations"}]}`, resp.Body.String())
assert.Equal(t, `{"errors":[{"message":"GET requests only allow query operations"}],"data":null}`, resp.Body.String())
})
}

Expand Down

0 comments on commit 20a5b6c

Please sign in to comment.