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  }