github.com/fortexxx/gqlgen@v0.10.3-0.20191216030626-ca5ea8b21ead/graphql/handler/server_test.go (about)

     1  package handler_test
     2  
     3  import (
     4  	"context"
     5  	"net/http"
     6  	"net/http/httptest"
     7  	"net/url"
     8  	"testing"
     9  
    10  	"github.com/99designs/gqlgen/graphql"
    11  	"github.com/99designs/gqlgen/graphql/handler/testserver"
    12  	"github.com/99designs/gqlgen/graphql/handler/transport"
    13  	"github.com/stretchr/testify/assert"
    14  	"github.com/stretchr/testify/require"
    15  	"github.com/vektah/gqlparser/ast"
    16  	"github.com/vektah/gqlparser/parser"
    17  )
    18  
    19  func TestServer(t *testing.T) {
    20  	srv := testserver.New()
    21  	srv.AddTransport(&transport.GET{})
    22  
    23  	t.Run("returns an error if no transport matches", func(t *testing.T) {
    24  		resp := post(srv, "/foo", "application/json")
    25  		assert.Equal(t, http.StatusBadRequest, resp.Code)
    26  		assert.Equal(t, `{"errors":[{"message":"transport not supported"}],"data":null}`, resp.Body.String())
    27  	})
    28  
    29  	t.Run("calls query on executable schema", func(t *testing.T) {
    30  		resp := get(srv, "/foo?query={name}")
    31  		assert.Equal(t, http.StatusOK, resp.Code)
    32  		assert.Equal(t, `{"data":{"name":"test"}}`, resp.Body.String())
    33  	})
    34  
    35  	t.Run("mutations are forbidden", func(t *testing.T) {
    36  		resp := get(srv, "/foo?query=mutation{name}")
    37  		assert.Equal(t, http.StatusNotAcceptable, resp.Code)
    38  		assert.Equal(t, `{"errors":[{"message":"GET requests only allow query operations"}],"data":null}`, resp.Body.String())
    39  	})
    40  
    41  	t.Run("subscriptions are forbidden", func(t *testing.T) {
    42  		resp := get(srv, "/foo?query=subscription{name}")
    43  		assert.Equal(t, http.StatusNotAcceptable, resp.Code)
    44  		assert.Equal(t, `{"errors":[{"message":"GET requests only allow query operations"}],"data":null}`, resp.Body.String())
    45  	})
    46  
    47  	t.Run("invokes operation middleware in order", func(t *testing.T) {
    48  		var calls []string
    49  		srv.AroundOperations(func(ctx context.Context, next graphql.OperationHandler) graphql.ResponseHandler {
    50  			calls = append(calls, "first")
    51  			return next(ctx)
    52  		})
    53  		srv.AroundOperations(func(ctx context.Context, next graphql.OperationHandler) graphql.ResponseHandler {
    54  			calls = append(calls, "second")
    55  			return next(ctx)
    56  		})
    57  
    58  		resp := get(srv, "/foo?query={name}")
    59  		assert.Equal(t, http.StatusOK, resp.Code, resp.Body.String())
    60  		assert.Equal(t, []string{"first", "second"}, calls)
    61  	})
    62  
    63  	t.Run("invokes response middleware in order", func(t *testing.T) {
    64  		var calls []string
    65  		srv.AroundResponses(func(ctx context.Context, next graphql.ResponseHandler) *graphql.Response {
    66  			calls = append(calls, "first")
    67  			return next(ctx)
    68  		})
    69  		srv.AroundResponses(func(ctx context.Context, next graphql.ResponseHandler) *graphql.Response {
    70  			calls = append(calls, "second")
    71  			return next(ctx)
    72  		})
    73  
    74  		resp := get(srv, "/foo?query={name}")
    75  		assert.Equal(t, http.StatusOK, resp.Code, resp.Body.String())
    76  		assert.Equal(t, []string{"first", "second"}, calls)
    77  	})
    78  
    79  	t.Run("invokes field middleware in order", func(t *testing.T) {
    80  		var calls []string
    81  		srv.AroundFields(func(ctx context.Context, next graphql.Resolver) (res interface{}, err error) {
    82  			calls = append(calls, "first")
    83  			return next(ctx)
    84  		})
    85  		srv.AroundFields(func(ctx context.Context, next graphql.Resolver) (res interface{}, err error) {
    86  			calls = append(calls, "second")
    87  			return next(ctx)
    88  		})
    89  
    90  		resp := get(srv, "/foo?query={name}")
    91  		assert.Equal(t, http.StatusOK, resp.Code, resp.Body.String())
    92  		assert.Equal(t, []string{"first", "second"}, calls)
    93  	})
    94  
    95  	t.Run("query caching", func(t *testing.T) {
    96  		cache := &graphql.MapCache{}
    97  		srv.SetQueryCache(cache)
    98  		qry := `query Foo {name}`
    99  
   100  		t.Run("cache miss populates cache", func(t *testing.T) {
   101  			resp := get(srv, "/foo?query="+url.QueryEscape(qry))
   102  			assert.Equal(t, http.StatusOK, resp.Code)
   103  			assert.Equal(t, `{"data":{"name":"test"}}`, resp.Body.String())
   104  
   105  			cacheDoc, ok := cache.Get(qry)
   106  			require.True(t, ok)
   107  			require.Equal(t, "Foo", cacheDoc.(*ast.QueryDocument).Operations[0].Name)
   108  		})
   109  
   110  		t.Run("cache hits use document from cache", func(t *testing.T) {
   111  			doc, err := parser.ParseQuery(&ast.Source{Input: `query Bar {name}`})
   112  			require.Nil(t, err)
   113  			cache.Add(qry, doc)
   114  
   115  			resp := get(srv, "/foo?query="+url.QueryEscape(qry))
   116  			assert.Equal(t, http.StatusOK, resp.Code)
   117  			assert.Equal(t, `{"data":{"name":"test"}}`, resp.Body.String())
   118  
   119  			cacheDoc, ok := cache.Get(qry)
   120  			require.True(t, ok)
   121  			require.Equal(t, "Bar", cacheDoc.(*ast.QueryDocument).Operations[0].Name)
   122  		})
   123  	})
   124  
   125  }
   126  
   127  func get(handler http.Handler, target string) *httptest.ResponseRecorder {
   128  	r := httptest.NewRequest("GET", target, nil)
   129  	w := httptest.NewRecorder()
   130  
   131  	handler.ServeHTTP(w, r)
   132  	return w
   133  }
   134  
   135  func post(handler http.Handler, target, contentType string) *httptest.ResponseRecorder {
   136  	r := httptest.NewRequest("POST", target, nil)
   137  	r.Header.Set("Content-Type", contentType)
   138  	w := httptest.NewRecorder()
   139  
   140  	handler.ServeHTTP(w, r)
   141  	return w
   142  }