1 package followschema
2
3 import (
4 "context"
5 "strconv"
6 "testing"
7 "time"
8
9 "github.com/stretchr/testify/require"
10
11 "github.com/99designs/gqlgen/client"
12 "github.com/99designs/gqlgen/graphql/handler"
13 )
14
15 func TestInput(t *testing.T) {
16 resolvers := &Stub{}
17 srv := handler.NewDefaultServer(NewExecutableSchema(Config{Resolvers: resolvers}))
18 c := client.New(srv)
19
20 t.Run("when function errors on directives", func(t *testing.T) {
21 resolvers.QueryResolver.InputSlice = func(ctx context.Context, arg []string) (b bool, e error) {
22 return true, nil
23 }
24
25 var resp struct {
26 DirectiveArg *string
27 }
28
29 err := c.Post(`query { inputSlice(arg: ["ok", 1, 2, "ok"]) }`, &resp)
30
31 require.EqualError(t, err, `http 422: {"errors":[{"message":"String cannot represent a non string value: 1","locations":[{"line":1,"column":32}],"extensions":{"code":"GRAPHQL_VALIDATION_FAILED"}},{"message":"String cannot represent a non string value: 2","locations":[{"line":1,"column":35}],"extensions":{"code":"GRAPHQL_VALIDATION_FAILED"}}],"data":null}`)
32 require.Nil(t, resp.DirectiveArg)
33 })
34
35 t.Run("when input slice nullable", func(t *testing.T) {
36 resolvers.QueryResolver.InputNullableSlice = func(ctx context.Context, arg []string) (b bool, e error) {
37 return arg == nil, nil
38 }
39
40 var resp struct {
41 InputNullableSlice bool
42 }
43 var err error
44 err = c.Post(`query { inputNullableSlice(arg: null) }`, &resp)
45 require.NoError(t, err)
46 require.True(t, resp.InputNullableSlice)
47
48 err = c.Post(`query { inputNullableSlice(arg: []) }`, &resp)
49 require.NoError(t, err)
50 require.False(t, resp.InputNullableSlice)
51 })
52
53 t.Run("coerce single value to slice", func(t *testing.T) {
54 check := func(ctx context.Context, arg []string) (b bool, e error) {
55 return len(arg) == 1 && arg[0] == "coerced", nil
56 }
57 resolvers.QueryResolver.InputSlice = check
58 resolvers.QueryResolver.InputNullableSlice = check
59
60 var resp struct {
61 Coerced bool
62 }
63 var err error
64 err = c.Post(`query { coerced: inputSlice(arg: "coerced") }`, &resp)
65 require.NoError(t, err)
66 require.True(t, resp.Coerced)
67
68 err = c.Post(`query { coerced: inputNullableSlice(arg: "coerced") }`, &resp)
69 require.NoError(t, err)
70 require.True(t, resp.Coerced)
71 })
72 }
73
74 func TestInputOmittable(t *testing.T) {
75 resolvers := &Stub{}
76 srv := handler.NewDefaultServer(NewExecutableSchema(Config{Resolvers: resolvers}))
77 c := client.New(srv)
78
79 t.Run("id field", func(t *testing.T) {
80 resolvers.QueryResolver.InputOmittable = func(ctx context.Context, arg OmittableInput) (string, error) {
81 value, isSet := arg.ID.ValueOK()
82 if !isSet {
83 return "<unset>", nil
84 }
85
86 if value == nil {
87 return "<nil>", nil
88 }
89
90 return *value, nil
91 }
92
93 var resp struct {
94 InputOmittable string
95 }
96 var err error
97
98 err = c.Post(`query { inputOmittable(arg: {}) }`, &resp)
99 require.NoError(t, err)
100 require.Equal(t, "<unset>", resp.InputOmittable)
101
102 err = c.Post(`query { inputOmittable(arg: { id: null }) }`, &resp)
103 require.NoError(t, err)
104 require.Equal(t, "<nil>", resp.InputOmittable)
105
106 err = c.Post(`query { inputOmittable(arg: { id: "foo" }) }`, &resp)
107 require.NoError(t, err)
108 require.Equal(t, "foo", resp.InputOmittable)
109 })
110
111 t.Run("bool field", func(t *testing.T) {
112 resolvers.QueryResolver.InputOmittable = func(ctx context.Context, arg OmittableInput) (string, error) {
113 value, isSet := arg.Bool.ValueOK()
114 if !isSet {
115 return "<unset>", nil
116 }
117
118 if value == nil {
119 return "<nil>", nil
120 }
121
122 return strconv.FormatBool(*value), nil
123 }
124
125 var resp struct {
126 InputOmittable string
127 }
128 var err error
129
130 err = c.Post(`query { inputOmittable(arg: {}) }`, &resp)
131 require.NoError(t, err)
132 require.Equal(t, "<unset>", resp.InputOmittable)
133
134 err = c.Post(`query { inputOmittable(arg: { bool: null }) }`, &resp)
135 require.NoError(t, err)
136 require.Equal(t, "<nil>", resp.InputOmittable)
137
138 err = c.Post(`query { inputOmittable(arg: { bool: false }) }`, &resp)
139 require.NoError(t, err)
140 require.Equal(t, "false", resp.InputOmittable)
141
142 err = c.Post(`query { inputOmittable(arg: { bool: true }) }`, &resp)
143 require.NoError(t, err)
144 require.Equal(t, "true", resp.InputOmittable)
145 })
146
147 t.Run("str field", func(t *testing.T) {
148 resolvers.QueryResolver.InputOmittable = func(ctx context.Context, arg OmittableInput) (string, error) {
149 value, isSet := arg.Str.ValueOK()
150 if !isSet {
151 return "<unset>", nil
152 }
153
154 if value == nil {
155 return "<nil>", nil
156 }
157
158 return *value, nil
159 }
160
161 var resp struct {
162 InputOmittable string
163 }
164 var err error
165
166 err = c.Post(`query { inputOmittable(arg: {}) }`, &resp)
167 require.NoError(t, err)
168 require.Equal(t, "<unset>", resp.InputOmittable)
169
170 err = c.Post(`query { inputOmittable(arg: { str: null }) }`, &resp)
171 require.NoError(t, err)
172 require.Equal(t, "<nil>", resp.InputOmittable)
173
174 err = c.Post(`query { inputOmittable(arg: { str: "bar" }) }`, &resp)
175 require.NoError(t, err)
176 require.Equal(t, "bar", resp.InputOmittable)
177 })
178
179 t.Run("int field", func(t *testing.T) {
180 resolvers.QueryResolver.InputOmittable = func(ctx context.Context, arg OmittableInput) (string, error) {
181 value, isSet := arg.Int.ValueOK()
182 if !isSet {
183 return "<unset>", nil
184 }
185
186 if value == nil {
187 return "<nil>", nil
188 }
189
190 return strconv.Itoa(*value), nil
191 }
192
193 var resp struct {
194 InputOmittable string
195 }
196 var err error
197
198 err = c.Post(`query { inputOmittable(arg: {}) }`, &resp)
199 require.NoError(t, err)
200 require.Equal(t, "<unset>", resp.InputOmittable)
201
202 err = c.Post(`query { inputOmittable(arg: { int: null }) }`, &resp)
203 require.NoError(t, err)
204 require.Equal(t, "<nil>", resp.InputOmittable)
205
206 err = c.Post(`query { inputOmittable(arg: { int: 42 }) }`, &resp)
207 require.NoError(t, err)
208 require.Equal(t, "42", resp.InputOmittable)
209 })
210
211 t.Run("time field", func(t *testing.T) {
212 resolvers.QueryResolver.InputOmittable = func(ctx context.Context, arg OmittableInput) (string, error) {
213 value, isSet := arg.Time.ValueOK()
214 if !isSet {
215 return "<unset>", nil
216 }
217
218 if value == nil {
219 return "<nil>", nil
220 }
221
222 return value.UTC().Format(time.RFC3339), nil
223 }
224
225 var resp struct {
226 InputOmittable string
227 }
228 var err error
229
230 err = c.Post(`query { inputOmittable(arg: {}) }`, &resp)
231 require.NoError(t, err)
232 require.Equal(t, "<unset>", resp.InputOmittable)
233
234 err = c.Post(`query { inputOmittable(arg: { time: null }) }`, &resp)
235 require.NoError(t, err)
236 require.Equal(t, "<nil>", resp.InputOmittable)
237
238 err = c.Post(`query { inputOmittable(arg: { time: "2011-04-05T16:01:33Z" }) }`, &resp)
239 require.NoError(t, err)
240 require.Equal(t, "2011-04-05T16:01:33Z", resp.InputOmittable)
241 })
242
243 t.Run("enum field", func(t *testing.T) {
244 resolvers.QueryResolver.InputOmittable = func(ctx context.Context, arg OmittableInput) (string, error) {
245 value, isSet := arg.Enum.ValueOK()
246 if !isSet {
247 return "<unset>", nil
248 }
249
250 if value == nil {
251 return "<nil>", nil
252 }
253
254 return value.String(), nil
255 }
256
257 var resp struct {
258 InputOmittable string
259 }
260 var err error
261
262 err = c.Post(`query { inputOmittable(arg: {}) }`, &resp)
263 require.NoError(t, err)
264 require.Equal(t, "<unset>", resp.InputOmittable)
265
266 err = c.Post(`query { inputOmittable(arg: { enum: null }) }`, &resp)
267 require.NoError(t, err)
268 require.Equal(t, "<nil>", resp.InputOmittable)
269
270 err = c.Post(`query { inputOmittable(arg: { enum: OK }) }`, &resp)
271 require.NoError(t, err)
272 require.Equal(t, "OK", resp.InputOmittable)
273
274 err = c.Post(`query { inputOmittable(arg: { enum: ERROR }) }`, &resp)
275 require.NoError(t, err)
276 require.Equal(t, "ERROR", resp.InputOmittable)
277 })
278
279 t.Run("scalar field", func(t *testing.T) {
280 resolvers.QueryResolver.InputOmittable = func(ctx context.Context, arg OmittableInput) (string, error) {
281 value, isSet := arg.Scalar.ValueOK()
282 if !isSet {
283 return "<unset>", nil
284 }
285
286 if value == nil {
287 return "<nil>", nil
288 }
289
290 return value.str, nil
291 }
292
293 var resp struct {
294 InputOmittable string
295 }
296 var err error
297
298 err = c.Post(`query { inputOmittable(arg: {}) }`, &resp)
299 require.NoError(t, err)
300 require.Equal(t, "<unset>", resp.InputOmittable)
301
302 err = c.Post(`query { inputOmittable(arg: { scalar: null }) }`, &resp)
303 require.NoError(t, err)
304 require.Equal(t, "<nil>", resp.InputOmittable)
305
306 err = c.Post(`query { inputOmittable(arg: { scalar: "baz" }) }`, &resp)
307 require.NoError(t, err)
308 require.Equal(t, "baz", resp.InputOmittable)
309 })
310
311 t.Run("object field", func(t *testing.T) {
312 resolvers.QueryResolver.InputOmittable = func(ctx context.Context, arg OmittableInput) (string, error) {
313 value, isSet := arg.Object.ValueOK()
314 if !isSet {
315 return "<unset>", nil
316 }
317
318 if value == nil {
319 return "<nil>", nil
320 }
321
322 return strconv.Itoa(value.Inner.ID), nil
323 }
324
325 var resp struct {
326 InputOmittable string
327 }
328 var err error
329
330 err = c.Post(`query { inputOmittable(arg: {}) }`, &resp)
331 require.NoError(t, err)
332 require.Equal(t, "<unset>", resp.InputOmittable)
333
334 err = c.Post(`query { inputOmittable(arg: { object: null }) }`, &resp)
335 require.NoError(t, err)
336 require.Equal(t, "<nil>", resp.InputOmittable)
337
338 err = c.Post(`query { inputOmittable(arg: { object: { inner: { id: 21 } } }) }`, &resp)
339 require.NoError(t, err)
340 require.Equal(t, "21", resp.InputOmittable)
341 })
342 }
343
View as plain text