simple-jsonapi-deserializer 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,806 @@
1
+ require 'spec_helper'
2
+
3
+ describe SimpleJSONAPIDeserializer::Deserializer do
4
+ describe '.deserialize' do
5
+ subject { SimpleJSONAPIDeserializer::Deserializer.new(json_hash).deserialize }
6
+
7
+ context 'with an invalid parameter' do
8
+ let(:json_hash) { nil }
9
+
10
+ it 'raises a custom error' do
11
+ expect { subject }.to raise_error(SimpleJSONAPIDeserializer::ParseError)
12
+ end
13
+ end
14
+
15
+ context 'with an invalid resource' do
16
+ let(:json_hash) do
17
+ {
18
+ 'data' => {
19
+ 'relationships' => {
20
+ 'test' => {}
21
+ }
22
+ },
23
+ 'include' => 5
24
+ }
25
+ end
26
+
27
+ it 'raises a custom error' do
28
+ expect { subject }.to raise_error(SimpleJSONAPIDeserializer::ParseError)
29
+ end
30
+ end
31
+
32
+ context 'with a resource' do
33
+ let(:json_hash) do
34
+ {
35
+ 'data' => {
36
+ 'id' => '123',
37
+ 'type' => 'mice'
38
+ }
39
+ }
40
+ end
41
+ let(:expected_result) do
42
+ {
43
+ 'id' => '123',
44
+ 'type' => 'mice'
45
+ }
46
+ end
47
+
48
+ it { is_expected.to eq(expected_result) }
49
+ end
50
+
51
+ context 'with a resource with attributes' do
52
+ let(:json_hash) do
53
+ {
54
+ 'data' => {
55
+ 'id' => '123',
56
+ 'type' => 'mice',
57
+ 'attributes' => {
58
+ 'color' => 'white',
59
+ 'name' => 'Vinnie'
60
+ }
61
+ }
62
+ }
63
+ end
64
+ let(:expected_result) do
65
+ {
66
+ 'id' => '123',
67
+ 'type' => 'mice',
68
+ 'color' => 'white',
69
+ 'name' => 'Vinnie'
70
+ }
71
+ end
72
+
73
+ it { is_expected.to eq(expected_result) }
74
+ end
75
+
76
+ context 'with a resource with unknown keys' do
77
+ let(:json_hash) do
78
+ {
79
+ 'data' => {
80
+ 'id' => '123',
81
+ 'type' => 'mice',
82
+ 'attributes' => {
83
+ 'name' => 'Vinnie'
84
+ },
85
+ 'unknown_key' => 'unknown'
86
+ }
87
+ }
88
+ end
89
+ let(:expected_result) do
90
+ {
91
+ 'id' => '123',
92
+ 'type' => 'mice',
93
+ 'name' => 'Vinnie'
94
+ }
95
+ end
96
+
97
+ it { is_expected.to eq(expected_result) }
98
+ end
99
+
100
+ # An array is not allowed as a root level resource, but it can be used to
101
+ # update relationships. In this case attributes will be ignored.
102
+ # http://jsonapi.org/format/#crud-updating-relationships
103
+ context 'with an array of resources' do
104
+ let(:json_hash) do
105
+ {
106
+ 'data' => [
107
+ {
108
+ 'id' => '123',
109
+ 'type' => 'mice',
110
+ 'attributes' => {
111
+ 'name' => 'Vinnie'
112
+ }
113
+ },
114
+ {
115
+ 'id' => '124',
116
+ 'type' => 'mice',
117
+ 'attributes' => {
118
+ 'name' => 'Rico'
119
+ }
120
+ }
121
+ ]
122
+ }
123
+ end
124
+ let(:expected_result) do
125
+ [
126
+ {
127
+ 'id' => '123',
128
+ 'type' => 'mice'
129
+ },
130
+ {
131
+ 'id' => '124',
132
+ 'type' => 'mice'
133
+ }
134
+ ]
135
+ end
136
+
137
+ it { is_expected.to eq(expected_result) }
138
+ end
139
+
140
+ describe 'relationships' do
141
+ context 'with a single relationship' do
142
+ let(:json_hash) do
143
+ {
144
+ 'data' => {
145
+ 'id' => '123',
146
+ 'type' => 'mice',
147
+ 'attributes' => {
148
+ 'name' => 'Vinnie'
149
+ },
150
+ 'relationships' => {
151
+ 'bike' => {
152
+ 'data' => {
153
+ 'id' => '5',
154
+ 'type' => 'bikes'
155
+ }
156
+ }
157
+ }
158
+ }
159
+ }
160
+ end
161
+ let(:expected_result) do
162
+ {
163
+ 'id' => '123',
164
+ 'type' => 'mice',
165
+ 'name' => 'Vinnie',
166
+ 'bike' => {
167
+ 'id' => '5',
168
+ 'type' => 'bikes'
169
+ }
170
+ }
171
+ end
172
+
173
+ it { is_expected.to eq(expected_result) }
174
+ end
175
+
176
+ context 'with multiple relationships' do
177
+ let(:json_hash) do
178
+ {
179
+ 'data' => {
180
+ 'id' => '123',
181
+ 'type' => 'mice',
182
+ 'attributes' => {
183
+ 'name' => 'Vinnie'
184
+ },
185
+ 'relationships' => {
186
+ 'bike' => {
187
+ 'data' => {
188
+ 'id' => '5',
189
+ 'type' => 'bikes'
190
+ }
191
+ },
192
+ 'villain' => {
193
+ 'data' => {
194
+ 'id' => '9',
195
+ 'type' => 'villains'
196
+ }
197
+ }
198
+ }
199
+ }
200
+ }
201
+ end
202
+ let(:expected_result) do
203
+ {
204
+ 'id' => '123',
205
+ 'type' => 'mice',
206
+ 'name' => 'Vinnie',
207
+ 'bike' => {
208
+ 'id' => '5',
209
+ 'type' => 'bikes'
210
+ },
211
+ 'villain' => {
212
+ 'id' => '9',
213
+ 'type' => 'villains'
214
+ }
215
+ }
216
+ end
217
+
218
+ it { is_expected.to eq(expected_result) }
219
+ end
220
+
221
+ context 'with to_many relationships' do
222
+ let(:json_hash) do
223
+ {
224
+ 'data' => {
225
+ 'id' => '123',
226
+ 'type' => 'mice',
227
+ 'attributes' => {
228
+ 'name' => 'Vinnie'
229
+ },
230
+ 'relationships' => {
231
+ 'bike' => {
232
+ 'data' => {
233
+ 'id' => '5',
234
+ 'type' => 'bikes'
235
+ }
236
+ },
237
+ 'villains' => {
238
+ 'data' => [
239
+ {
240
+ 'id' => '9',
241
+ 'type' => 'villains'
242
+ },
243
+ {
244
+ 'id' => '15',
245
+ 'type' => 'villains'
246
+ }
247
+ ]
248
+ }
249
+ }
250
+ }
251
+ }
252
+ end
253
+ let(:expected_result) do
254
+ {
255
+ 'id' => '123',
256
+ 'type' => 'mice',
257
+ 'name' => 'Vinnie',
258
+ 'bike' => {
259
+ 'id' => '5',
260
+ 'type' => 'bikes'
261
+ },
262
+ 'villains' => [
263
+ {
264
+ 'id' => '9',
265
+ 'type' => 'villains'
266
+ },
267
+ {
268
+ 'id' => '15',
269
+ 'type' => 'villains'
270
+ }
271
+ ]
272
+ }
273
+ end
274
+
275
+ it { is_expected.to eq(expected_result) }
276
+ end
277
+ end
278
+
279
+ describe 'relationships with includes' do
280
+ context 'with a single relationship' do
281
+ let(:json_hash) do
282
+ {
283
+ 'data' => {
284
+ 'id' => '123',
285
+ 'type' => 'mice',
286
+ 'attributes' => {
287
+ 'name' => 'Vinnie'
288
+ },
289
+ 'relationships' => {
290
+ 'bike' => {
291
+ 'data' => {
292
+ 'id' => '5',
293
+ 'type' => 'bikes'
294
+ }
295
+ }
296
+ }
297
+ },
298
+ 'include' => [
299
+ {
300
+ 'id' => '5',
301
+ 'type' => 'bikes',
302
+ 'attributes' => {
303
+ 'color' => 'red'
304
+ }
305
+ }
306
+ ]
307
+ }
308
+ end
309
+ let(:expected_result) do
310
+ {
311
+ 'id' => '123',
312
+ 'type' => 'mice',
313
+ 'name' => 'Vinnie',
314
+ 'bike' => {
315
+ 'id' => '5',
316
+ 'type' => 'bikes',
317
+ 'color' => 'red'
318
+ }
319
+ }
320
+ end
321
+
322
+ it { is_expected.to eq(expected_result) }
323
+ end
324
+
325
+ context 'with multiple relationships' do
326
+ let(:json_hash) do
327
+ {
328
+ 'data' => {
329
+ 'id' => '123',
330
+ 'type' => 'mice',
331
+ 'attributes' => {
332
+ 'name' => 'Vinnie'
333
+ },
334
+ 'relationships' => {
335
+ 'bike' => {
336
+ 'data' => {
337
+ 'id' => '5',
338
+ 'type' => 'bikes'
339
+ }
340
+ },
341
+ 'villain' => {
342
+ 'data' => {
343
+ 'id' => '9',
344
+ 'type' => 'villains'
345
+ }
346
+ }
347
+ }
348
+ },
349
+ 'include' => [
350
+ {
351
+ 'id' => '5',
352
+ 'type' => 'bikes',
353
+ 'attributes' => {
354
+ 'color' => 'red'
355
+ }
356
+ },
357
+ {
358
+ 'id' => '9',
359
+ 'type' => 'villains',
360
+ 'attributes' => {
361
+ 'first_name' => 'Lawrence',
362
+ 'last_name' => 'Limburger'
363
+ }
364
+ }
365
+ ]
366
+ }
367
+ end
368
+ let(:expected_result) do
369
+ {
370
+ 'id' => '123',
371
+ 'type' => 'mice',
372
+ 'name' => 'Vinnie',
373
+ 'bike' => {
374
+ 'id' => '5',
375
+ 'type' => 'bikes',
376
+ 'color' => 'red'
377
+ },
378
+ 'villain' => {
379
+ 'id' => '9',
380
+ 'type' => 'villains',
381
+ 'first_name' => 'Lawrence',
382
+ 'last_name' => 'Limburger'
383
+ }
384
+ }
385
+ end
386
+
387
+ it { is_expected.to eq(expected_result) }
388
+ end
389
+
390
+ context 'with to_many relationships' do
391
+ let(:json_hash) do
392
+ {
393
+ 'data' => {
394
+ 'id' => '123',
395
+ 'type' => 'mice',
396
+ 'attributes' => {
397
+ 'name' => 'Vinnie'
398
+ },
399
+ 'relationships' => {
400
+ 'bike' => {
401
+ 'data' => {
402
+ 'id' => '5',
403
+ 'type' => 'bikes'
404
+ }
405
+ },
406
+ 'villains' => {
407
+ 'data' => [
408
+ {
409
+ 'id' => '9',
410
+ 'type' => 'villains'
411
+ },
412
+ {
413
+ 'id' => '15',
414
+ 'type' => 'villains'
415
+ }
416
+ ]
417
+ }
418
+ }
419
+ },
420
+ 'include' => [
421
+ {
422
+ 'id' => '5',
423
+ 'type' => 'bikes',
424
+ 'attributes' => {
425
+ 'color' => 'red'
426
+ }
427
+ },
428
+ {
429
+ 'id' => '9',
430
+ 'type' => 'villains',
431
+ 'attributes' => {
432
+ 'first_name' => 'Lawrence',
433
+ 'last_name' => 'Limburger'
434
+ }
435
+ },
436
+ {
437
+ 'id' => '15',
438
+ 'type' => 'villains',
439
+ 'attributes' => {
440
+ 'first_name' => 'Grease',
441
+ 'last_name' => 'Pit'
442
+ }
443
+ }
444
+ ]
445
+ }
446
+ end
447
+ let(:expected_result) do
448
+ {
449
+ 'id' => '123',
450
+ 'type' => 'mice',
451
+ 'name' => 'Vinnie',
452
+ 'bike' => {
453
+ 'id' => '5',
454
+ 'type' => 'bikes',
455
+ 'color' => 'red'
456
+ },
457
+ 'villains' => [
458
+ {
459
+ 'id' => '9',
460
+ 'type' => 'villains',
461
+ 'first_name' => 'Lawrence',
462
+ 'last_name' => 'Limburger'
463
+ },
464
+ {
465
+ 'id' => '15',
466
+ 'type' => 'villains',
467
+ 'first_name' => 'Grease',
468
+ 'last_name' => 'Pit'
469
+ }
470
+ ]
471
+ }
472
+ end
473
+
474
+ it { is_expected.to eq(expected_result) }
475
+ end
476
+
477
+ context 'with nested relationships' do
478
+ let(:json_hash) do
479
+ {
480
+ 'data' => {
481
+ 'id' => '123',
482
+ 'type' => 'mice',
483
+ 'attributes' => {
484
+ 'name' => 'Vinnie'
485
+ },
486
+ 'relationships' => {
487
+ 'bike' => {
488
+ 'data' => {
489
+ 'id' => '5',
490
+ 'type' => 'bikes'
491
+ }
492
+ },
493
+ 'villains' => {
494
+ 'data' => [
495
+ {
496
+ 'id' => '9',
497
+ 'type' => 'villains'
498
+ },
499
+ {
500
+ 'id' => '15',
501
+ 'type' => 'villains'
502
+ }
503
+ ]
504
+ }
505
+ }
506
+ },
507
+ 'include' => [
508
+ {
509
+ 'id' => '5',
510
+ 'type' => 'bikes',
511
+ 'attributes' => {
512
+ 'color' => 'red'
513
+ }
514
+ },
515
+ {
516
+ 'id' => '9',
517
+ 'type' => 'villains',
518
+ 'attributes' => {
519
+ 'first_name' => 'Lawrence',
520
+ 'last_name' => 'Limburger'
521
+ },
522
+ 'relationships' => {
523
+ 'assistants' => {
524
+ 'data' => [
525
+ {
526
+ 'id' => '24',
527
+ 'type' => 'villains'
528
+ },
529
+ {
530
+ 'id' => '15',
531
+ 'type' => 'villains'
532
+ }
533
+ ]
534
+ }
535
+ }
536
+ },
537
+ {
538
+ 'id' => '15',
539
+ 'type' => 'villains',
540
+ 'attributes' => {
541
+ 'first_name' => 'Grease',
542
+ 'last_name' => 'Pit'
543
+ }
544
+ },
545
+ {
546
+ 'id' => '24',
547
+ 'type' => 'villains',
548
+ 'attributes' => {
549
+ 'first_name' => 'Benjamin',
550
+ 'last_name' => 'Karbunkle'
551
+ }
552
+ }
553
+ ]
554
+ }
555
+ end
556
+ let(:expected_result) do
557
+ {
558
+ 'id' => '123',
559
+ 'type' => 'mice',
560
+ 'name' => 'Vinnie',
561
+ 'bike' => {
562
+ 'id' => '5',
563
+ 'type' => 'bikes',
564
+ 'color' => 'red'
565
+ },
566
+ 'villains' => [
567
+ {
568
+ 'id' => '9',
569
+ 'type' => 'villains',
570
+ 'first_name' => 'Lawrence',
571
+ 'last_name' => 'Limburger',
572
+ 'assistants' => [
573
+ {
574
+ 'id' => '24',
575
+ 'type' => 'villains',
576
+ 'first_name' => 'Benjamin',
577
+ 'last_name' => 'Karbunkle'
578
+ },
579
+ {
580
+ 'id' => '15',
581
+ 'type' => 'villains',
582
+ 'first_name' => 'Grease',
583
+ 'last_name' => 'Pit'
584
+ }
585
+ ]
586
+ },
587
+ {
588
+ 'id' => '15',
589
+ 'type' => 'villains',
590
+ 'first_name' => 'Grease',
591
+ 'last_name' => 'Pit'
592
+ }
593
+ ]
594
+ }
595
+ end
596
+
597
+ it { is_expected.to eq(expected_result) }
598
+ end
599
+ end
600
+
601
+ context 'with cyclic relationships' do
602
+ let(:json_hash) do
603
+ {
604
+ 'data' => {
605
+ 'id' => '123',
606
+ 'type' => 'mice',
607
+ 'attributes' => {
608
+ 'name' => 'Vinnie'
609
+ },
610
+ 'relationships' => {
611
+ 'bike' => {
612
+ 'data' => {
613
+ 'id' => '5',
614
+ 'type' => 'bikes'
615
+ }
616
+ },
617
+ 'villains' => {
618
+ 'data' => [
619
+ {
620
+ 'id' => '9',
621
+ 'type' => 'villains'
622
+ },
623
+ {
624
+ 'id' => '15',
625
+ 'type' => 'villains'
626
+ }
627
+ ]
628
+ },
629
+ 'episodes' => {
630
+ 'data' => [
631
+ {
632
+ 'id' => '1',
633
+ 'type' => 'episodes'
634
+ }
635
+ ]
636
+ }
637
+ }
638
+ },
639
+ 'include' => [
640
+ {
641
+ 'id' => '5',
642
+ 'type' => 'bikes',
643
+ 'attributes' => {
644
+ 'color' => 'red'
645
+ }
646
+ },
647
+ {
648
+ 'id' => '9',
649
+ 'type' => 'villains',
650
+ 'attributes' => {
651
+ 'first_name' => 'Lawrence',
652
+ 'last_name' => 'Limburger'
653
+ },
654
+ 'relationships' => {
655
+ 'assistants' => {
656
+ 'data' => [
657
+ {
658
+ 'id' => '24',
659
+ 'type' => 'villains'
660
+ },
661
+ {
662
+ 'id' => '15',
663
+ 'type' => 'villains'
664
+ }
665
+ ]
666
+ }
667
+ }
668
+ },
669
+ {
670
+ 'id' => '15',
671
+ 'type' => 'villains',
672
+ 'attributes' => {
673
+ 'first_name' => 'Grease',
674
+ 'last_name' => 'Pit'
675
+ }
676
+ },
677
+ {
678
+ 'id' => '24',
679
+ 'type' => 'villains',
680
+ 'attributes' => {
681
+ 'first_name' => 'Benjamin',
682
+ 'last_name' => 'Karbunkle'
683
+ },
684
+ 'relationships' => {
685
+ 'boss' => {
686
+ 'data' => {
687
+ 'id' => '9',
688
+ 'type' => 'villains'
689
+ }
690
+ }
691
+ }
692
+ },
693
+ {
694
+ 'id' => '1',
695
+ 'type' => 'episodes',
696
+ 'attributes' => {
697
+ 'name' => 'Rock and Ride!'
698
+ },
699
+ 'relationships' => {
700
+ 'characters' => {
701
+ 'data' => [
702
+ {
703
+ 'id' => '123',
704
+ 'type' => 'mice'
705
+ },
706
+ {
707
+ 'id' => '9',
708
+ 'type' => 'villains'
709
+ }
710
+ ]
711
+ }
712
+ }
713
+ }
714
+ ]
715
+ }
716
+ end
717
+ let(:expected_result) do
718
+ {
719
+ 'id' => '123',
720
+ 'type' => 'mice',
721
+ 'name' => 'Vinnie',
722
+ 'bike' => {
723
+ 'id' => '5',
724
+ 'type' => 'bikes',
725
+ 'color' => 'red'
726
+ },
727
+ 'villains' => [
728
+ {
729
+ 'id' => '9',
730
+ 'type' => 'villains',
731
+ 'first_name' => 'Lawrence',
732
+ 'last_name' => 'Limburger',
733
+ 'assistants' => [
734
+ {
735
+ 'id' => '24',
736
+ 'type' => 'villains',
737
+ 'first_name' => 'Benjamin',
738
+ 'last_name' => 'Karbunkle',
739
+ 'boss' => {
740
+ 'id' => '9',
741
+ 'type' => 'villains',
742
+ 'first_name' => 'Lawrence',
743
+ 'last_name' => 'Limburger'
744
+ }
745
+ },
746
+ {
747
+ 'id' => '15',
748
+ 'type' => 'villains',
749
+ 'first_name' => 'Grease',
750
+ 'last_name' => 'Pit'
751
+ }
752
+ ]
753
+ },
754
+ {
755
+ 'id' => '15',
756
+ 'type' => 'villains',
757
+ 'first_name' => 'Grease',
758
+ 'last_name' => 'Pit'
759
+ }
760
+ ],
761
+ 'episodes' => [
762
+ {
763
+ 'id' => '1',
764
+ 'name' => 'Rock and Ride!',
765
+ 'type' => 'episodes',
766
+ 'characters' => [
767
+ {
768
+ 'id' => '123',
769
+ 'type' => 'mice'
770
+ },
771
+ {
772
+ 'id' => '9',
773
+ 'type' => 'villains',
774
+ 'first_name' => 'Lawrence',
775
+ 'last_name' => 'Limburger',
776
+ 'assistants' => [
777
+ {
778
+ 'id' => '24',
779
+ 'type' => 'villains',
780
+ 'first_name' => 'Benjamin',
781
+ 'last_name' => 'Karbunkle',
782
+ 'boss' => {
783
+ 'id' => '9',
784
+ 'type' => 'villains',
785
+ 'first_name' => 'Lawrence',
786
+ 'last_name' => 'Limburger'
787
+ }
788
+ },
789
+ {
790
+ 'id' => '15',
791
+ 'type' => 'villains',
792
+ 'first_name' => 'Grease',
793
+ 'last_name' => 'Pit'
794
+ }
795
+ ]
796
+ }
797
+ ]
798
+ }
799
+ ]
800
+ }
801
+ end
802
+
803
+ it { is_expected.to eq(expected_result) }
804
+ end
805
+ end
806
+ end