1 package jsonutil_test
2
3 import (
4 "reflect"
5 "testing"
6 "time"
7
8 "github.com/shurcooL/graphql"
9 "github.com/shurcooL/graphql/internal/jsonutil"
10 )
11
12 func TestUnmarshalGraphQL(t *testing.T) {
13
21 type query struct {
22 Me struct {
23 Name graphql.String
24 Height graphql.Float
25 }
26 }
27 var got query
28 err := jsonutil.UnmarshalGraphQL([]byte(`{
29 "me": {
30 "name": "Luke Skywalker",
31 "height": 1.72
32 }
33 }`), &got)
34 if err != nil {
35 t.Fatal(err)
36 }
37 var want query
38 want.Me.Name = "Luke Skywalker"
39 want.Me.Height = 1.72
40 if !reflect.DeepEqual(got, want) {
41 t.Error("not equal")
42 }
43 }
44
45 func TestUnmarshalGraphQL_graphqlTag(t *testing.T) {
46 type query struct {
47 Foo graphql.String `graphql:"baz"`
48 }
49 var got query
50 err := jsonutil.UnmarshalGraphQL([]byte(`{
51 "baz": "bar"
52 }`), &got)
53 if err != nil {
54 t.Fatal(err)
55 }
56 want := query{
57 Foo: "bar",
58 }
59 if !reflect.DeepEqual(got, want) {
60 t.Error("not equal")
61 }
62 }
63
64 func TestUnmarshalGraphQL_jsonTag(t *testing.T) {
65 type query struct {
66 Foo graphql.String `json:"baz"`
67 }
68 var got query
69 err := jsonutil.UnmarshalGraphQL([]byte(`{
70 "foo": "bar"
71 }`), &got)
72 if err != nil {
73 t.Fatal(err)
74 }
75 want := query{
76 Foo: "bar",
77 }
78 if !reflect.DeepEqual(got, want) {
79 t.Error("not equal")
80 }
81 }
82
83 func TestUnmarshalGraphQL_array(t *testing.T) {
84 type query struct {
85 Foo []graphql.String
86 Bar []graphql.String
87 Baz []graphql.String
88 }
89 var got query
90 err := jsonutil.UnmarshalGraphQL([]byte(`{
91 "foo": [
92 "bar",
93 "baz"
94 ],
95 "bar": [],
96 "baz": null
97 }`), &got)
98 if err != nil {
99 t.Fatal(err)
100 }
101 want := query{
102 Foo: []graphql.String{"bar", "baz"},
103 Bar: []graphql.String{},
104 Baz: []graphql.String(nil),
105 }
106 if !reflect.DeepEqual(got, want) {
107 t.Error("not equal")
108 }
109 }
110
111
112
113 func TestUnmarshalGraphQL_arrayReset(t *testing.T) {
114 var got = []string{"initial"}
115 err := jsonutil.UnmarshalGraphQL([]byte(`["bar", "baz"]`), &got)
116 if err != nil {
117 t.Fatal(err)
118 }
119 want := []string{"bar", "baz"}
120 if !reflect.DeepEqual(got, want) {
121 t.Error("not equal")
122 }
123 }
124
125 func TestUnmarshalGraphQL_objectArray(t *testing.T) {
126 type query struct {
127 Foo []struct {
128 Name graphql.String
129 }
130 }
131 var got query
132 err := jsonutil.UnmarshalGraphQL([]byte(`{
133 "foo": [
134 {"name": "bar"},
135 {"name": "baz"}
136 ]
137 }`), &got)
138 if err != nil {
139 t.Fatal(err)
140 }
141 want := query{
142 Foo: []struct{ Name graphql.String }{
143 {"bar"},
144 {"baz"},
145 },
146 }
147 if !reflect.DeepEqual(got, want) {
148 t.Error("not equal")
149 }
150 }
151
152 func TestUnmarshalGraphQL_pointer(t *testing.T) {
153 type query struct {
154 Foo *graphql.String
155 Bar *graphql.String
156 }
157 var got query
158 got.Bar = new(graphql.String)
159 err := jsonutil.UnmarshalGraphQL([]byte(`{
160 "foo": "foo",
161 "bar": null
162 }`), &got)
163 if err != nil {
164 t.Fatal(err)
165 }
166 want := query{
167 Foo: graphql.NewString("foo"),
168 Bar: nil,
169 }
170 if !reflect.DeepEqual(got, want) {
171 t.Error("not equal")
172 }
173 }
174
175 func TestUnmarshalGraphQL_objectPointerArray(t *testing.T) {
176 type query struct {
177 Foo []*struct {
178 Name graphql.String
179 }
180 }
181 var got query
182 err := jsonutil.UnmarshalGraphQL([]byte(`{
183 "foo": [
184 {"name": "bar"},
185 null,
186 {"name": "baz"}
187 ]
188 }`), &got)
189 if err != nil {
190 t.Fatal(err)
191 }
192 want := query{
193 Foo: []*struct{ Name graphql.String }{
194 {"bar"},
195 nil,
196 {"baz"},
197 },
198 }
199 if !reflect.DeepEqual(got, want) {
200 t.Error("not equal")
201 }
202 }
203
204 func TestUnmarshalGraphQL_pointerWithInlineFragment(t *testing.T) {
205 type actor struct {
206 User struct {
207 DatabaseID uint64
208 } `graphql:"... on User"`
209 Login string
210 }
211 type query struct {
212 Author actor
213 Editor *actor
214 }
215 var got query
216 err := jsonutil.UnmarshalGraphQL([]byte(`{
217 "author": {
218 "databaseId": 1,
219 "login": "test1"
220 },
221 "editor": {
222 "databaseId": 2,
223 "login": "test2"
224 }
225 }`), &got)
226 if err != nil {
227 t.Fatal(err)
228 }
229 var want query
230 want.Author = actor{
231 User: struct{ DatabaseID uint64 }{1},
232 Login: "test1",
233 }
234 want.Editor = &actor{
235 User: struct{ DatabaseID uint64 }{2},
236 Login: "test2",
237 }
238
239 if !reflect.DeepEqual(got, want) {
240 t.Error("not equal")
241 }
242 }
243
244 func TestUnmarshalGraphQL_unexportedField(t *testing.T) {
245 type query struct {
246 foo graphql.String
247 }
248 err := jsonutil.UnmarshalGraphQL([]byte(`{"foo": "bar"}`), new(query))
249 if err == nil {
250 t.Fatal("got error: nil, want: non-nil")
251 }
252 if got, want := err.Error(), "struct field for \"foo\" doesn't exist in any of 1 places to unmarshal"; got != want {
253 t.Errorf("got error: %v, want: %v", got, want)
254 }
255 }
256
257 func TestUnmarshalGraphQL_multipleValues(t *testing.T) {
258 type query struct {
259 Foo graphql.String
260 }
261 err := jsonutil.UnmarshalGraphQL([]byte(`{"foo": "bar"}{"foo": "baz"}`), new(query))
262 if err == nil {
263 t.Fatal("got error: nil, want: non-nil")
264 }
265 if got, want := err.Error(), "invalid token '{' after top-level value"; got != want {
266 t.Errorf("got error: %v, want: %v", got, want)
267 }
268 }
269
270 func TestUnmarshalGraphQL_union(t *testing.T) {
271
284 type actor struct{ Login graphql.String }
285 type closedEvent struct {
286 Actor actor
287 CreatedAt time.Time
288 }
289 type reopenedEvent struct {
290 Actor actor
291 CreatedAt time.Time
292 }
293 type issueTimelineItem struct {
294 Typename string `graphql:"__typename"`
295 ClosedEvent closedEvent `graphql:"... on ClosedEvent"`
296 ReopenedEvent reopenedEvent `graphql:"... on ReopenedEvent"`
297 }
298 var got issueTimelineItem
299 err := jsonutil.UnmarshalGraphQL([]byte(`{
300 "__typename": "ClosedEvent",
301 "createdAt": "2017-06-29T04:12:01Z",
302 "actor": {
303 "login": "shurcooL-test"
304 }
305 }`), &got)
306 if err != nil {
307 t.Fatal(err)
308 }
309 want := issueTimelineItem{
310 Typename: "ClosedEvent",
311 ClosedEvent: closedEvent{
312 Actor: actor{
313 Login: "shurcooL-test",
314 },
315 CreatedAt: time.Unix(1498709521, 0).UTC(),
316 },
317 ReopenedEvent: reopenedEvent{
318 Actor: actor{
319 Login: "shurcooL-test",
320 },
321 CreatedAt: time.Unix(1498709521, 0).UTC(),
322 },
323 }
324 if !reflect.DeepEqual(got, want) {
325 t.Error("not equal")
326 }
327 }
328
329
330 func TestUnmarshalGraphQL_arrayInsideInlineFragment(t *testing.T) {
331
346 type query struct {
347 Search struct {
348 Nodes []struct {
349 PullRequest struct {
350 Commits struct {
351 Nodes []struct {
352 URL string `graphql:"url"`
353 }
354 } `graphql:"commits(last: 1)"`
355 } `graphql:"... on PullRequest"`
356 }
357 } `graphql:"search(type: ISSUE, first: 1, query: \"type:pr repo:owner/name\")"`
358 }
359 var got query
360 err := jsonutil.UnmarshalGraphQL([]byte(`{
361 "search": {
362 "nodes": [
363 {
364 "commits": {
365 "nodes": [
366 {
367 "url": "https://example.org/commit/49e1"
368 }
369 ]
370 }
371 }
372 ]
373 }
374 }`), &got)
375 if err != nil {
376 t.Fatal(err)
377 }
378 var want query
379 want.Search.Nodes = make([]struct {
380 PullRequest struct {
381 Commits struct {
382 Nodes []struct {
383 URL string `graphql:"url"`
384 }
385 } `graphql:"commits(last: 1)"`
386 } `graphql:"... on PullRequest"`
387 }, 1)
388 want.Search.Nodes[0].PullRequest.Commits.Nodes = make([]struct {
389 URL string `graphql:"url"`
390 }, 1)
391 want.Search.Nodes[0].PullRequest.Commits.Nodes[0].URL = "https://example.org/commit/49e1"
392 if !reflect.DeepEqual(got, want) {
393 t.Error("not equal")
394 }
395 }
396
View as plain text