github.com/geneva/gqlgen@v0.17.7-0.20230801155730-7b9317164836/graphql/handler/transport/http_graphql_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/geneva/gqlgen/graphql/handler/testserver"
    11  	"github.com/geneva/gqlgen/graphql/handler/transport"
    12  	"github.com/stretchr/testify/assert"
    13  )
    14  
    15  func TestGRAPHQL(t *testing.T) {
    16  	h := testserver.New()
    17  	h.AddTransport(transport.GRAPHQL{})
    18  
    19  	t.Run("success", func(t *testing.T) {
    20  		resp := doGraphqlRequest(h, "POST", "/graphql", `{ name }`)
    21  		assert.Equal(t, http.StatusOK, resp.Code)
    22  		assert.Equal(t, `{"data":{"name":"test"}}`, resp.Body.String())
    23  	})
    24  
    25  	t.Run("success even if url encoded", func(t *testing.T) {
    26  		resp := doGraphqlRequest(h, "POST", "/graphql", `%7B%20name%20%7D`)
    27  		assert.Equal(t, http.StatusOK, resp.Code)
    28  		assert.Equal(t, `{"data":{"name":"test"}}`, resp.Body.String())
    29  	})
    30  
    31  	t.Run("parse failure", func(t *testing.T) {
    32  		resp := doGraphqlRequest(h, "POST", "/graphql", `{"!"}`)
    33  		assert.Equal(t, http.StatusUnprocessableEntity, resp.Code, resp.Body.String())
    34  		assert.Equal(t, resp.Header().Get("Content-Type"), "application/json")
    35  		assert.Equal(t, `{"errors":[{"message":"Expected Name, found String","locations":[{"line":1,"column":3}],"extensions":{"code":"GRAPHQL_PARSE_FAILED"}}],"data":null}`, resp.Body.String())
    36  	})
    37  
    38  	t.Run("parse query failure", func(t *testing.T) {
    39  		resp := doGraphqlRequest(h, "POST", "/graphql", `%7B%H7U6Z`)
    40  		assert.Equal(t, http.StatusUnprocessableEntity, resp.Code, resp.Body.String())
    41  		assert.Equal(t, resp.Header().Get("Content-Type"), "application/json")
    42  		assert.Equal(t, resp.Body.String(), `{"errors":[{"message":"could not cleanup body: invalid URL escape \"%H7\""}],"data":null}`)
    43  	})
    44  
    45  	t.Run("validation failure", func(t *testing.T) {
    46  		resp := doGraphqlRequest(h, "POST", "/graphql", `{ title }`)
    47  		assert.Equal(t, http.StatusUnprocessableEntity, resp.Code, resp.Body.String())
    48  		assert.Equal(t, resp.Header().Get("Content-Type"), "application/json")
    49  		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())
    50  	})
    51  
    52  	t.Run("execution failure", func(t *testing.T) {
    53  		resp := doGraphqlRequest(h, "POST", "/graphql", `mutation { name }`)
    54  		assert.Equal(t, http.StatusOK, resp.Code, resp.Body.String())
    55  		assert.Equal(t, resp.Header().Get("Content-Type"), "application/json")
    56  		assert.Equal(t, `{"errors":[{"message":"mutations are not supported"}],"data":null}`, resp.Body.String())
    57  	})
    58  
    59  	t.Run("validate content type", func(t *testing.T) {
    60  		doReq := func(handler http.Handler, method string, target string, body string, contentType string) *httptest.ResponseRecorder {
    61  			r := httptest.NewRequest(method, target, strings.NewReader(body))
    62  			if contentType != "" {
    63  				r.Header.Set("Content-Type", contentType)
    64  			}
    65  			w := httptest.NewRecorder()
    66  
    67  			handler.ServeHTTP(w, r)
    68  			return w
    69  		}
    70  
    71  		validContentTypes := []string{
    72  			"application/graphql",
    73  			"application/graphql; charset=utf-8",
    74  		}
    75  
    76  		for _, contentType := range validContentTypes {
    77  			t.Run(fmt.Sprintf("allow for content type %s", contentType), func(t *testing.T) {
    78  				resp := doReq(h, "POST", "/graphql", `{ name }`, contentType)
    79  				assert.Equal(t, http.StatusOK, resp.Code, resp.Body.String())
    80  				assert.Equal(t, `{"data":{"name":"test"}}`, resp.Body.String())
    81  			})
    82  		}
    83  
    84  		invalidContentTypes := []string{
    85  			"",
    86  			"text/plain",
    87  		}
    88  
    89  		for _, tc := range invalidContentTypes {
    90  			t.Run(fmt.Sprintf("reject for content type %s", tc), func(t *testing.T) {
    91  				resp := doReq(h, "POST", "/graphql", `{"query":"{ name }"}`, tc)
    92  				assert.Equal(t, http.StatusBadRequest, resp.Code, resp.Body.String())
    93  				assert.Equal(t, fmt.Sprintf(`{"errors":[{"message":"%s"}],"data":null}`, "transport not supported"), resp.Body.String())
    94  			})
    95  		}
    96  	})
    97  }
    98  
    99  func doGraphqlRequest(handler http.Handler, method string, target string, body string) *httptest.ResponseRecorder {
   100  	r := httptest.NewRequest(method, target, strings.NewReader(body))
   101  	r.Header.Set("Content-Type", "application/graphql")
   102  	w := httptest.NewRecorder()
   103  
   104  	handler.ServeHTTP(w, r)
   105  	return w
   106  }