@platformatic/sql-graphql 0.0.23

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (54) hide show
  1. package/.nyc_output/0681b2b7-587a-40f2-8242-257bc4c72456.json +1 -0
  2. package/.nyc_output/191054d4-6a1e-4a1b-87bb-f801ed78a223.json +1 -0
  3. package/.nyc_output/22ead0f6-e5a6-4647-a2ea-db2f42498081.json +1 -0
  4. package/.nyc_output/4e847e26-05cd-4063-9277-48aff86d6822.json +1 -0
  5. package/.nyc_output/5acfd416-02d1-497b-8dbd-69c0af167c62.json +1 -0
  6. package/.nyc_output/5ec04f76-9bcb-475d-b79e-f9304cc0026c.json +1 -0
  7. package/.nyc_output/5f3bb47a-0d2d-440a-a466-8ffa9ab3efaa.json +1 -0
  8. package/.nyc_output/71c2bd84-9a72-4e86-83c6-d587ce525fe4.json +1 -0
  9. package/.nyc_output/74cc1dab-7479-48e7-80b0-c97351d8856e.json +1 -0
  10. package/.nyc_output/9f5d12ba-bc3d-461c-a0e2-2a95d2020c19.json +1 -0
  11. package/.nyc_output/ac343b71-6f76-421c-a287-46d19bb48f89.json +1 -0
  12. package/.nyc_output/c1c0eecb-63a0-4258-81b6-50e7488bd67c.json +1 -0
  13. package/.nyc_output/c201a1cd-3105-4d18-bbbb-8d7fa674d439.json +1 -0
  14. package/.nyc_output/d6da0270-e9ed-41e2-bbf3-9262d1df683c.json +1 -0
  15. package/.nyc_output/processinfo/0681b2b7-587a-40f2-8242-257bc4c72456.json +1 -0
  16. package/.nyc_output/processinfo/191054d4-6a1e-4a1b-87bb-f801ed78a223.json +1 -0
  17. package/.nyc_output/processinfo/22ead0f6-e5a6-4647-a2ea-db2f42498081.json +1 -0
  18. package/.nyc_output/processinfo/4e847e26-05cd-4063-9277-48aff86d6822.json +1 -0
  19. package/.nyc_output/processinfo/5acfd416-02d1-497b-8dbd-69c0af167c62.json +1 -0
  20. package/.nyc_output/processinfo/5ec04f76-9bcb-475d-b79e-f9304cc0026c.json +1 -0
  21. package/.nyc_output/processinfo/5f3bb47a-0d2d-440a-a466-8ffa9ab3efaa.json +1 -0
  22. package/.nyc_output/processinfo/71c2bd84-9a72-4e86-83c6-d587ce525fe4.json +1 -0
  23. package/.nyc_output/processinfo/74cc1dab-7479-48e7-80b0-c97351d8856e.json +1 -0
  24. package/.nyc_output/processinfo/9f5d12ba-bc3d-461c-a0e2-2a95d2020c19.json +1 -0
  25. package/.nyc_output/processinfo/ac343b71-6f76-421c-a287-46d19bb48f89.json +1 -0
  26. package/.nyc_output/processinfo/c1c0eecb-63a0-4258-81b6-50e7488bd67c.json +1 -0
  27. package/.nyc_output/processinfo/c201a1cd-3105-4d18-bbbb-8d7fa674d439.json +1 -0
  28. package/.nyc_output/processinfo/d6da0270-e9ed-41e2-bbf3-9262d1df683c.json +1 -0
  29. package/.nyc_output/processinfo/index.json +1 -0
  30. package/.taprc +1 -0
  31. package/LICENSE +201 -0
  32. package/NOTICE +13 -0
  33. package/README.md +13 -0
  34. package/index.d.ts +40 -0
  35. package/index.js +117 -0
  36. package/lib/entity-to-type.js +248 -0
  37. package/lib/relationship.js +67 -0
  38. package/lib/utils.js +77 -0
  39. package/package.json +44 -0
  40. package/test/datatypes.test.js +708 -0
  41. package/test/federation.test.js +312 -0
  42. package/test/helper.js +70 -0
  43. package/test/hooks.test.js +660 -0
  44. package/test/ignore.test.js +117 -0
  45. package/test/insert.test.js +181 -0
  46. package/test/inserted_updated_at.test.js +517 -0
  47. package/test/nested.test.js +862 -0
  48. package/test/no-modification-of-entity.test.js +113 -0
  49. package/test/order_by.test.js +397 -0
  50. package/test/relations.test.js +60 -0
  51. package/test/simple.test.js +708 -0
  52. package/test/sqlite.test.js +276 -0
  53. package/test/types/index.test-d.ts +33 -0
  54. package/test/where.test.js +814 -0
@@ -0,0 +1,862 @@
1
+ 'use strict'
2
+
3
+ const { test } = require('tap')
4
+ const sqlGraphQL = require('..')
5
+ const sqlMapper = require('@platformatic/sql-mapper')
6
+ const fastify = require('fastify')
7
+ const { clear, connInfo, isMysql, isSQLite } = require('./helper')
8
+
9
+ test('nested resolver', async ({ pass, teardown, same, equal }) => {
10
+ const app = fastify()
11
+ app.register(sqlMapper, {
12
+ ...connInfo,
13
+ async onDatabaseLoad (db, sql) {
14
+ pass('onDatabaseLoad called')
15
+
16
+ await clear(db, sql)
17
+
18
+ if (isMysql) {
19
+ await db.query(sql`
20
+ CREATE TABLE categories (
21
+ id SERIAL PRIMARY KEY,
22
+ name VARCHAR(255)
23
+ );
24
+ CREATE TABLE pages (
25
+ id SERIAL PRIMARY KEY,
26
+ title VARCHAR(42),
27
+ category_id BIGINT UNSIGNED,
28
+ FOREIGN KEY (category_id) REFERENCES categories(id) ON DELETE CASCADE
29
+ );
30
+ `)
31
+ } else if (isSQLite) {
32
+ await db.query(sql`
33
+ CREATE TABLE categories (
34
+ id INTEGER PRIMARY KEY,
35
+ name VARCHAR(42)
36
+ );
37
+ `)
38
+ await db.query(sql`
39
+ CREATE TABLE pages (
40
+ id INTEGER PRIMARY KEY,
41
+ title VARCHAR(42),
42
+ category_id INTEGER REFERENCES categories(id)
43
+ );
44
+ `)
45
+ } else {
46
+ await db.query(sql`
47
+ CREATE TABLE categories (
48
+ id SERIAL PRIMARY KEY,
49
+ name VARCHAR(42)
50
+ );
51
+ CREATE TABLE pages (
52
+ id SERIAL PRIMARY KEY,
53
+ title VARCHAR(42),
54
+ category_id INTEGER REFERENCES categories(id)
55
+ );
56
+ `)
57
+ }
58
+ }
59
+ })
60
+ app.register(sqlGraphQL)
61
+ teardown(app.close.bind(app))
62
+
63
+ const categories = [{
64
+ name: 'Pets'
65
+ }, {
66
+ name: 'Food'
67
+ }]
68
+
69
+ await app.inject({
70
+ method: 'POST',
71
+ url: '/graphql',
72
+ body: {
73
+ query: `
74
+ mutation batch($inputs: [CategoryInput]!) {
75
+ insertCategories(inputs: $inputs) {
76
+ id
77
+ name
78
+ }
79
+ }
80
+ `,
81
+ variables: {
82
+ inputs: categories
83
+ }
84
+ }
85
+ })
86
+
87
+ {
88
+ const res = await app.inject({
89
+ method: 'POST',
90
+ url: '/graphql',
91
+ body: {
92
+ query: `
93
+ mutation {
94
+ savePage(input: { title: "Hello", categoryId: 1 }) {
95
+ id
96
+ title
97
+ category {
98
+ id
99
+ name
100
+ }
101
+ }
102
+ }
103
+ `
104
+ }
105
+ })
106
+ equal(res.statusCode, 200, 'savePage status code')
107
+ same(res.json(), {
108
+ data: {
109
+ savePage: {
110
+ id: 1,
111
+ title: 'Hello',
112
+ category: {
113
+ id: 1,
114
+ name: 'Pets'
115
+ }
116
+ }
117
+ }
118
+ }, 'savePage response')
119
+ }
120
+
121
+ {
122
+ const res = await app.inject({
123
+ method: 'POST',
124
+ url: '/graphql',
125
+ body: {
126
+ query: `
127
+ query {
128
+ getPageById(id: 1) {
129
+ id
130
+ title
131
+ category {
132
+ id
133
+ name
134
+ pages {
135
+ id
136
+ title
137
+ category {
138
+ id
139
+ name
140
+ }
141
+ }
142
+ }
143
+ }
144
+ }
145
+ `
146
+ }
147
+ })
148
+ equal(res.statusCode, 200, 'pages status code')
149
+ same(res.json(), {
150
+ data: {
151
+ getPageById: {
152
+ id: 1,
153
+ title: 'Hello',
154
+ category: {
155
+ id: 1,
156
+ name: 'Pets',
157
+ pages: [{
158
+ id: 1,
159
+ title: 'Hello',
160
+ category: {
161
+ id: 1,
162
+ name: 'Pets'
163
+ }
164
+ }]
165
+ }
166
+ }
167
+ }
168
+ }, 'pages response')
169
+ }
170
+
171
+ // Without ids
172
+ {
173
+ const res = await app.inject({
174
+ method: 'POST',
175
+ url: '/graphql',
176
+ body: {
177
+ query: `
178
+ query {
179
+ getPageById(id: 1) {
180
+ title
181
+ category {
182
+ name
183
+ pages {
184
+ title
185
+ category {
186
+ name
187
+ }
188
+ }
189
+ }
190
+ }
191
+ }
192
+ `
193
+ }
194
+ })
195
+ equal(res.statusCode, 200, 'pages status code')
196
+ same(res.json(), {
197
+ data: {
198
+ getPageById: {
199
+ title: 'Hello',
200
+ category: {
201
+ name: 'Pets',
202
+ pages: [{
203
+ title: 'Hello',
204
+ category: {
205
+ name: 'Pets'
206
+ }
207
+ }]
208
+ }
209
+ }
210
+ }
211
+ }, 'pages response')
212
+ }
213
+
214
+ {
215
+ const res = await app.inject({
216
+ method: 'POST',
217
+ url: '/graphql',
218
+ body: {
219
+ query: `
220
+ query {
221
+ categories {
222
+ id
223
+ name
224
+ pages {
225
+ id
226
+ title
227
+ category {
228
+ id
229
+ name
230
+ }
231
+ }
232
+ }
233
+ }
234
+ `
235
+ }
236
+ })
237
+ equal(res.statusCode, 200, 'categories.posts status code')
238
+ same(res.json(), {
239
+ data: {
240
+ categories: [{
241
+ id: 1,
242
+ name: 'Pets',
243
+ pages: [{
244
+ id: 1,
245
+ title: 'Hello',
246
+ category: {
247
+ id: 1,
248
+ name: 'Pets'
249
+ }
250
+ }]
251
+ }, {
252
+ id: 2,
253
+ name: 'Food',
254
+ pages: []
255
+ }]
256
+ }
257
+ }, 'categories.posts response')
258
+ }
259
+ })
260
+
261
+ test('disable one-too-many', async ({ pass, teardown, same, equal, match }) => {
262
+ const app = fastify()
263
+ app.register(sqlMapper, {
264
+ ...connInfo,
265
+ async onDatabaseLoad (db, sql) {
266
+ pass('onDatabaseLoad called')
267
+
268
+ await clear(db, sql)
269
+
270
+ if (isMysql) {
271
+ await db.query(sql`
272
+ CREATE TABLE categories (
273
+ id SERIAL PRIMARY KEY,
274
+ name VARCHAR(255)
275
+ );
276
+ CREATE TABLE pages (
277
+ id SERIAL PRIMARY KEY,
278
+ title VARCHAR(42),
279
+ category_id BIGINT UNSIGNED,
280
+ FOREIGN KEY (category_id) REFERENCES categories(id) ON DELETE CASCADE
281
+ );
282
+ `)
283
+ } else if (isSQLite) {
284
+ await db.query(sql`
285
+ CREATE TABLE categories (
286
+ id INTEGER PRIMARY KEY,
287
+ name VARCHAR(42)
288
+ );
289
+ `)
290
+ await db.query(sql`
291
+ CREATE TABLE pages (
292
+ id INTEGER PRIMARY KEY,
293
+ title VARCHAR(42),
294
+ category_id INTEGER REFERENCES categories(id)
295
+ );
296
+ `)
297
+ } else {
298
+ await db.query(sql`
299
+ CREATE TABLE categories (
300
+ id SERIAL PRIMARY KEY,
301
+ name VARCHAR(42)
302
+ );
303
+ CREATE TABLE pages (
304
+ id SERIAL PRIMARY KEY,
305
+ title VARCHAR(42),
306
+ category_id INTEGER REFERENCES categories(id)
307
+ );
308
+ `)
309
+ }
310
+ }
311
+ })
312
+ app.register(sqlGraphQL, {
313
+ resolvers: {
314
+ Category: {
315
+ pages: false
316
+ }
317
+ }
318
+ })
319
+ teardown(app.close.bind(app))
320
+
321
+ const categories = [{
322
+ name: 'Pets'
323
+ }, {
324
+ name: 'Food'
325
+ }]
326
+
327
+ await app.inject({
328
+ method: 'POST',
329
+ url: '/graphql',
330
+ body: {
331
+ query: `
332
+ mutation batch($inputs: [CategoryInput]!) {
333
+ insertCategories(inputs: $inputs) {
334
+ id
335
+ name
336
+ }
337
+ }
338
+ `,
339
+ variables: {
340
+ inputs: categories
341
+ }
342
+ }
343
+ })
344
+
345
+ {
346
+ const res = await app.inject({
347
+ method: 'POST',
348
+ url: '/graphql',
349
+ body: {
350
+ query: `
351
+ mutation {
352
+ savePage(input: { title: "Hello", categoryId: 1 }) {
353
+ id
354
+ title
355
+ category {
356
+ id
357
+ name
358
+ }
359
+ }
360
+ }
361
+ `
362
+ }
363
+ })
364
+ equal(res.statusCode, 200, 'savePage status code')
365
+ same(res.json(), {
366
+ data: {
367
+ savePage: {
368
+ id: 1,
369
+ title: 'Hello',
370
+ category: {
371
+ id: 1,
372
+ name: 'Pets'
373
+ }
374
+ }
375
+ }
376
+ }, 'savePage response')
377
+ }
378
+
379
+ {
380
+ const res = await app.inject({
381
+ method: 'POST',
382
+ url: '/graphql',
383
+ body: {
384
+ query: `
385
+ query {
386
+ getPageById(id: 1) {
387
+ id
388
+ title
389
+ category {
390
+ id
391
+ name
392
+ }
393
+ }
394
+ }
395
+ `
396
+ }
397
+ })
398
+ equal(res.statusCode, 200, 'pages status code')
399
+ same(res.json(), {
400
+ data: {
401
+ getPageById: {
402
+ id: 1,
403
+ title: 'Hello',
404
+ category: {
405
+ id: 1,
406
+ name: 'Pets'
407
+ }
408
+ }
409
+ }
410
+ }, 'pages response')
411
+ }
412
+
413
+ {
414
+ const res = await app.inject({
415
+ method: 'POST',
416
+ url: '/graphql',
417
+ body: {
418
+ query: `
419
+ query {
420
+ categories {
421
+ id
422
+ name
423
+ pages {
424
+ id
425
+ title
426
+ category {
427
+ id
428
+ name
429
+ }
430
+ }
431
+ }
432
+ }
433
+ `
434
+ }
435
+ })
436
+ equal(res.statusCode, 400, 'categories.posts status code')
437
+ match(res.json(), {
438
+ errors: [{
439
+ message: 'Cannot query field "pages" on type "Category". Did you mean "name"?'
440
+ }]
441
+ }, 'categories.posts response')
442
+ }
443
+ })
444
+
445
+ test('disable many-to-one relationship', async ({ pass, teardown, same, equal, match }) => {
446
+ const app = fastify()
447
+ app.register(sqlMapper, {
448
+ ...connInfo,
449
+ async onDatabaseLoad (db, sql) {
450
+ pass('onDatabaseLoad called')
451
+
452
+ await clear(db, sql)
453
+
454
+ if (isMysql) {
455
+ await db.query(sql`
456
+ CREATE TABLE categories (
457
+ id SERIAL PRIMARY KEY,
458
+ name VARCHAR(255)
459
+ );
460
+ CREATE TABLE pages (
461
+ id SERIAL PRIMARY KEY,
462
+ title VARCHAR(42),
463
+ category_id BIGINT UNSIGNED,
464
+ FOREIGN KEY (category_id) REFERENCES categories(id) ON DELETE CASCADE
465
+ );
466
+ `)
467
+ } else if (isSQLite) {
468
+ await db.query(sql`
469
+ CREATE TABLE categories (
470
+ id INTEGER PRIMARY KEY,
471
+ name VARCHAR(42)
472
+ );
473
+ `)
474
+ await db.query(sql`
475
+ CREATE TABLE pages (
476
+ id INTEGER PRIMARY KEY,
477
+ title VARCHAR(42),
478
+ category_id INTEGER REFERENCES categories(id)
479
+ );
480
+ `)
481
+ } else {
482
+ await db.query(sql`
483
+ CREATE TABLE categories (
484
+ id SERIAL PRIMARY KEY,
485
+ name VARCHAR(42)
486
+ );
487
+ CREATE TABLE pages (
488
+ id SERIAL PRIMARY KEY,
489
+ title VARCHAR(42),
490
+ category_id INTEGER REFERENCES categories(id)
491
+ );
492
+ `)
493
+ }
494
+ }
495
+ })
496
+ app.register(sqlGraphQL, {
497
+ resolvers: {
498
+ Page: {
499
+ category: false
500
+ }
501
+ }
502
+ })
503
+ teardown(app.close.bind(app))
504
+
505
+ const categories = [{
506
+ name: 'Pets'
507
+ }, {
508
+ name: 'Food'
509
+ }]
510
+
511
+ await app.inject({
512
+ method: 'POST',
513
+ url: '/graphql',
514
+ body: {
515
+ query: `
516
+ mutation batch($inputs: [CategoryInput]!) {
517
+ insertCategories(inputs: $inputs) {
518
+ id
519
+ name
520
+ }
521
+ }
522
+ `,
523
+ variables: {
524
+ inputs: categories
525
+ }
526
+ }
527
+ })
528
+
529
+ {
530
+ const res = await app.inject({
531
+ method: 'POST',
532
+ url: '/graphql',
533
+ body: {
534
+ query: `
535
+ mutation {
536
+ savePage(input: { title: "Hello", categoryId: 1 }) {
537
+ id
538
+ title
539
+ }
540
+ }
541
+ `
542
+ }
543
+ })
544
+ equal(res.statusCode, 200, 'savePage status code')
545
+ same(res.json(), {
546
+ data: {
547
+ savePage: {
548
+ id: 1,
549
+ title: 'Hello'
550
+ }
551
+ }
552
+ }, 'savePage response')
553
+ }
554
+
555
+ {
556
+ const res = await app.inject({
557
+ method: 'POST',
558
+ url: '/graphql',
559
+ body: {
560
+ query: `
561
+ query {
562
+ getPageById(id: 1) {
563
+ id
564
+ title
565
+ category {
566
+ id
567
+ name
568
+ }
569
+ }
570
+ }
571
+ `
572
+ }
573
+ })
574
+ equal(res.statusCode, 400, 'pages status code')
575
+ match(res.json(), {
576
+ errors: [{
577
+ message: 'Cannot query field "category" on type "Page". Did you mean "categoryId"?'
578
+ }]
579
+ }, 'pages response')
580
+ }
581
+
582
+ {
583
+ const res = await app.inject({
584
+ method: 'POST',
585
+ url: '/graphql',
586
+ body: {
587
+ query: `
588
+ query {
589
+ categories {
590
+ id
591
+ name
592
+ pages {
593
+ id
594
+ title
595
+ }
596
+ }
597
+ }
598
+ `
599
+ }
600
+ })
601
+ equal(res.statusCode, 200, 'categories.posts status code')
602
+ same(res.json(), {
603
+ data: {
604
+ categories: [{
605
+ id: 1,
606
+ name: 'Pets',
607
+ pages: [{
608
+ id: 1,
609
+ title: 'Hello'
610
+ }]
611
+ }, {
612
+ id: 2,
613
+ name: 'Food',
614
+ pages: []
615
+ }]
616
+ }
617
+ }, 'categories.posts response')
618
+ }
619
+ })
620
+
621
+ test('nested update', async ({ pass, teardown, same, equal }) => {
622
+ const app = fastify()
623
+ app.register(sqlMapper, {
624
+ ...connInfo,
625
+ async onDatabaseLoad (db, sql) {
626
+ pass('onDatabaseLoad called')
627
+
628
+ await clear(db, sql)
629
+
630
+ if (isMysql) {
631
+ await db.query(sql`
632
+ CREATE TABLE categories (
633
+ id SERIAL PRIMARY KEY,
634
+ name VARCHAR(255)
635
+ );
636
+ CREATE TABLE pages (
637
+ id SERIAL PRIMARY KEY,
638
+ title VARCHAR(42),
639
+ category_id BIGINT UNSIGNED,
640
+ FOREIGN KEY (category_id) REFERENCES categories(id) ON DELETE CASCADE
641
+ );
642
+ `)
643
+ } else if (isSQLite) {
644
+ await db.query(sql`
645
+ CREATE TABLE categories (
646
+ id INTEGER PRIMARY KEY,
647
+ name VARCHAR(42)
648
+ );
649
+ `)
650
+ await db.query(sql`
651
+ CREATE TABLE pages (
652
+ id INTEGER PRIMARY KEY,
653
+ title VARCHAR(42),
654
+ category_id INTEGER REFERENCES categories(id)
655
+ );
656
+ `)
657
+ } else {
658
+ await db.query(sql`
659
+ CREATE TABLE categories (
660
+ id SERIAL PRIMARY KEY,
661
+ name VARCHAR(42)
662
+ );
663
+ CREATE TABLE pages (
664
+ id SERIAL PRIMARY KEY,
665
+ title VARCHAR(42),
666
+ category_id INTEGER REFERENCES categories(id)
667
+ );
668
+ `)
669
+ }
670
+ }
671
+ })
672
+ app.register(sqlGraphQL)
673
+ teardown(app.close.bind(app))
674
+
675
+ const categories = [{
676
+ name: 'Pets'
677
+ }, {
678
+ name: 'Food'
679
+ }]
680
+
681
+ await app.inject({
682
+ method: 'POST',
683
+ url: '/graphql',
684
+ body: {
685
+ query: `
686
+ mutation batch($inputs: [CategoryInput]!) {
687
+ insertCategories(inputs: $inputs) {
688
+ id
689
+ name
690
+ }
691
+ }
692
+ `,
693
+ variables: {
694
+ inputs: categories
695
+ }
696
+ }
697
+ })
698
+
699
+ {
700
+ const res = await app.inject({
701
+ method: 'POST',
702
+ url: '/graphql',
703
+ body: {
704
+ query: `
705
+ mutation {
706
+ savePage(input: { title: "Hello", categoryId: 1 }) {
707
+ id
708
+ title
709
+ category {
710
+ id
711
+ name
712
+ }
713
+ }
714
+ }
715
+ `
716
+ }
717
+ })
718
+ equal(res.statusCode, 200, 'savePage status code')
719
+ same(res.json(), {
720
+ data: {
721
+ savePage: {
722
+ id: 1,
723
+ title: 'Hello',
724
+ category: {
725
+ id: 1,
726
+ name: 'Pets'
727
+ }
728
+ }
729
+ }
730
+ }, 'savePage response')
731
+ }
732
+
733
+ {
734
+ const res = await app.inject({
735
+ method: 'POST',
736
+ url: '/graphql',
737
+ body: {
738
+ query: `
739
+ query {
740
+ getPageById(id: 1) {
741
+ id
742
+ title
743
+ category {
744
+ id
745
+ name
746
+ pages {
747
+ id
748
+ title
749
+ category {
750
+ id
751
+ name
752
+ }
753
+ }
754
+ }
755
+ }
756
+ }
757
+ `
758
+ }
759
+ })
760
+ equal(res.statusCode, 200, 'pages status code')
761
+ same(res.json(), {
762
+ data: {
763
+ getPageById: {
764
+ id: 1,
765
+ title: 'Hello',
766
+ category: {
767
+ id: 1,
768
+ name: 'Pets',
769
+ pages: [{
770
+ id: 1,
771
+ title: 'Hello',
772
+ category: {
773
+ id: 1,
774
+ name: 'Pets'
775
+ }
776
+ }]
777
+ }
778
+ }
779
+ }
780
+ }, 'pages response')
781
+ }
782
+
783
+ {
784
+ const res = await app.inject({
785
+ method: 'POST',
786
+ url: '/graphql',
787
+ body: {
788
+ query: `
789
+ query {
790
+ categories {
791
+ id
792
+ name
793
+ pages {
794
+ id
795
+ title
796
+ category {
797
+ id
798
+ name
799
+ }
800
+ }
801
+ }
802
+ }
803
+ `
804
+ }
805
+ })
806
+ equal(res.statusCode, 200, 'categories.posts status code')
807
+ same(res.json(), {
808
+ data: {
809
+ categories: [{
810
+ id: 1,
811
+ name: 'Pets',
812
+ pages: [{
813
+ id: 1,
814
+ title: 'Hello',
815
+ category: {
816
+ id: 1,
817
+ name: 'Pets'
818
+ }
819
+ }]
820
+ }, {
821
+ id: 2,
822
+ name: 'Food',
823
+ pages: []
824
+ }]
825
+ }
826
+ }, 'categories.posts response')
827
+ }
828
+
829
+ {
830
+ const res = await app.inject({
831
+ method: 'POST',
832
+ url: '/graphql',
833
+ body: {
834
+ query: `
835
+ mutation {
836
+ savePage(input: { title: "Updated", id: 1 }) {
837
+ id
838
+ title
839
+ category {
840
+ id
841
+ name
842
+ }
843
+ }
844
+ }
845
+ `
846
+ }
847
+ })
848
+ equal(res.statusCode, 200, 'savePage status code')
849
+ same(res.json(), {
850
+ data: {
851
+ savePage: {
852
+ id: 1,
853
+ title: 'Updated',
854
+ category: {
855
+ id: 1,
856
+ name: 'Pets'
857
+ }
858
+ }
859
+ }
860
+ }, 'savePage response')
861
+ }
862
+ })