From aeb7aee3aac4e5572efc14109943ce4e9f3f7cbc Mon Sep 17 00:00:00 2001 From: secretworry Date: Sat, 4 Jan 2020 13:14:01 +0800 Subject: [PATCH 1/4] added go module files --- go.mod | 8 ++++++++ go.sum | 3 +++ 2 files changed, 11 insertions(+) create mode 100644 go.mod create mode 100644 go.sum diff --git a/go.mod b/go.mod new file mode 100644 index 0000000..0cc9b4d --- /dev/null +++ b/go.mod @@ -0,0 +1,8 @@ +module github.com/machinebox/graphql + +go 1.12 + +require ( + github.com/matryer/is v1.2.0 + github.com/pkg/errors v0.8.1 +) diff --git a/go.sum b/go.sum new file mode 100644 index 0000000..de4a465 --- /dev/null +++ b/go.sum @@ -0,0 +1,3 @@ +github.com/matryer/is v1.2.0 h1:92UTHpy8CDwaJ08GqLDzhhuixiBUUD1p3AU6PHddz4A= +github.com/matryer/is v1.2.0/go.mod h1:2fLPjFQM9rhQ15aVEtbuwhJinnOqrmgXPNdZsdwlWXA= +github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= From 75e2918bdcd3cdc32bb025849374742c22ce455b Mon Sep 17 00:00:00 2001 From: secretworry Date: Sat, 4 Jan 2020 13:26:51 +0800 Subject: [PATCH 2/4] added definition for standard graphql errors --- graphql.go | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/graphql.go b/graphql.go index 05c29b7..e853fd5 100644 --- a/graphql.go +++ b/graphql.go @@ -257,6 +257,24 @@ func (e graphErr) Error() string { return "graphql: " + e.Message } +// Location represents the location of a error +type Location struct { + Line int `json:"line,omitempty"` + Column int `json:"column,omitempty"` +} + +// GraphError represents the standard graphql error described in https://graphql.github.io/graphql-spec/June2018/#sec-Errors +type GraphError struct { + Message string `json:"message"` + Path []interface{} `json:"path,omitempty"` + Locations []Location `json:"locations,omitempty"` + Extensions map[string]interface{} `json:"extensions,omitempty"` +} + +func (e GraphError) Error() string { + return fmt.Sprintf("graphql: %s", e.Message) +} + type graphResponse struct { Data interface{} Errors []graphErr From 0a891346b0986be8bad6b230b1e978daa1c8e759 Mon Sep 17 00:00:00 2001 From: secretworry Date: Sat, 4 Jan 2020 14:28:57 +0800 Subject: [PATCH 3/4] added tests for current error implementation --- graphql_json_test.go | 62 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 62 insertions(+) diff --git a/graphql_json_test.go b/graphql_json_test.go index a973d2d..75599fe 100644 --- a/graphql_json_test.go +++ b/graphql_json_test.go @@ -159,3 +159,65 @@ func TestHeader(t *testing.T) { is.Equal(resp.Value, "some data") } + +func TestErrors(t *testing.T) { + is := is.New(t) + type errorSuit struct { + response string + statusCode int + expectedMessage string + } + var suits = []errorSuit{ + errorSuit{ + response: `{ + "errors": [ + { + "message": "Name for character with ID 1002 could not be fetched.", + "locations": [ { "line": 6, "column": 7 } ], + "path": [ "hero", "heroFriends", 1, "name" ], + "extensions": { + "code": "CAN_NOT_FETCH_BY_ID", + "timestamp": "Fri Feb 9 14:33:09 UTC 2018" + } + } + ] + }`, + statusCode: 404, + expectedMessage: "graphql: Name for character with ID 1002 could not be fetched.", + }, + errorSuit{ + response: `{ + "errors": [ + { + "message": "Server error" + } + ] + }`, + statusCode: 500, + expectedMessage: "graphql: Server error", + }, + } + for _, suit := range suits { + func() { + srv := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + w.WriteHeader(suit.statusCode) + _, err := io.WriteString(w, suit.response) + is.NoErr(err) + })) + defer srv.Close() + ctx, cancel := context.WithTimeout(context.Background(), 1*time.Second) + defer cancel() + client := NewClient(srv.URL) + req := NewRequest("query {}") + var resp struct { + Value string + } + err := client.Run(ctx, req, &resp) + if err != nil { + is.Equal(err.Error(), suit.expectedMessage) + } else { + is.Fail() + } + }() + } +} From 90b9ff7051fe9784427125c1f9d3ea28783095fc Mon Sep 17 00:00:00 2001 From: secretworry Date: Sat, 4 Jan 2020 14:56:43 +0800 Subject: [PATCH 4/4] Replaced graphErr with GraphError --- graphql.go | 10 +--------- graphql_json_test.go | 16 ++++++++++++++++ 2 files changed, 17 insertions(+), 9 deletions(-) diff --git a/graphql.go b/graphql.go index e853fd5..356932f 100644 --- a/graphql.go +++ b/graphql.go @@ -249,14 +249,6 @@ func ImmediatelyCloseReqBody() ClientOption { // modify the behaviour of the Client. type ClientOption func(*Client) -type graphErr struct { - Message string -} - -func (e graphErr) Error() string { - return "graphql: " + e.Message -} - // Location represents the location of a error type Location struct { Line int `json:"line,omitempty"` @@ -277,7 +269,7 @@ func (e GraphError) Error() string { type graphResponse struct { Data interface{} - Errors []graphErr + Errors []GraphError } // Request is a GraphQL request. diff --git a/graphql_json_test.go b/graphql_json_test.go index 75599fe..d1a0438 100644 --- a/graphql_json_test.go +++ b/graphql_json_test.go @@ -166,6 +166,7 @@ func TestErrors(t *testing.T) { response string statusCode int expectedMessage string + expected GraphError } var suits = []errorSuit{ errorSuit{ @@ -184,6 +185,17 @@ func TestErrors(t *testing.T) { }`, statusCode: 404, expectedMessage: "graphql: Name for character with ID 1002 could not be fetched.", + expected: GraphError{ + Message: "Name for character with ID 1002 could not be fetched.", + Locations: []Location{ + Location{Line: 6, Column: 7}, + }, + Path: []interface{}{"hero", "heroFriends", float64(1), "name"}, + Extensions: map[string]interface{}{ + "code": "CAN_NOT_FETCH_BY_ID", + "timestamp": "Fri Feb 9 14:33:09 UTC 2018", + }, + }, }, errorSuit{ response: `{ @@ -195,6 +207,9 @@ func TestErrors(t *testing.T) { }`, statusCode: 500, expectedMessage: "graphql: Server error", + expected: GraphError{ + Message: "Server error", + }, }, } for _, suit := range suits { @@ -215,6 +230,7 @@ func TestErrors(t *testing.T) { err := client.Run(ctx, req, &resp) if err != nil { is.Equal(err.Error(), suit.expectedMessage) + is.Equal(err, suit.expected) } else { is.Fail() }