1 package transport_test
2
3 import (
4 "fmt"
5 "net/http"
6 "net/http/httptest"
7 "strings"
8 "testing"
9
10 "github.com/stretchr/testify/assert"
11
12 "github.com/99designs/gqlgen/graphql/handler/testserver"
13 "github.com/99designs/gqlgen/graphql/handler/transport"
14 )
15
16 func TestGRAPHQL(t *testing.T) {
17 h := testserver.New()
18 h.AddTransport(transport.GRAPHQL{})
19
20 t.Run("success", func(t *testing.T) {
21 resp := doGraphqlRequest(h, "POST", "/graphql", `{ name }`)
22 assert.Equal(t, http.StatusOK, resp.Code)
23 assert.Equal(t, `{"data":{"name":"test"}}`, resp.Body.String())
24 })
25
26 t.Run("success even if url encoded", func(t *testing.T) {
27 resp := doGraphqlRequest(h, "POST", "/graphql", `%7B%20name%20%7D`)
28 assert.Equal(t, http.StatusOK, resp.Code)
29 assert.Equal(t, `{"data":{"name":"test"}}`, resp.Body.String())
30 })
31
32 t.Run("parse failure", func(t *testing.T) {
33 resp := doGraphqlRequest(h, "POST", "/graphql", `{"!"}`)
34 assert.Equal(t, http.StatusUnprocessableEntity, resp.Code, resp.Body.String())
35 assert.Equal(t, resp.Header().Get("Content-Type"), "application/json")
36 assert.Equal(t, `{"errors":[{"message":"Expected Name, found String","locations":[{"line":1,"column":3}],"extensions":{"code":"GRAPHQL_PARSE_FAILED"}}],"data":null}`, resp.Body.String())
37 })
38
39 t.Run("parse query failure", func(t *testing.T) {
40 resp := doGraphqlRequest(h, "POST", "/graphql", `%7B%H7U6Z`)
41 assert.Equal(t, http.StatusUnprocessableEntity, resp.Code, resp.Body.String())
42 assert.Equal(t, resp.Header().Get("Content-Type"), "application/json")
43 assert.Equal(t, resp.Body.String(), `{"errors":[{"message":"could not cleanup body: invalid URL escape \"%H7\""}],"data":null}`)
44 })
45
46 t.Run("validation failure", func(t *testing.T) {
47 resp := doGraphqlRequest(h, "POST", "/graphql", `{ title }`)
48 assert.Equal(t, http.StatusUnprocessableEntity, resp.Code, resp.Body.String())
49 assert.Equal(t, resp.Header().Get("Content-Type"), "application/json")
50 assert.Equal(t, `{"errors":[{"message":"Cannot query field \"title\" on type \"Query\".","locations":[{"line":1,"column":3}],"extensions":{"code":"GRAPHQL_VALIDATION_FAILED"}}],"data":null}`, resp.Body.String())
51 })
52
53 t.Run("execution failure", func(t *testing.T) {
54 resp := doGraphqlRequest(h, "POST", "/graphql", `mutation { name }`)
55 assert.Equal(t, http.StatusOK, resp.Code, resp.Body.String())
56 assert.Equal(t, resp.Header().Get("Content-Type"), "application/json")
57 assert.Equal(t, `{"errors":[{"message":"mutations are not supported"}],"data":null}`, resp.Body.String())
58 })
59
60 t.Run("validate content type", func(t *testing.T) {
61 doReq := func(handler http.Handler, method string, target string, body string, contentType string) *httptest.ResponseRecorder {
62 r := httptest.NewRequest(method, target, strings.NewReader(body))
63 if contentType != "" {
64 r.Header.Set("Content-Type", contentType)
65 }
66 w := httptest.NewRecorder()
67
68 handler.ServeHTTP(w, r)
69 return w
70 }
71
72 validContentTypes := []string{
73 "application/graphql",
74 "application/graphql; charset=utf-8",
75 }
76
77 for _, contentType := range validContentTypes {
78 t.Run(fmt.Sprintf("allow for content type %s", contentType), func(t *testing.T) {
79 resp := doReq(h, "POST", "/graphql", `{ name }`, contentType)
80 assert.Equal(t, http.StatusOK, resp.Code, resp.Body.String())
81 assert.Equal(t, `{"data":{"name":"test"}}`, resp.Body.String())
82 })
83 }
84
85 invalidContentTypes := []string{
86 "",
87 "text/plain",
88 }
89
90 for _, tc := range invalidContentTypes {
91 t.Run(fmt.Sprintf("reject for content type %s", tc), func(t *testing.T) {
92 resp := doReq(h, "POST", "/graphql", `{"query":"{ name }"}`, tc)
93 assert.Equal(t, http.StatusBadRequest, resp.Code, resp.Body.String())
94 assert.Equal(t, fmt.Sprintf(`{"errors":[{"message":"%s"}],"data":null}`, "transport not supported"), resp.Body.String())
95 })
96 }
97 })
98 }
99
100 func doGraphqlRequest(handler http.Handler, method string, target string, body string) *httptest.ResponseRecorder {
101 r := httptest.NewRequest(method, target, strings.NewReader(body))
102 r.Header.Set("Content-Type", "application/graphql")
103 w := httptest.NewRecorder()
104
105 handler.ServeHTTP(w, r)
106 return w
107 }
108
View as plain text