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 TestPOST(t *testing.T) {
17 h := testserver.New()
18 h.AddTransport(transport.POST{})
19
20 t.Run("success", func(t *testing.T) {
21 resp := doRequest(h, "POST", "/graphql", `{"query":"{ name }"}`, "application/json")
22 assert.Equal(t, http.StatusOK, resp.Code)
23 assert.Equal(t, `{"data":{"name":"test"}}`, resp.Body.String())
24 })
25
26 t.Run("decode failure", func(t *testing.T) {
27 resp := doRequest(h, "POST", "/graphql", "notjson", "application/json")
28 assert.Equal(t, http.StatusBadRequest, resp.Code, resp.Body.String())
29 assert.Equal(t, resp.Header().Get("Content-Type"), "application/json")
30 assert.Equal(t, `{"errors":[{"message":"json request body could not be decoded: invalid character 'o' in literal null (expecting 'u') body:notjson"}],"data":null}`, resp.Body.String())
31 })
32
33 t.Run("parse failure", func(t *testing.T) {
34 resp := doRequest(h, "POST", "/graphql", `{"query": "!"}`, "application/json")
35 assert.Equal(t, http.StatusUnprocessableEntity, resp.Code, resp.Body.String())
36 assert.Equal(t, resp.Header().Get("Content-Type"), "application/json")
37 assert.Equal(t, `{"errors":[{"message":"Unexpected !","locations":[{"line":1,"column":1}],"extensions":{"code":"GRAPHQL_PARSE_FAILED"}}],"data":null}`, resp.Body.String())
38 })
39
40 t.Run("validation failure", func(t *testing.T) {
41 resp := doRequest(h, "POST", "/graphql", `{"query": "{ title }"}`, "application/json")
42 assert.Equal(t, http.StatusUnprocessableEntity, resp.Code, resp.Body.String())
43 assert.Equal(t, resp.Header().Get("Content-Type"), "application/json")
44 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())
45 })
46
47 t.Run("invalid variable", func(t *testing.T) {
48 resp := doRequest(h, "POST", "/graphql", `{"query": "query($id:Int!){find(id:$id)}","variables":{"id":false}}`, "application/json")
49 assert.Equal(t, http.StatusUnprocessableEntity, resp.Code, resp.Body.String())
50 assert.Equal(t, resp.Header().Get("Content-Type"), "application/json")
51 assert.Equal(t, `{"errors":[{"message":"cannot use bool as Int","path":["variable","id"],"extensions":{"code":"GRAPHQL_VALIDATION_FAILED"}}],"data":null}`, resp.Body.String())
52 })
53
54 t.Run("execution failure", func(t *testing.T) {
55 resp := doRequest(h, "POST", "/graphql", `{"query": "mutation { name }"}`, "application/json")
56 assert.Equal(t, http.StatusOK, resp.Code, resp.Body.String())
57 assert.Equal(t, resp.Header().Get("Content-Type"), "application/json")
58 assert.Equal(t, `{"errors":[{"message":"mutations are not supported"}],"data":null}`, resp.Body.String())
59 })
60
61 t.Run("validate content type", func(t *testing.T) {
62 doReq := func(handler http.Handler, method string, target string, body string, contentType string) *httptest.ResponseRecorder {
63 r := httptest.NewRequest(method, target, strings.NewReader(body))
64 if contentType != "" {
65 r.Header.Set("Content-Type", contentType)
66 }
67 w := httptest.NewRecorder()
68
69 handler.ServeHTTP(w, r)
70 return w
71 }
72
73 validContentTypes := []string{
74 "application/json",
75 "application/json; charset=utf-8",
76 }
77
78 for _, contentType := range validContentTypes {
79 t.Run(fmt.Sprintf("allow for content type %s", contentType), func(t *testing.T) {
80 resp := doReq(h, "POST", "/graphql", `{"query":"{ name }"}`, contentType)
81 assert.Equal(t, http.StatusOK, resp.Code, resp.Body.String())
82 assert.Equal(t, `{"data":{"name":"test"}}`, resp.Body.String())
83 })
84 }
85
86 invalidContentTypes := []string{
87 "",
88 "text/plain",
89 }
90
91 for _, tc := range invalidContentTypes {
92 t.Run(fmt.Sprintf("reject for content type %s", tc), func(t *testing.T) {
93 resp := doReq(h, "POST", "/graphql", `{"query":"{ name }"}`, tc)
94 assert.Equal(t, http.StatusBadRequest, resp.Code, resp.Body.String())
95 assert.Equal(t, fmt.Sprintf(`{"errors":[{"message":"%s"}],"data":null}`, "transport not supported"), resp.Body.String())
96 })
97 }
98 })
99 }
100
101 func doRequest(handler http.Handler, method string, target string, body string, contentType string) *httptest.ResponseRecorder {
102 r := httptest.NewRequest(method, target, strings.NewReader(body))
103 r.Header.Set("Content-Type", contentType)
104 w := httptest.NewRecorder()
105
106 handler.ServeHTTP(w, r)
107 return w
108 }
109
View as plain text