jsonapi-serializers 0.1.0

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.
@@ -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