jsonapi-serializers 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,630 @@
1
+ describe JSONAPI::Serializer do
2
+ def serialize_primary(object, options = {})
3
+ # Note: intentional high-coupling to protected method for tests.
4
+ JSONAPI::Serializer.send(:serialize_primary, object, options)
5
+ end
6
+
7
+ describe 'internal-only serialize_primary' do
8
+ it 'serializes nil to nil' do
9
+ # Spec: Primary data MUST be either:
10
+ # - a single resource object or null, for requests that target single resources
11
+ # http://jsonapi.org/format/#document-structure-top-level
12
+ primary_data = serialize_primary(nil, {serializer: MyApp::PostSerializer})
13
+ expect(primary_data).to be_nil
14
+ end
15
+ it 'can serialize primary data for a simple object' do
16
+ post = create(:post)
17
+ primary_data = serialize_primary(post, {serializer: MyApp::SimplestPostSerializer})
18
+ expect(primary_data).to eq({
19
+ 'id' => '1',
20
+ 'type' => 'posts',
21
+ 'attributes' => {
22
+ 'title' => 'Title for Post 1',
23
+ 'long-content' => 'Body for Post 1',
24
+ },
25
+ 'links' => {
26
+ 'self' => '/posts/1',
27
+ },
28
+ })
29
+ end
30
+ it 'can serialize primary data for a simple object with a long name' do
31
+ long_comment = create(:long_comment, post: create(:post))
32
+ primary_data = serialize_primary(long_comment, {serializer: MyApp::LongCommentSerializer})
33
+ expect(primary_data).to eq({
34
+ 'id' => '1',
35
+ 'type' => 'long-comments',
36
+ 'attributes' => {
37
+ 'body' => 'Body for LongComment 1',
38
+ },
39
+ 'links' => {
40
+ 'self' => '/long-comments/1',
41
+ 'user' => {
42
+ 'self' => '/long-comments/1/links/user',
43
+ 'related' => '/long-comments/1/user',
44
+ },
45
+ 'post' => {
46
+ 'self' => '/long-comments/1/links/post',
47
+ 'related' => '/long-comments/1/post',
48
+ },
49
+ },
50
+ })
51
+ end
52
+ it 'can serialize primary data for a simple object with resource-level metadata' do
53
+ post = create(:post)
54
+ primary_data = serialize_primary(post, {serializer: MyApp::PostSerializerWithMetadata})
55
+ expect(primary_data).to eq({
56
+ 'id' => '1',
57
+ 'type' => 'posts',
58
+ 'attributes' => {
59
+ 'title' => 'Title for Post 1',
60
+ 'long-content' => 'Body for Post 1',
61
+ },
62
+ 'links' => {
63
+ 'self' => '/posts/1',
64
+ },
65
+ 'meta' => {
66
+ 'copyright' => 'Copyright 2015 Example Corp.',
67
+ 'authors' => [
68
+ 'Aliens',
69
+ ],
70
+ },
71
+ })
72
+ end
73
+ context 'without any linkage includes (default)' do
74
+ it 'can serialize primary data for an object with to-one and to-many relationships' do
75
+ post = create(:post)
76
+ primary_data = serialize_primary(post, {serializer: MyApp::PostSerializer})
77
+ expect(primary_data).to eq({
78
+ 'id' => '1',
79
+ 'type' => 'posts',
80
+ 'attributes' => {
81
+ 'title' => 'Title for Post 1',
82
+ 'long-content' => 'Body for Post 1',
83
+ },
84
+ 'links' => {
85
+ 'self' => '/posts/1',
86
+ # Both to-one and to-many links are present, but neither include linkage:
87
+ 'author' => {
88
+ 'self' => '/posts/1/links/author',
89
+ 'related' => '/posts/1/author',
90
+ },
91
+ 'long-comments' => {
92
+ 'self' => '/posts/1/links/long-comments',
93
+ 'related' => '/posts/1/long-comments',
94
+ },
95
+ },
96
+ })
97
+ end
98
+ end
99
+ context 'with linkage includes' do
100
+ it 'can serialize primary data for a null to-one relationship' do
101
+ post = create(:post, author: nil)
102
+ options = {
103
+ serializer: MyApp::PostSerializer,
104
+ include_linkages: ['author', 'long-comments'],
105
+ }
106
+ primary_data = serialize_primary(post, options)
107
+ expect(primary_data).to eq({
108
+ 'id' => '1',
109
+ 'type' => 'posts',
110
+ 'attributes' => {
111
+ 'title' => 'Title for Post 1',
112
+ 'long-content' => 'Body for Post 1',
113
+ },
114
+ 'links' => {
115
+ 'self' => '/posts/1',
116
+ 'author' => {
117
+ 'self' => '/posts/1/links/author',
118
+ 'related' => '/posts/1/author',
119
+ # Spec: Resource linkage MUST be represented as one of the following:
120
+ # - null for empty to-one relationships.
121
+ # http://jsonapi.org/format/#document-structure-resource-relationships
122
+ 'linkage' => nil,
123
+ },
124
+ 'long-comments' => {
125
+ 'self' => '/posts/1/links/long-comments',
126
+ 'related' => '/posts/1/long-comments',
127
+ 'linkage' => [],
128
+ },
129
+ },
130
+ })
131
+ end
132
+ it 'can serialize primary data for a simple to-one relationship' do
133
+ post = create(:post, :with_author)
134
+ options = {
135
+ serializer: MyApp::PostSerializer,
136
+ include_linkages: ['author', 'long-comments'],
137
+ }
138
+ primary_data = serialize_primary(post, options)
139
+ expect(primary_data).to eq({
140
+ 'id' => '1',
141
+ 'type' => 'posts',
142
+ 'attributes' => {
143
+ 'title' => 'Title for Post 1',
144
+ 'long-content' => 'Body for Post 1',
145
+ },
146
+ 'links' => {
147
+ 'self' => '/posts/1',
148
+ 'author' => {
149
+ 'self' => '/posts/1/links/author',
150
+ 'related' => '/posts/1/author',
151
+ # Spec: Resource linkage MUST be represented as one of the following:
152
+ # - a 'linkage object' (defined below) for non-empty to-one relationships.
153
+ # http://jsonapi.org/format/#document-structure-resource-relationships
154
+ 'linkage' => {
155
+ 'type' => 'users',
156
+ 'id' => '1',
157
+ },
158
+ },
159
+ 'long-comments' => {
160
+ 'self' => '/posts/1/links/long-comments',
161
+ 'related' => '/posts/1/long-comments',
162
+ 'linkage' => [],
163
+ },
164
+ },
165
+ })
166
+ end
167
+ it 'can serialize primary data for an empty to-many relationship' do
168
+ post = create(:post, long_comments: [])
169
+ options = {
170
+ serializer: MyApp::PostSerializer,
171
+ include_linkages: ['author', 'long-comments'],
172
+ }
173
+ primary_data = serialize_primary(post, options)
174
+ expect(primary_data).to eq({
175
+ 'id' => '1',
176
+ 'type' => 'posts',
177
+ 'attributes' => {
178
+ 'title' => 'Title for Post 1',
179
+ 'long-content' => 'Body for Post 1',
180
+ },
181
+ 'links' => {
182
+ 'self' => '/posts/1',
183
+ 'author' => {
184
+ 'self' => '/posts/1/links/author',
185
+ 'related' => '/posts/1/author',
186
+ 'linkage' => nil,
187
+ },
188
+ 'long-comments' => {
189
+ 'self' => '/posts/1/links/long-comments',
190
+ 'related' => '/posts/1/long-comments',
191
+ # Spec: Resource linkage MUST be represented as one of the following:
192
+ # - an empty array ([]) for empty to-many relationships.
193
+ # http://jsonapi.org/format/#document-structure-resource-relationships
194
+ 'linkage' => [],
195
+ },
196
+ },
197
+ })
198
+ end
199
+ it 'can serialize primary data for a simple to-many relationship' do
200
+ long_comments = create_list(:long_comment, 2)
201
+ post = create(:post, long_comments: long_comments)
202
+ options = {
203
+ serializer: MyApp::PostSerializer,
204
+ include_linkages: ['author', 'long-comments'],
205
+ }
206
+ primary_data = serialize_primary(post, options)
207
+ expect(primary_data).to eq({
208
+ 'id' => '1',
209
+ 'type' => 'posts',
210
+ 'attributes' => {
211
+ 'title' => 'Title for Post 1',
212
+ 'long-content' => 'Body for Post 1',
213
+ },
214
+ 'links' => {
215
+ 'self' => '/posts/1',
216
+ 'author' => {
217
+ 'self' => '/posts/1/links/author',
218
+ 'related' => '/posts/1/author',
219
+ 'linkage' => nil,
220
+ },
221
+ 'long-comments' => {
222
+ 'self' => '/posts/1/links/long-comments',
223
+ 'related' => '/posts/1/long-comments',
224
+ # Spec: Resource linkage MUST be represented as one of the following:
225
+ # - an array of linkage objects for non-empty to-many relationships.
226
+ # http://jsonapi.org/format/#document-structure-resource-relationships
227
+ 'linkage' => [
228
+ {
229
+ 'type' => 'long-comments',
230
+ 'id' => '1',
231
+ },
232
+ {
233
+ 'type' => 'long-comments',
234
+ 'id' => '2',
235
+ },
236
+ ],
237
+ },
238
+ },
239
+ })
240
+ end
241
+ end
242
+ end
243
+
244
+ describe 'JSONAPI::Serializer.serialize' do
245
+ # The following tests rely on the fact that serialize_primary has been tested above, so object
246
+ # primary data is not explicitly tested here. If things are broken, look above here first.
247
+
248
+ it 'can serialize a nil object' do
249
+ expect(JSONAPI::Serializer.serialize(nil)).to eq({'data' => nil})
250
+ end
251
+ it 'can serialize a nil object with includes' do
252
+ # Also, the include argument is not validated in this case because we don't know the type.
253
+ data = JSONAPI::Serializer.serialize(nil, include: ['fake'])
254
+ expect(data).to eq({'data' => nil, 'included' => []})
255
+ end
256
+ it 'can serialize an empty array' do
257
+ # Also, the include argument is not validated in this case because we don't know the type.
258
+ data = JSONAPI::Serializer.serialize([], is_collection: true, include: ['fake'])
259
+ expect(data).to eq({'data' => [], 'included' => []})
260
+ end
261
+ it 'can serialize a simple object' do
262
+ post = create(:post)
263
+ expect(JSONAPI::Serializer.serialize(post)).to eq({
264
+ 'data' => serialize_primary(post, {serializer: MyApp::PostSerializer}),
265
+ })
266
+ end
267
+ it 'can serialize a collection' do
268
+ posts = create_list(:post, 2)
269
+ expect(JSONAPI::Serializer.serialize(posts, is_collection: true)).to eq({
270
+ 'data' => [
271
+ serialize_primary(posts.first, {serializer: MyApp::PostSerializer}),
272
+ serialize_primary(posts.last, {serializer: MyApp::PostSerializer}),
273
+ ],
274
+ })
275
+ end
276
+ it 'raises AmbiguousCollectionError if is_collection is not passed' do
277
+ posts = create_list(:post, 2)
278
+ error = JSONAPI::Serializer::AmbiguousCollectionError
279
+ expect { JSONAPI::Serializer.serialize(posts) }.to raise_error(error)
280
+ end
281
+ it 'can serialize a nil object when given serializer' do
282
+ options = {serializer: MyApp::PostSerializer}
283
+ expect(JSONAPI::Serializer.serialize(nil, options)).to eq({'data' => nil})
284
+ end
285
+ it 'can serialize an empty array when given serializer' do
286
+ options = {is_collection: true, serializer: MyApp::PostSerializer}
287
+ expect(JSONAPI::Serializer.serialize([], options)).to eq({'data' => []})
288
+ end
289
+ it 'can serialize a simple object when given serializer' do
290
+ post = create(:post)
291
+ options = {serializer: MyApp::SimplestPostSerializer}
292
+ expect(JSONAPI::Serializer.serialize(post, options)).to eq({
293
+ 'data' => serialize_primary(post, {serializer: MyApp::SimplestPostSerializer}),
294
+ })
295
+ end
296
+ it 'handles include of nil to-one relationship with compound document' do
297
+ post = create(:post)
298
+
299
+ expected_primary_data = serialize_primary(post, {
300
+ serializer: MyApp::PostSerializer,
301
+ include_linkages: ['author'],
302
+ })
303
+ expect(JSONAPI::Serializer.serialize(post, include: ['author'])).to eq({
304
+ 'data' => expected_primary_data,
305
+ 'included' => [],
306
+ })
307
+ end
308
+ it 'handles include of simple to-one relationship with compound document' do
309
+ post = create(:post, :with_author)
310
+
311
+ expected_primary_data = serialize_primary(post, {
312
+ serializer: MyApp::PostSerializer,
313
+ include_linkages: ['author'],
314
+ })
315
+ expect(JSONAPI::Serializer.serialize(post, include: ['author'])).to eq({
316
+ 'data' => expected_primary_data,
317
+ 'included' => [
318
+ serialize_primary(post.author, {serializer: MyApp::UserSerializer}),
319
+ ],
320
+ })
321
+ end
322
+ it 'handles include of empty to-many relationships with compound document' do
323
+ post = create(:post, :with_author, long_comments: [])
324
+
325
+ expected_primary_data = serialize_primary(post, {
326
+ serializer: MyApp::PostSerializer,
327
+ include_linkages: ['long-comments'],
328
+ })
329
+ expect(JSONAPI::Serializer.serialize(post, include: ['long-comments'])).to eq({
330
+ 'data' => expected_primary_data,
331
+ 'included' => [],
332
+ })
333
+ end
334
+ it 'handles include of to-many relationships with compound document' do
335
+ long_comments = create_list(:long_comment, 2)
336
+ post = create(:post, :with_author, long_comments: long_comments)
337
+
338
+ expected_primary_data = serialize_primary(post, {
339
+ serializer: MyApp::PostSerializer,
340
+ include_linkages: ['long-comments'],
341
+ })
342
+ expect(JSONAPI::Serializer.serialize(post, include: ['long-comments'])).to eq({
343
+ 'data' => expected_primary_data,
344
+ 'included' => [
345
+ serialize_primary(long_comments.first, {serializer: MyApp::LongCommentSerializer}),
346
+ serialize_primary(long_comments.last, {serializer: MyApp::LongCommentSerializer}),
347
+ ],
348
+ })
349
+ end
350
+ it 'only includes one copy of each referenced relationship' do
351
+ long_comment = create(:long_comment)
352
+ long_comments = [long_comment, long_comment]
353
+ post = create(:post, :with_author, long_comments: long_comments)
354
+
355
+ expected_primary_data = serialize_primary(post, {
356
+ serializer: MyApp::PostSerializer,
357
+ include_linkages: ['long-comments'],
358
+ })
359
+ expect(JSONAPI::Serializer.serialize(post, include: ['long-comments'])).to eq({
360
+ 'data' => expected_primary_data,
361
+ 'included' => [
362
+ serialize_primary(long_comment, {serializer: MyApp::LongCommentSerializer}),
363
+ ],
364
+ })
365
+ end
366
+ it 'handles circular-referencing relationships with compound document' do
367
+ long_comments = create_list(:long_comment, 2)
368
+ post = create(:post, :with_author, long_comments: long_comments)
369
+
370
+ # Make sure each long-comment has a circular reference back to the post.
371
+ long_comments.each { |c| c.post = post }
372
+
373
+ expected_primary_data = serialize_primary(post, {
374
+ serializer: MyApp::PostSerializer,
375
+ include_linkages: ['long-comments'],
376
+ })
377
+ expect(JSONAPI::Serializer.serialize(post, include: ['long-comments'])).to eq({
378
+ 'data' => expected_primary_data,
379
+ 'included' => [
380
+ serialize_primary(post.long_comments.first, {serializer: MyApp::LongCommentSerializer}),
381
+ serialize_primary(post.long_comments.last, {serializer: MyApp::LongCommentSerializer}),
382
+ ],
383
+ })
384
+ end
385
+ it 'errors if include is not a defined attribute' do
386
+ user = create(:user)
387
+ expect { JSONAPI::Serializer.serialize(user, include: ['fake-attr']) }.to raise_error
388
+ end
389
+ it 'handles recursive loading of relationships' do
390
+ user = create(:user)
391
+ long_comments = create_list(:long_comment, 2, user: user)
392
+ post = create(:post, :with_author, long_comments: long_comments)
393
+ # Make sure each long-comment has a circular reference back to the post.
394
+ long_comments.each { |c| c.post = post }
395
+
396
+ expected_data = {
397
+ # Note that in this case the primary data does not include linkage for 'long-comments',
398
+ # forcing clients to still have to request linkage from long-comments and post. This is an
399
+ # odd but valid data state because the user requested to only include the leaf author node,
400
+ # and we only automatically expose direct children linkages if they match given includes.
401
+ #
402
+ # Spec: Resource linkage in a compound document allows a client to link together
403
+ # all of the included resource objects without having to GET any relationship URLs.
404
+ # http://jsonapi.org/format/#document-structure-resource-relationships
405
+ #
406
+ # Also, spec: A request for comments.author should not automatically also include
407
+ # comments in the response. This can happen if the client already has the comments locally,
408
+ # and now wants to fetch the associated authors without fetching the comments again.
409
+ # http://jsonapi.org/format/#fetching-includes
410
+ 'data' => serialize_primary(post, {serializer: MyApp::PostSerializer}),
411
+ 'included' => [
412
+ # Only the author is included:
413
+ serialize_primary(post.author, {serializer: MyApp::UserSerializer}),
414
+ ],
415
+ }
416
+ includes = ['long-comments.post.author']
417
+ actual_data = JSONAPI::Serializer.serialize(post, include: ['long-comments.post.author'])
418
+ # Multiple expectations for better diff output for debugging.
419
+ expect(actual_data['data']).to eq(expected_data['data'])
420
+ expect(actual_data['included']).to eq(expected_data['included'])
421
+ expect(actual_data).to eq(expected_data)
422
+ end
423
+ it 'handles recursive loading of multiple to-one relationships on children' do
424
+ first_user = create(:user)
425
+ second_user = create(:user)
426
+ first_comment = create(:long_comment, user: first_user)
427
+ second_comment = create(:long_comment, user: second_user)
428
+ long_comments = [first_comment, second_comment]
429
+ post = create(:post, :with_author, long_comments: long_comments)
430
+ # Make sure each long-comment has a circular reference back to the post.
431
+ long_comments.each { |c| c.post = post }
432
+
433
+ expected_data = {
434
+ # Same note about primary data linkages as above.
435
+ 'data' => serialize_primary(post, {serializer: MyApp::PostSerializer}),
436
+ 'included' => [
437
+ serialize_primary(first_user, {serializer: MyApp::UserSerializer}),
438
+ serialize_primary(second_user, {serializer: MyApp::UserSerializer}),
439
+ ],
440
+ }
441
+ includes = ['long-comments.user']
442
+ actual_data = JSONAPI::Serializer.serialize(post, include: includes)
443
+
444
+ # Multiple expectations for better diff output for debugging.
445
+ expect(actual_data['data']).to eq(expected_data['data'])
446
+ expect(actual_data['included']).to eq(expected_data['included'])
447
+ expect(actual_data).to eq(expected_data)
448
+ end
449
+ it 'includes linkage in compounded resources only if the immediate parent was also included' do
450
+ comment_user = create(:user)
451
+ long_comments = [create(:long_comment, user: comment_user)]
452
+ post = create(:post, :with_author, long_comments: long_comments)
453
+
454
+ expected_primary_data = serialize_primary(post, {
455
+ serializer: MyApp::PostSerializer,
456
+ include_linkages: ['long-comments'],
457
+ })
458
+ expected_data = {
459
+ 'data' => expected_primary_data,
460
+ 'included' => [
461
+ serialize_primary(long_comments.first, {
462
+ serializer: MyApp::LongCommentSerializer,
463
+ include_linkages: ['user'],
464
+ }),
465
+ # Note: post.author does not show up here because it was not included.
466
+ serialize_primary(comment_user, {serializer: MyApp::UserSerializer}),
467
+ ],
468
+ }
469
+ includes = ['long-comments', 'long-comments.user']
470
+ actual_data = JSONAPI::Serializer.serialize(post, include: includes)
471
+
472
+ # Multiple expectations for better diff output for debugging.
473
+ expect(actual_data['data']).to eq(expected_data['data'])
474
+ expect(actual_data['included']).to eq(expected_data['included'])
475
+ expect(actual_data).to eq(expected_data)
476
+ end
477
+ it 'handles recursive loading of to-many relationships with overlapping include paths' do
478
+ user = create(:user)
479
+ long_comments = create_list(:long_comment, 2, user: user)
480
+ post = create(:post, :with_author, long_comments: long_comments)
481
+ # Make sure each long-comment has a circular reference back to the post.
482
+ long_comments.each { |c| c.post = post }
483
+
484
+ expected_primary_data = serialize_primary(post, {
485
+ serializer: MyApp::PostSerializer,
486
+ include_linkages: ['long-comments'],
487
+ })
488
+ expected_data = {
489
+ 'data' => expected_primary_data,
490
+ 'included' => [
491
+ serialize_primary(long_comments.first, {serializer: MyApp::LongCommentSerializer}),
492
+ serialize_primary(long_comments.last, {serializer: MyApp::LongCommentSerializer}),
493
+ serialize_primary(post.author, {serializer: MyApp::UserSerializer}),
494
+ ],
495
+ }
496
+ # Also test that it handles string include arguments.
497
+ includes = 'long-comments, long-comments.post.author'
498
+ actual_data = JSONAPI::Serializer.serialize(post, include: includes)
499
+
500
+ # Multiple expectations for better diff output for debugging.
501
+ expect(actual_data['data']).to eq(expected_data['data'])
502
+ expect(actual_data['included']).to eq(expected_data['included'])
503
+ expect(actual_data).to eq(expected_data)
504
+ end
505
+
506
+ context 'on collection' do
507
+ it 'handles include of has_many relationships with compound document' do
508
+ long_comments = create_list(:long_comment, 2)
509
+ posts = create_list(:post, 2, :with_author, long_comments: long_comments)
510
+
511
+ expected_primary_data = JSONAPI::Serializer.send(:serialize_primary_multi, posts, {
512
+ serializer: MyApp::PostSerializer,
513
+ include_linkages: ['long-comments'],
514
+ })
515
+ data = JSONAPI::Serializer.serialize(posts, is_collection: true, include: ['long-comments'])
516
+ expect(data).to eq({
517
+ 'data' => expected_primary_data,
518
+ 'included' => [
519
+ serialize_primary(long_comments.first, {serializer: MyApp::LongCommentSerializer}),
520
+ serialize_primary(long_comments.last, {serializer: MyApp::LongCommentSerializer}),
521
+ ],
522
+ })
523
+ end
524
+ end
525
+ end
526
+
527
+ describe 'serialize (class method)' do
528
+ it 'delegates to module method but overrides serializer' do
529
+ post = create(:post)
530
+ expect(MyApp::SimplestPostSerializer.serialize(post)).to eq({
531
+ 'data' => serialize_primary(post, {serializer: MyApp::SimplestPostSerializer}),
532
+ })
533
+ end
534
+ end
535
+
536
+ describe 'internal-only parse_relationship_paths' do
537
+ it 'correctly handles empty arrays' do
538
+ result = JSONAPI::Serializer.send(:parse_relationship_paths, [])
539
+ expect(result).to eq({})
540
+ end
541
+ it 'correctly handles single-level relationship paths' do
542
+ result = JSONAPI::Serializer.send(:parse_relationship_paths, ['foo'])
543
+ expect(result).to eq({
544
+ 'foo' => {_include: true}
545
+ })
546
+ end
547
+ it 'correctly handles multi-level relationship paths' do
548
+ result = JSONAPI::Serializer.send(:parse_relationship_paths, ['foo.bar'])
549
+ expect(result).to eq({
550
+ 'foo' => {'bar' => {_include: true}}
551
+ })
552
+ end
553
+ it 'correctly handles multi-level relationship paths with same parent' do
554
+ paths = ['foo', 'foo.bar']
555
+ result = JSONAPI::Serializer.send(:parse_relationship_paths, paths)
556
+ expect(result).to eq({
557
+ 'foo' => {_include: true, 'bar' => {_include: true}}
558
+ })
559
+ end
560
+ it 'correctly handles multi-level relationship paths with different parent' do
561
+ paths = ['foo', 'bar', 'bar.baz']
562
+ result = JSONAPI::Serializer.send(:parse_relationship_paths, paths)
563
+ expect(result).to eq({
564
+ 'foo' => {_include: true},
565
+ 'bar' => {_include: true, 'baz' => {_include: true}},
566
+ })
567
+ end
568
+ it 'correctly handles three-leveled path' do
569
+ paths = ['foo', 'foo.bar', 'foo.bar.baz']
570
+ result = JSONAPI::Serializer.send(:parse_relationship_paths, paths)
571
+ expect(result).to eq({
572
+ 'foo' => {_include: true, 'bar' => {_include: true, 'baz' => {_include: true}}}
573
+ })
574
+ end
575
+ it 'correctly handles three-leveled path with skipped middle' do
576
+ paths = ['foo', 'foo.bar.baz']
577
+ result = JSONAPI::Serializer.send(:parse_relationship_paths, paths)
578
+ expect(result).to eq({
579
+ 'foo' => {_include: true, 'bar' => {'baz' => {_include: true}}}
580
+ })
581
+ end
582
+ end
583
+ describe 'if/unless handling with contexts' do
584
+ it 'can be used to show/hide attributes' do
585
+ post = create(:post)
586
+ options = {serializer: MyApp::PostSerializerWithContextHandling}
587
+
588
+ options[:context] = {show_body: false}
589
+ data = JSONAPI::Serializer.serialize(post, options)
590
+ expect(data['data']['attributes']).to_not have_key('body')
591
+
592
+ options[:context] = {show_body: true}
593
+ data = JSONAPI::Serializer.serialize(post, options)
594
+ expect(data['data']['attributes']).to have_key('body')
595
+ expect(data['data']['attributes']['body']).to eq('Body for Post 1')
596
+
597
+ options[:context] = {hide_body: true}
598
+ data = JSONAPI::Serializer.serialize(post, options)
599
+ expect(data['data']['attributes']).to_not have_key('body')
600
+
601
+ options[:context] = {hide_body: false}
602
+ data = JSONAPI::Serializer.serialize(post, options)
603
+ expect(data['data']['attributes']).to have_key('body')
604
+ expect(data['data']['attributes']['body']).to eq('Body for Post 1')
605
+
606
+ options[:context] = {show_body: false, hide_body: false}
607
+ data = JSONAPI::Serializer.serialize(post, options)
608
+ expect(data['data']['attributes']).to_not have_key('body')
609
+
610
+ options[:context] = {show_body: true, hide_body: false}
611
+ data = JSONAPI::Serializer.serialize(post, options)
612
+ expect(data['data']['attributes']).to have_key('body')
613
+ expect(data['data']['attributes']['body']).to eq('Body for Post 1')
614
+
615
+ # Remember: attribute is configured as if: show_body?, unless: hide_body?
616
+ # and the results should be logically AND'd together:
617
+ options[:context] = {show_body: false, hide_body: true}
618
+ data = JSONAPI::Serializer.serialize(post, options)
619
+ expect(data['data']['attributes']).to_not have_key('body')
620
+
621
+ options[:context] = {show_body: true, hide_body: true}
622
+ data = JSONAPI::Serializer.serialize(post, options)
623
+ expect(data['data']['attributes']).to_not have_key('body')
624
+ end
625
+ end
626
+ describe 'context' do
627
+ xit 'is correctly passed through all serializers' do
628
+ end
629
+ end
630
+ end
@@ -0,0 +1,19 @@
1
+ require 'factory_girl'
2
+ require './lib/jsonapi-serializers'
3
+ require './spec/support/serializers'
4
+
5
+ RSpec.configure do |config|
6
+ config.include FactoryGirl::Syntax::Methods
7
+
8
+ config.mock_with :rspec do |mocks|
9
+ mocks.verify_partial_doubles = true
10
+ end
11
+
12
+ config.before(:each) do
13
+ # Force FactoryGirl sequences to be fully reset before each test run to simplify ID testing
14
+ # since we are not using a database or real fixtures. Inside of each test case, IDs will
15
+ # increment per type starting at 1.
16
+ FactoryGirl.reload
17
+ load './spec/support/factory.rb'
18
+ end
19
+ end
@@ -0,0 +1,26 @@
1
+ require 'factory_girl'
2
+
3
+ FactoryGirl.define do
4
+ factory :post, class: MyApp::Post do
5
+ skip_create
6
+ sequence(:id) {|n| n }
7
+ sequence(:title) {|n| "Title for Post #{n}" }
8
+ sequence(:body) {|n| "Body for Post #{n}" }
9
+
10
+ trait :with_author do
11
+ association :author, factory: :user
12
+ end
13
+ end
14
+
15
+ factory :long_comment, class: MyApp::LongComment do
16
+ skip_create
17
+ sequence(:id) {|n| n }
18
+ sequence(:body) {|n| "Body for LongComment #{n}" }
19
+ end
20
+
21
+ factory :user, class: MyApp::User do
22
+ skip_create
23
+ sequence(:id) {|n| n }
24
+ sequence(:name) {|n| "User ##{n}"}
25
+ end
26
+ end