github.com/deliveroo/gqlgen@v0.7.2/handler/graphql_test.go (about)

     1  package handler
     2  
     3  import (
     4  	"net/http"
     5  	"net/http/httptest"
     6  	"strings"
     7  	"testing"
     8  
     9  	"github.com/stretchr/testify/assert"
    10  )
    11  
    12  func TestHandlerPOST(t *testing.T) {
    13  	h := GraphQL(&executableSchemaStub{})
    14  
    15  	t.Run("success", func(t *testing.T) {
    16  		resp := doRequest(h, "POST", "/graphql", `{"query":"{ me { name } }"}`)
    17  		assert.Equal(t, http.StatusOK, resp.Code)
    18  		assert.Equal(t, `{"data":{"name":"test"}}`, resp.Body.String())
    19  	})
    20  
    21  	t.Run("query caching", func(t *testing.T) {
    22  		// Run enough unique queries to evict a bunch of them
    23  		for i := 0; i < 2000; i++ {
    24  			query := `{"query":"` + strings.Repeat(" ", i) + "{ me { name } }" + `"}`
    25  			resp := doRequest(h, "POST", "/graphql", query)
    26  			assert.Equal(t, http.StatusOK, resp.Code)
    27  			assert.Equal(t, `{"data":{"name":"test"}}`, resp.Body.String())
    28  		}
    29  
    30  		t.Run("evicted queries run", func(t *testing.T) {
    31  			query := `{"query":"` + strings.Repeat(" ", 0) + "{ me { name } }" + `"}`
    32  			resp := doRequest(h, "POST", "/graphql", query)
    33  			assert.Equal(t, http.StatusOK, resp.Code)
    34  			assert.Equal(t, `{"data":{"name":"test"}}`, resp.Body.String())
    35  		})
    36  
    37  		t.Run("non-evicted queries run", func(t *testing.T) {
    38  			query := `{"query":"` + strings.Repeat(" ", 1999) + "{ me { name } }" + `"}`
    39  			resp := doRequest(h, "POST", "/graphql", query)
    40  			assert.Equal(t, http.StatusOK, resp.Code)
    41  			assert.Equal(t, `{"data":{"name":"test"}}`, resp.Body.String())
    42  		})
    43  	})
    44  
    45  	t.Run("decode failure", func(t *testing.T) {
    46  		resp := doRequest(h, "POST", "/graphql", "notjson")
    47  		assert.Equal(t, http.StatusBadRequest, resp.Code)
    48  		assert.Equal(t, `{"errors":[{"message":"json body could not be decoded: invalid character 'o' in literal null (expecting 'u')"}],"data":null}`, resp.Body.String())
    49  	})
    50  
    51  	t.Run("parse failure", func(t *testing.T) {
    52  		resp := doRequest(h, "POST", "/graphql", `{"query": "!"}`)
    53  		assert.Equal(t, http.StatusUnprocessableEntity, resp.Code)
    54  		assert.Equal(t, `{"errors":[{"message":"Unexpected !","locations":[{"line":1,"column":1}]}],"data":null}`, resp.Body.String())
    55  	})
    56  
    57  	t.Run("validation failure", func(t *testing.T) {
    58  		resp := doRequest(h, "POST", "/graphql", `{"query": "{ me { title }}"}`)
    59  		assert.Equal(t, http.StatusUnprocessableEntity, resp.Code)
    60  		assert.Equal(t, `{"errors":[{"message":"Cannot query field \"title\" on type \"User\".","locations":[{"line":1,"column":8}]}],"data":null}`, resp.Body.String())
    61  	})
    62  
    63  	t.Run("invalid variable", func(t *testing.T) {
    64  		resp := doRequest(h, "POST", "/graphql", `{"query": "query($id:Int!){user(id:$id){name}}","variables":{"id":false}}`)
    65  		assert.Equal(t, http.StatusUnprocessableEntity, resp.Code)
    66  		assert.Equal(t, `{"errors":[{"message":"cannot use bool as Int","path":["variable","id"]}],"data":null}`, resp.Body.String())
    67  	})
    68  
    69  	t.Run("execution failure", func(t *testing.T) {
    70  		resp := doRequest(h, "POST", "/graphql", `{"query": "mutation { me { name } }"}`)
    71  		assert.Equal(t, http.StatusOK, resp.Code)
    72  		assert.Equal(t, `{"errors":[{"message":"mutations are not supported"}],"data":null}`, resp.Body.String())
    73  	})
    74  }
    75  
    76  func TestHandlerGET(t *testing.T) {
    77  	h := GraphQL(&executableSchemaStub{})
    78  
    79  	t.Run("success", func(t *testing.T) {
    80  		resp := doRequest(h, "GET", "/graphql?query={me{name}}", ``)
    81  		assert.Equal(t, http.StatusOK, resp.Code)
    82  		assert.Equal(t, `{"data":{"name":"test"}}`, resp.Body.String())
    83  	})
    84  
    85  	t.Run("decode failure", func(t *testing.T) {
    86  		resp := doRequest(h, "GET", "/graphql?query=me{id}&variables=notjson", "")
    87  		assert.Equal(t, http.StatusBadRequest, resp.Code)
    88  		assert.Equal(t, `{"errors":[{"message":"variables could not be decoded"}],"data":null}`, resp.Body.String())
    89  	})
    90  
    91  	t.Run("invalid variable", func(t *testing.T) {
    92  		resp := doRequest(h, "GET", `/graphql?query=query($id:Int!){user(id:$id){name}}&variables={"id":false}`, "")
    93  		assert.Equal(t, http.StatusUnprocessableEntity, resp.Code)
    94  		assert.Equal(t, `{"errors":[{"message":"cannot use bool as Int","path":["variable","id"]}],"data":null}`, resp.Body.String())
    95  	})
    96  
    97  	t.Run("parse failure", func(t *testing.T) {
    98  		resp := doRequest(h, "GET", "/graphql?query=!", "")
    99  		assert.Equal(t, http.StatusUnprocessableEntity, resp.Code)
   100  		assert.Equal(t, `{"errors":[{"message":"Unexpected !","locations":[{"line":1,"column":1}]}],"data":null}`, resp.Body.String())
   101  	})
   102  
   103  	t.Run("no mutations", func(t *testing.T) {
   104  		resp := doRequest(h, "GET", "/graphql?query=mutation{me{name}}", "")
   105  		assert.Equal(t, http.StatusUnprocessableEntity, resp.Code)
   106  		assert.Equal(t, `{"errors":[{"message":"GET requests only allow query operations"}],"data":null}`, resp.Body.String())
   107  	})
   108  }
   109  
   110  func TestHandlerOptions(t *testing.T) {
   111  	h := GraphQL(&executableSchemaStub{})
   112  
   113  	resp := doRequest(h, "OPTIONS", "/graphql?query={me{name}}", ``)
   114  	assert.Equal(t, http.StatusOK, resp.Code)
   115  	assert.Equal(t, "OPTIONS, GET, POST", resp.HeaderMap.Get("Allow"))
   116  }
   117  
   118  func TestHandlerHead(t *testing.T) {
   119  	h := GraphQL(&executableSchemaStub{})
   120  
   121  	resp := doRequest(h, "HEAD", "/graphql?query={me{name}}", ``)
   122  	assert.Equal(t, http.StatusMethodNotAllowed, resp.Code)
   123  }
   124  
   125  func doRequest(handler http.Handler, method string, target string, body string) *httptest.ResponseRecorder {
   126  	r := httptest.NewRequest(method, target, strings.NewReader(body))
   127  	w := httptest.NewRecorder()
   128  
   129  	handler.ServeHTTP(w, r)
   130  	return w
   131  }