github.com/maeglindeveloper/gqlgen@v0.13.1-0.20210413081235-57808b12a0a0/graphql/handler/transport/http_post_test.go (about) 1 package transport_test 2 3 import ( 4 "fmt" 5 "net/http" 6 "net/http/httptest" 7 "strings" 8 "testing" 9 10 "github.com/99designs/gqlgen/graphql/handler/testserver" 11 "github.com/99designs/gqlgen/graphql/handler/transport" 12 "github.com/stretchr/testify/assert" 13 ) 14 15 func TestPOST(t *testing.T) { 16 h := testserver.New() 17 h.AddTransport(transport.POST{}) 18 19 t.Run("success", func(t *testing.T) { 20 resp := doRequest(h, "POST", "/graphql", `{"query":"{ name }"}`) 21 assert.Equal(t, http.StatusOK, resp.Code) 22 assert.Equal(t, `{"data":{"name":"test"}}`, resp.Body.String()) 23 }) 24 25 t.Run("decode failure", func(t *testing.T) { 26 resp := doRequest(h, "POST", "/graphql", "notjson") 27 assert.Equal(t, http.StatusBadRequest, resp.Code, resp.Body.String()) 28 assert.Equal(t, resp.Header().Get("Content-Type"), "application/json") 29 assert.Equal(t, `{"errors":[{"message":"json body could not be decoded: invalid character 'o' in literal null (expecting 'u')"}],"data":null}`, resp.Body.String()) 30 }) 31 32 t.Run("parse failure", func(t *testing.T) { 33 resp := doRequest(h, "POST", "/graphql", `{"query": "!"}`) 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":"Unexpected !","locations":[{"line":1,"column":1}],"extensions":{"code":"GRAPHQL_PARSE_FAILED"}}],"data":null}`, resp.Body.String()) 37 }) 38 39 t.Run("validation failure", func(t *testing.T) { 40 resp := doRequest(h, "POST", "/graphql", `{"query": "{ title }"}`) 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, `{"errors":[{"message":"Cannot query field \"title\" on type \"Query\".","locations":[{"line":1,"column":3}],"extensions":{"code":"GRAPHQL_VALIDATION_FAILED"}}],"data":null}`, resp.Body.String()) 44 }) 45 46 t.Run("invalid variable", func(t *testing.T) { 47 resp := doRequest(h, "POST", "/graphql", `{"query": "query($id:Int!){find(id:$id)}","variables":{"id":false}}`) 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 use bool as Int","path":["variable","id"],"extensions":{"code":"GRAPHQL_VALIDATION_FAILED"}}],"data":null}`, resp.Body.String()) 51 }) 52 53 t.Run("execution failure", func(t *testing.T) { 54 resp := doRequest(h, "POST", "/graphql", `{"query": "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/json", 74 "application/json; 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", `{"query":"{ 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 // These content types are currently not supported, but they are supported by other GraphQL servers, like express-graphql. 90 "application/x-www-form-urlencoded", 91 "application/graphql", 92 } 93 94 for _, tc := range invalidContentTypes { 95 t.Run(fmt.Sprintf("reject for content type %s", tc), func(t *testing.T) { 96 resp := doReq(h, "POST", "/graphql", `{"query":"{ name }"}`, tc) 97 assert.Equal(t, http.StatusBadRequest, resp.Code, resp.Body.String()) 98 assert.Equal(t, fmt.Sprintf(`{"errors":[{"message":"%s"}],"data":null}`, "transport not supported"), resp.Body.String()) 99 }) 100 } 101 }) 102 } 103 104 func doRequest(handler http.Handler, method string, target string, body string) *httptest.ResponseRecorder { 105 r := httptest.NewRequest(method, target, strings.NewReader(body)) 106 r.Header.Set("Content-Type", "application/json") 107 w := httptest.NewRecorder() 108 109 handler.ServeHTTP(w, r) 110 return w 111 }