github.com/HaswinVidanage/gqlgen@v0.8.1-0.20220609041233-69528c1bf712/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, resp.Header().Get("Content-Type"), "application/json")
    49  		assert.Equal(t, `{"errors":[{"message":"json body could not be decoded: invalid character 'o' in literal null (expecting 'u')"}],"data":null}`, resp.Body.String())
    50  	})
    51  
    52  	t.Run("parse failure", func(t *testing.T) {
    53  		resp := doRequest(h, "POST", "/graphql", `{"query": "!"}`)
    54  		assert.Equal(t, http.StatusUnprocessableEntity, resp.Code)
    55  		assert.Equal(t, resp.Header().Get("Content-Type"), "application/json")
    56  		assert.Equal(t, `{"errors":[{"message":"Unexpected !","locations":[{"line":1,"column":1}]}],"data":null}`, resp.Body.String())
    57  	})
    58  
    59  	t.Run("validation failure", func(t *testing.T) {
    60  		resp := doRequest(h, "POST", "/graphql", `{"query": "{ me { title }}"}`)
    61  		assert.Equal(t, http.StatusUnprocessableEntity, resp.Code)
    62  		assert.Equal(t, resp.Header().Get("Content-Type"), "application/json")
    63  		assert.Equal(t, `{"errors":[{"message":"Cannot query field \"title\" on type \"User\".","locations":[{"line":1,"column":8}]}],"data":null}`, resp.Body.String())
    64  	})
    65  
    66  	t.Run("invalid variable", func(t *testing.T) {
    67  		resp := doRequest(h, "POST", "/graphql", `{"query": "query($id:Int!){user(id:$id){name}}","variables":{"id":false}}`)
    68  		assert.Equal(t, http.StatusUnprocessableEntity, resp.Code)
    69  		assert.Equal(t, resp.Header().Get("Content-Type"), "application/json")
    70  		assert.Equal(t, `{"errors":[{"message":"cannot use bool as Int","path":["variable","id"]}],"data":null}`, resp.Body.String())
    71  	})
    72  
    73  	t.Run("execution failure", func(t *testing.T) {
    74  		resp := doRequest(h, "POST", "/graphql", `{"query": "mutation { me { name } }"}`)
    75  		assert.Equal(t, http.StatusOK, resp.Code)
    76  		assert.Equal(t, resp.Header().Get("Content-Type"), "application/json")
    77  		assert.Equal(t, `{"errors":[{"message":"mutations are not supported"}],"data":null}`, resp.Body.String())
    78  	})
    79  }
    80  
    81  func TestHandlerGET(t *testing.T) {
    82  	h := GraphQL(&executableSchemaStub{})
    83  
    84  	t.Run("success", func(t *testing.T) {
    85  		resp := doRequest(h, "GET", "/graphql?query={me{name}}", ``)
    86  		assert.Equal(t, http.StatusOK, resp.Code)
    87  		assert.Equal(t, `{"data":{"name":"test"}}`, resp.Body.String())
    88  	})
    89  
    90  	t.Run("decode failure", func(t *testing.T) {
    91  		resp := doRequest(h, "GET", "/graphql?query=me{id}&variables=notjson", "")
    92  		assert.Equal(t, http.StatusBadRequest, resp.Code)
    93  		assert.Equal(t, `{"errors":[{"message":"variables could not be decoded"}],"data":null}`, resp.Body.String())
    94  	})
    95  
    96  	t.Run("invalid variable", func(t *testing.T) {
    97  		resp := doRequest(h, "GET", `/graphql?query=query($id:Int!){user(id:$id){name}}&variables={"id":false}`, "")
    98  		assert.Equal(t, http.StatusUnprocessableEntity, resp.Code)
    99  		assert.Equal(t, `{"errors":[{"message":"cannot use bool as Int","path":["variable","id"]}],"data":null}`, resp.Body.String())
   100  	})
   101  
   102  	t.Run("parse failure", func(t *testing.T) {
   103  		resp := doRequest(h, "GET", "/graphql?query=!", "")
   104  		assert.Equal(t, http.StatusUnprocessableEntity, resp.Code)
   105  		assert.Equal(t, `{"errors":[{"message":"Unexpected !","locations":[{"line":1,"column":1}]}],"data":null}`, resp.Body.String())
   106  	})
   107  
   108  	t.Run("no mutations", func(t *testing.T) {
   109  		resp := doRequest(h, "GET", "/graphql?query=mutation{me{name}}", "")
   110  		assert.Equal(t, http.StatusUnprocessableEntity, resp.Code)
   111  		assert.Equal(t, `{"errors":[{"message":"GET requests only allow query operations"}],"data":null}`, resp.Body.String())
   112  	})
   113  }
   114  
   115  func TestHandlerOptions(t *testing.T) {
   116  	h := GraphQL(&executableSchemaStub{})
   117  
   118  	resp := doRequest(h, "OPTIONS", "/graphql?query={me{name}}", ``)
   119  	assert.Equal(t, http.StatusOK, resp.Code)
   120  	assert.Equal(t, "OPTIONS, GET, POST", resp.Header().Get("Allow"))
   121  }
   122  
   123  func TestHandlerHead(t *testing.T) {
   124  	h := GraphQL(&executableSchemaStub{})
   125  
   126  	resp := doRequest(h, "HEAD", "/graphql?query={me{name}}", ``)
   127  	assert.Equal(t, http.StatusMethodNotAllowed, resp.Code)
   128  }
   129  
   130  func doRequest(handler http.Handler, method string, target string, body string) *httptest.ResponseRecorder {
   131  	r := httptest.NewRequest(method, target, strings.NewReader(body))
   132  	w := httptest.NewRecorder()
   133  
   134  	handler.ServeHTTP(w, r)
   135  	return w
   136  }