github.com/maeglindeveloper/gqlgen@v0.13.1-0.20210413081235-57808b12a0a0/graphql/handler/extension/apq_test.go (about) 1 package extension_test 2 3 import ( 4 "context" 5 "net/http" 6 "testing" 7 8 "github.com/99designs/gqlgen/graphql" 9 "github.com/99designs/gqlgen/graphql/handler/extension" 10 "github.com/99designs/gqlgen/graphql/handler/testserver" 11 "github.com/99designs/gqlgen/graphql/handler/transport" 12 "github.com/stretchr/testify/require" 13 ) 14 15 func TestAPQIntegration(t *testing.T) { 16 h := testserver.New() 17 h.Use(&extension.AutomaticPersistedQuery{Cache: graphql.MapCache{}}) 18 h.AddTransport(&transport.POST{}) 19 20 var stats *extension.ApqStats 21 h.AroundResponses(func(ctx context.Context, next graphql.ResponseHandler) *graphql.Response { 22 stats = extension.GetApqStats(ctx) 23 return next(ctx) 24 }) 25 26 resp := doRequest(h, "POST", "/graphql", `{"query":"{ name }","extensions":{"persistedQuery":{"version":1,"sha256Hash":"30166fc3298853f22709fce1e4a00e98f1b6a3160eaaaf9cb3b7db6a16073b07"}}}`) 27 require.Equal(t, http.StatusOK, resp.Code, resp.Body.String()) 28 require.Equal(t, `{"data":{"name":"test"}}`, resp.Body.String()) 29 30 require.NotNil(t, stats) 31 require.True(t, stats.SentQuery) 32 require.Equal(t, "30166fc3298853f22709fce1e4a00e98f1b6a3160eaaaf9cb3b7db6a16073b07", stats.Hash) 33 } 34 35 func TestAPQ(t *testing.T) { 36 const query = "{ me { name } }" 37 const hash = "b8d9506e34c83b0e53c2aa463624fcea354713bc38f95276e6f0bd893ffb5b88" 38 39 t.Run("with query and no hash", func(t *testing.T) { 40 ctx := newOC() 41 params := &graphql.RawParams{ 42 Query: "original query", 43 } 44 err := extension.AutomaticPersistedQuery{graphql.MapCache{}}.MutateOperationParameters(ctx, params) 45 require.Nil(t, err) 46 47 require.Equal(t, "original query", params.Query) 48 }) 49 50 t.Run("with hash miss and no query", func(t *testing.T) { 51 ctx := newOC() 52 params := &graphql.RawParams{ 53 Extensions: map[string]interface{}{ 54 "persistedQuery": map[string]interface{}{ 55 "sha256Hash": hash, 56 "version": 1, 57 }, 58 }, 59 } 60 61 err := extension.AutomaticPersistedQuery{graphql.MapCache{}}.MutateOperationParameters(ctx, params) 62 require.Equal(t, err.Message, "PersistedQueryNotFound") 63 }) 64 65 t.Run("with hash miss and query", func(t *testing.T) { 66 ctx := newOC() 67 params := &graphql.RawParams{ 68 Query: query, 69 Extensions: map[string]interface{}{ 70 "persistedQuery": map[string]interface{}{ 71 "sha256Hash": hash, 72 "version": 1, 73 }, 74 }, 75 } 76 cache := graphql.MapCache{} 77 err := extension.AutomaticPersistedQuery{cache}.MutateOperationParameters(ctx, params) 78 require.Nil(t, err) 79 80 require.Equal(t, "{ me { name } }", params.Query) 81 require.Equal(t, "{ me { name } }", cache[hash]) 82 }) 83 84 t.Run("with hash miss and query", func(t *testing.T) { 85 ctx := newOC() 86 params := &graphql.RawParams{ 87 Query: query, 88 Extensions: map[string]interface{}{ 89 "persistedQuery": map[string]interface{}{ 90 "sha256Hash": hash, 91 "version": 1, 92 }, 93 }, 94 } 95 cache := graphql.MapCache{} 96 err := extension.AutomaticPersistedQuery{cache}.MutateOperationParameters(ctx, params) 97 require.Nil(t, err) 98 99 require.Equal(t, "{ me { name } }", params.Query) 100 require.Equal(t, "{ me { name } }", cache[hash]) 101 }) 102 103 t.Run("with hash hit and no query", func(t *testing.T) { 104 ctx := newOC() 105 params := &graphql.RawParams{ 106 Extensions: map[string]interface{}{ 107 "persistedQuery": map[string]interface{}{ 108 "sha256Hash": hash, 109 "version": 1, 110 }, 111 }, 112 } 113 cache := graphql.MapCache{ 114 hash: query, 115 } 116 err := extension.AutomaticPersistedQuery{cache}.MutateOperationParameters(ctx, params) 117 require.Nil(t, err) 118 119 require.Equal(t, "{ me { name } }", params.Query) 120 }) 121 122 t.Run("with malformed extension payload", func(t *testing.T) { 123 ctx := newOC() 124 params := &graphql.RawParams{ 125 Extensions: map[string]interface{}{ 126 "persistedQuery": "asdf", 127 }, 128 } 129 130 err := extension.AutomaticPersistedQuery{graphql.MapCache{}}.MutateOperationParameters(ctx, params) 131 require.Equal(t, err.Message, "invalid APQ extension data") 132 }) 133 134 t.Run("with invalid extension version", func(t *testing.T) { 135 ctx := newOC() 136 params := &graphql.RawParams{ 137 Extensions: map[string]interface{}{ 138 "persistedQuery": map[string]interface{}{ 139 "version": 2, 140 }, 141 }, 142 } 143 err := extension.AutomaticPersistedQuery{graphql.MapCache{}}.MutateOperationParameters(ctx, params) 144 require.Equal(t, err.Message, "unsupported APQ version") 145 }) 146 147 t.Run("with hash mismatch", func(t *testing.T) { 148 ctx := newOC() 149 params := &graphql.RawParams{ 150 Query: query, 151 Extensions: map[string]interface{}{ 152 "persistedQuery": map[string]interface{}{ 153 "sha256Hash": "badhash", 154 "version": 1, 155 }, 156 }, 157 } 158 159 err := extension.AutomaticPersistedQuery{graphql.MapCache{}}.MutateOperationParameters(ctx, params) 160 require.Equal(t, err.Message, "provided APQ hash does not match query") 161 }) 162 } 163 164 func newOC() context.Context { 165 oc := &graphql.OperationContext{} 166 return graphql.WithOperationContext(context.Background(), oc) 167 }