breezy_template 0.2.0 → 0.3.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,714 @@
1
+ require 'test_helper'
2
+ require 'active_support/inflector'
3
+ require 'breezy_template'
4
+ require 'byebug'
5
+
6
+ def jbuild(&block)
7
+ BreezyTemplate.new({}, &block).attributes!
8
+ end
9
+
10
+ Comment = Struct.new(:content, :id)
11
+
12
+ class NonEnumerable
13
+ def initialize(collection)
14
+ @collection = collection
15
+ end
16
+
17
+ delegate :map, :count, to: :@collection
18
+ end
19
+
20
+ class VeryBasicWrapper < BasicObject
21
+ def initialize(thing)
22
+ @thing = thing
23
+ end
24
+
25
+ def method_missing(name, *args, &block)
26
+ @thing.send name, *args, &block
27
+ end
28
+ end
29
+
30
+ # This is not Struct, because structs are Enumerable
31
+ class Person
32
+ attr_reader :name, :age
33
+
34
+ def initialize(name, age)
35
+ @name, @age = name, age
36
+ end
37
+ end
38
+
39
+ class RelationMock
40
+ include Enumerable
41
+
42
+ def each(&block)
43
+ [Person.new('Bob', 30), Person.new('Frank', 50)].each(&block)
44
+ end
45
+
46
+ def empty?
47
+ false
48
+ end
49
+ end
50
+
51
+
52
+ class TemplateTest < ActiveSupport::TestCase
53
+ setup do
54
+ BreezyTemplate.send :class_variable_set, '@@key_formatter', nil
55
+ end
56
+
57
+ test 'single key' do
58
+ result = jbuild do |json|
59
+ json.content 'hello'
60
+ end
61
+
62
+ assert_equal 'hello', result['content']
63
+ end
64
+
65
+ test 'single key with false value' do
66
+ result = jbuild do |json|
67
+ json.content false
68
+ end
69
+
70
+ assert_equal false, result['content']
71
+ end
72
+
73
+ test 'single key with nil value' do
74
+ result = jbuild do |json|
75
+ json.content nil
76
+ end
77
+
78
+ assert result.has_key?('content')
79
+ assert_equal nil, result['content']
80
+ end
81
+
82
+ test 'multiple keys' do
83
+ result = jbuild do |json|
84
+ json.title 'hello'
85
+ json.content 'world'
86
+ end
87
+
88
+ assert_equal 'hello', result['title']
89
+ assert_equal 'world', result['content']
90
+ end
91
+
92
+ # test 'extracting from object' do
93
+ # person = Struct.new(:name, :age).new('David', 32)
94
+ #
95
+ # result = jbuild do |json|
96
+ # json.extract! person, :name, :age
97
+ # end
98
+ #
99
+ # assert_equal 'David', result['name']
100
+ # assert_equal 32, result['age']
101
+ # end
102
+
103
+ # test 'extracting from object using call style for 1.9' do
104
+ # person = Struct.new(:name, :age).new('David', 32)
105
+ #
106
+ # result = jbuild do |json|
107
+ # json.(person, :name, :age)
108
+ # end
109
+ #
110
+ # assert_equal 'David', result['name']
111
+ # assert_equal 32, result['age']
112
+ # end
113
+
114
+ # test 'extracting from hash' do
115
+ # person = {:name => 'Jim', :age => 34}
116
+ #
117
+ # result = jbuild do |json|
118
+ # json.extract! person, :name, :age
119
+ # end
120
+ #
121
+ # assert_equal 'Jim', result['name']
122
+ # assert_equal 34, result['age']
123
+ # end
124
+
125
+ test 'nesting single child with block' do
126
+ result = jbuild do |json|
127
+ json.author do
128
+ json.name 'David'
129
+ json.age 32
130
+ end
131
+ end
132
+
133
+ assert_equal 'David', result['author']['name']
134
+ assert_equal 32, result['author']['age']
135
+ end
136
+
137
+ test 'empty block handling' do
138
+ result = jbuild do |json|
139
+ json.foo 'bar'
140
+ json.author do
141
+ end
142
+ end
143
+
144
+ assert_equal 'bar', result['foo']
145
+ assert !result.key?('author')
146
+ end
147
+
148
+ test 'blocks will override, last one wins' do
149
+ result = jbuild do |json|
150
+ json.author do
151
+ json.name 'David'
152
+ end
153
+
154
+ json.author do
155
+ json.age 32
156
+ end
157
+ end
158
+
159
+ assert_equal nil, result['author']['name']
160
+ assert_equal 32, result['author']['age']
161
+ end
162
+ #
163
+ # test 'blocks are additive via extract syntax' do
164
+ # person = Person.new('Pavel', 27)
165
+ #
166
+ # result = jbuild do |json|
167
+ # json.author person, :age
168
+ # json.author person, :name
169
+ # end
170
+ #
171
+ # assert_equal 'Pavel', result['author']['name']
172
+ # assert_equal nil, result['author']['age']
173
+ # end
174
+
175
+ test 'arrays are not additive, last one wins' do
176
+ result = jbuild do |json|
177
+ json.array! %w[foo]
178
+ json.array! %w[bar]
179
+ end
180
+
181
+ assert_equal %w[bar], result
182
+ end
183
+
184
+ test 'nesting multiple children with block' do
185
+ result = jbuild do |json|
186
+ json.comments do
187
+ json.child! { json.content 'hello' }
188
+ json.child! { json.content 'world' }
189
+ end
190
+ end
191
+
192
+ assert_equal 'hello', result['comments'].first['content']
193
+ assert_equal 'world', result['comments'].second['content']
194
+ end
195
+
196
+ # test 'nesting single child with inline extract' do
197
+ # person = Person.new('David', 32)
198
+ #
199
+ # result = jbuild do |json|
200
+ # json.author person, :name, :age
201
+ # end
202
+ #
203
+ # assert_equal 'David', result['author']['name']
204
+ # assert_equal 32, result['author']['age']
205
+ # end
206
+ #
207
+ test 'nesting multiple children from array' do
208
+ comments = [ Comment.new('hello', 1), Comment.new('world', 2) ]
209
+
210
+ result = jbuild do |json|
211
+ json.comments do
212
+ json.array! comments do |comment|
213
+ json.content comment.content
214
+ end
215
+ end
216
+ end
217
+
218
+ assert_equal ['content'], result['comments'].first.keys
219
+ assert_equal 'hello', result['comments'].first['content']
220
+ assert_equal 'world', result['comments'].second['content']
221
+ end
222
+
223
+ test 'nesting multiple children from array when child array is empty' do
224
+ comments = []
225
+
226
+ result = jbuild do |json|
227
+ json.name 'Parent'
228
+ json.comments do
229
+ json.array! comments do |comment|
230
+ json.content comment.content
231
+ end
232
+ end
233
+ end
234
+
235
+ assert_equal 'Parent', result['name']
236
+ assert_equal [], result['comments']
237
+ end
238
+
239
+ # test 'nesting multiple children from array with inline loop' do
240
+ # comments = [ Comment.new('hello', 1), Comment.new('world', 2) ]
241
+ #
242
+ # result = jbuild do |json|
243
+ # json.comments comments do |comment|
244
+ # json.content comment.content
245
+ # end
246
+ # end
247
+ #
248
+ # assert_equal ['content'], result['comments'].first.keys
249
+ # assert_equal 'hello', result['comments'].first['content']
250
+ # assert_equal 'world', result['comments'].second['content']
251
+ # end
252
+
253
+ # todo: revisit test 'handles nil-collections as empty arrays' do
254
+ # result = jbuild do |json|
255
+ # json.comments nil do |comment|
256
+ # json.content comment.content
257
+ # end
258
+ # end
259
+ #
260
+ # assert_equal [], result['comments']
261
+ # end
262
+
263
+ test 'nesting multiple children from a non-Enumerable that responds to #map' do
264
+ comments = NonEnumerable.new([ Comment.new('hello', 1), Comment.new('world', 2) ])
265
+
266
+ result = jbuild do |json|
267
+ json.comments do
268
+ json.array! comments do |comment|
269
+ json.content comment.content
270
+ end
271
+ end
272
+ end
273
+
274
+ assert_equal ['content'], result['comments'].first.keys
275
+ assert_equal 'hello', result['comments'].first['content']
276
+ assert_equal 'world', result['comments'].second['content']
277
+ end
278
+
279
+ # test 'nesting multiple chilren from a non-Enumerable that responds to #map with inline loop' do
280
+ # comments = NonEnumerable.new([ Comment.new('hello', 1), Comment.new('world', 2) ])
281
+ #
282
+ # result = jbuild do |json|
283
+ # json.comments comments do |comment|
284
+ # json.content comment.content
285
+ # end
286
+ # end
287
+ #
288
+ # assert_equal ['content'], result['comments'].first.keys
289
+ # assert_equal 'hello', result['comments'].first['content']
290
+ # assert_equal 'world', result['comments'].second['content']
291
+ # end
292
+
293
+ test 'array! casts array-like objects to array before merging' do
294
+ wrapped_array = VeryBasicWrapper.new(%w[foo bar])
295
+
296
+ result = jbuild do |json|
297
+ json.array! wrapped_array
298
+ end
299
+
300
+ assert_equal %w[foo bar], result
301
+ end
302
+
303
+ # #todo: remove this ability
304
+ # test 'nesting multiple children from array with inline loop on root' do
305
+ # comments = [ Comment.new('hello', 1), Comment.new('world', 2) ]
306
+ #
307
+ # result = jbuild do |json|
308
+ # json.call(comments) do |comment|
309
+ # json.content comment.content
310
+ # end
311
+ # end
312
+ #
313
+ # assert_equal 'hello', result.first['content']
314
+ # assert_equal 'world', result.second['content']
315
+ # end
316
+
317
+ test 'array nested inside nested hash' do
318
+ result = jbuild do |json|
319
+ json.author do
320
+ json.name 'David'
321
+ json.age 32
322
+
323
+ json.comments do
324
+ json.child! { json.content 'hello' }
325
+ json.child! { json.content 'world' }
326
+ end
327
+ end
328
+ end
329
+
330
+ assert_equal 'hello', result['author']['comments'].first['content']
331
+ assert_equal 'world', result['author']['comments'].second['content']
332
+ end
333
+
334
+ test 'array nested inside array' do
335
+ result = jbuild do |json|
336
+ json.comments do
337
+ json.child! do
338
+ json.authors do
339
+ json.child! do
340
+ json.name 'david'
341
+ end
342
+ end
343
+ end
344
+ end
345
+ end
346
+
347
+ assert_equal 'david', result['comments'].first['authors'].first['name']
348
+ end
349
+
350
+ test 'directly set an array nested in another array' do
351
+ data = [ { :department => 'QA', :not_in_json => 'hello', :names => ['John', 'David'] } ]
352
+
353
+ result = jbuild do |json|
354
+ json.array! data do |object|
355
+ json.department object[:department]
356
+ json.names do
357
+ json.array! object[:names]
358
+ end
359
+ end
360
+ end
361
+
362
+ assert_equal 'David', result[0]['names'].last
363
+ assert !result[0].key?('not_in_json')
364
+ end
365
+ # skip for now
366
+ # test 'nested jbuilder objects' do
367
+ # to_nest = Jbuilder.new{ |json| json.nested_value 'Nested Test' }
368
+ #
369
+ # result = jbuild do |json|
370
+ # json.value 'Test'
371
+ # json.nested to_nest
372
+ # end
373
+ #
374
+ # expected = {'value' => 'Test', 'nested' => {'nested_value' => 'Nested Test'}}
375
+ # assert_equal expected, result
376
+ # end
377
+ #
378
+ # test 'nested jbuilder object via set!' do
379
+ # to_nest = Jbuilder.new{ |json| json.nested_value 'Nested Test' }
380
+ #
381
+ # result = jbuild do |json|
382
+ # json.value 'Test'
383
+ # json.set! :nested, to_nest
384
+ # end
385
+ #
386
+ # expected = {'value' => 'Test', 'nested' => {'nested_value' => 'Nested Test'}}
387
+ # assert_equal expected, result
388
+ # end
389
+ #
390
+ test 'top-level array' do
391
+ comments = [ Comment.new('hello', 1), Comment.new('world', 2) ]
392
+
393
+ result = jbuild do |json|
394
+ json.array! comments do |comment|
395
+ json.content comment.content
396
+ end
397
+ end
398
+
399
+ assert_equal 'hello', result.first['content']
400
+ assert_equal 'world', result.second['content']
401
+ end
402
+
403
+ test 'it allows using next in array block to skip value' do
404
+ comments = [ Comment.new('hello', 1), Comment.new('skip', 2), Comment.new('world', 3) ]
405
+ result = jbuild do |json|
406
+ json.array! comments do |comment|
407
+ next if comment.id == 2
408
+ json.content comment.content
409
+ end
410
+ end
411
+
412
+ assert_equal 2, result.length
413
+ assert_equal 'hello', result.first['content']
414
+ assert_equal 'world', result.second['content']
415
+ end
416
+
417
+ test 'extract attributes directly from array' do
418
+ comments = [ Comment.new('hello', 1), Comment.new('world', 2) ]
419
+
420
+ result = jbuild do |json|
421
+ json.array! comments, :content, :id
422
+ end
423
+
424
+ assert_equal 'hello', result.first['content']
425
+ assert_equal 1, result.first['id']
426
+ assert_equal 'world', result.second['content']
427
+ assert_equal 2, result.second['id']
428
+ end
429
+
430
+ test 'empty top-level array' do
431
+ comments = []
432
+
433
+ result = jbuild do |json|
434
+ json.array! comments do |comment|
435
+ json.content comment.content
436
+ end
437
+ end
438
+
439
+ assert_equal [], result
440
+ end
441
+
442
+ test 'dynamically set a key/value' do
443
+ result = jbuild do |json|
444
+ json.set! :each, 'stuff'
445
+ end
446
+
447
+ assert_equal 'stuff', result['each']
448
+ end
449
+
450
+ test 'dynamically set a key/nested child with block' do
451
+ result = jbuild do |json|
452
+ json.set! :author do
453
+ json.name 'David'
454
+ json.age 32
455
+ end
456
+ end
457
+
458
+ assert_equal 'David', result['author']['name']
459
+ assert_equal 32, result['author']['age']
460
+ end
461
+
462
+ # test 'dynamically sets a collection' do
463
+ # comments = [ Comment.new('hello', 1), Comment.new('world', 2) ]
464
+ #
465
+ # result = jbuild do |json|
466
+ # json.set! :comments, comments, :content
467
+ # end
468
+ #
469
+ # assert_equal ['content'], result['comments'].first.keys
470
+ # assert_equal 'hello', result['comments'].first['content']
471
+ # assert_equal 'world', result['comments'].second['content']
472
+ # end
473
+
474
+ # test 'query like object' do
475
+ # result = jbuild do |json|
476
+ # json.relations RelationMock.new, :name, :age
477
+ # end
478
+ #
479
+ # assert_equal 2, result['relations'].length
480
+ # assert_equal 'Bob', result['relations'][0]['name']
481
+ # assert_equal 50, result['relations'][1]['age']
482
+ # end
483
+
484
+ # reconsider
485
+ # test 'initialize via options hash' do
486
+ # jbuilder = Jbuilder.new(key_formatter: 1, ignore_nil: 2)
487
+ # assert_equal 1, jbuilder.instance_eval{ @key_formatter }
488
+ # assert_equal 2, jbuilder.instance_eval{ @ignore_nil }
489
+ # end
490
+
491
+ test 'key_format! with parameter' do
492
+ result = jbuild do |json|
493
+ json.key_format! camelize: [:lower]
494
+ json.camel_style 'for JS'
495
+ end
496
+
497
+ assert_equal ['camelStyle'], result.keys
498
+ end
499
+
500
+ test 'key_format! with parameter not as an array' do
501
+ result = jbuild do |json|
502
+ json.key_format! :camelize => :lower
503
+ json.camel_style 'for JS'
504
+ end
505
+
506
+ assert_equal ['camelStyle'], result.keys
507
+ end
508
+
509
+ test 'key_format! propagates to child elements' do
510
+ result = jbuild do |json|
511
+ json.key_format! :upcase
512
+ json.level1 'one'
513
+ json.level2 do
514
+ json.value 'two'
515
+ end
516
+ end
517
+
518
+ assert_equal 'one', result['LEVEL1']
519
+ assert_equal 'two', result['LEVEL2']['VALUE']
520
+ end
521
+
522
+ test 'key_format! resets after child element' do
523
+ result = jbuild do |json|
524
+ json.level2 do
525
+ json.key_format! :upcase
526
+ json.value 'two'
527
+ end
528
+ json.level1 'one'
529
+ end
530
+
531
+ assert_equal 'two', result['level2']['VALUE']
532
+ assert_equal 'one', result['level1']
533
+ end
534
+
535
+ test 'key_format! with no parameter' do
536
+ result = jbuild do |json|
537
+ json.key_format! :upcase
538
+ json.lower 'Value'
539
+ end
540
+
541
+ assert_equal ['LOWER'], result.keys
542
+ end
543
+
544
+ test 'key_format! with multiple steps' do
545
+ result = jbuild do |json|
546
+ json.key_format! :upcase, :pluralize
547
+ json.pill 'foo'
548
+ end
549
+
550
+ assert_equal ['PILLs'], result.keys
551
+ end
552
+
553
+ test 'key_format! with lambda/proc' do
554
+ result = jbuild do |json|
555
+ json.key_format! ->(key){ key + ' and friends' }
556
+ json.oats 'foo'
557
+ end
558
+
559
+ assert_equal ['oats and friends'], result.keys
560
+ end
561
+
562
+ test 'default key_format!' do
563
+ BreezyTemplate.key_format camelize: :lower
564
+ result = jbuild{ |json| json.camel_style 'for JS' }
565
+ assert_equal ['camelStyle'], result.keys
566
+ end
567
+ #
568
+ test 'do not use default key formatter directly' do
569
+ BreezyTemplate.key_format
570
+ jbuild{ |json| json.key 'value' }
571
+ formatter = BreezyTemplate.send(:class_variable_get, '@@key_formatter')
572
+ cache = formatter.instance_variable_get('@cache')
573
+ assert_empty cache
574
+ end
575
+
576
+ test 'ignore_nil! without a parameter' do
577
+ result = jbuild do |json|
578
+ json.ignore_nil!
579
+ json.test nil
580
+ end
581
+
582
+ assert_empty result.keys
583
+ end
584
+
585
+ test 'ignore_nil! with parameter' do
586
+ result = jbuild do |json|
587
+ json.ignore_nil! true
588
+ json.name 'Bob'
589
+ json.dne nil
590
+ end
591
+
592
+ assert_equal ['name'], result.keys
593
+
594
+ result = jbuild do |json|
595
+ json.ignore_nil! false
596
+ json.name 'Bob'
597
+ json.dne nil
598
+ end
599
+
600
+ assert_equal ['name', 'dne'], result.keys
601
+ end
602
+
603
+ test 'default ignore_nil!' do
604
+ BreezyTemplate.ignore_nil
605
+
606
+ result = jbuild do |json|
607
+ json.name 'Bob'
608
+ json.dne nil
609
+ end
610
+
611
+ assert_equal ['name'], result.keys
612
+ BreezyTemplate.send(:class_variable_set, '@@ignore_nil', false)
613
+ end
614
+
615
+ test 'nil!' do
616
+ result = jbuild do |json|
617
+ json.key 'value'
618
+ json.nil!
619
+ end
620
+
621
+ assert_nil result
622
+ end
623
+
624
+ test 'null!' do
625
+ result = jbuild do |json|
626
+ json.key 'value'
627
+ json.null!
628
+ end
629
+
630
+ assert_nil result
631
+ end
632
+
633
+ test 'null! in a block' do
634
+ result = jbuild do |json|
635
+ json.author do
636
+ json.name 'David'
637
+ end
638
+
639
+ json.author do
640
+ json.null!
641
+ end
642
+ end
643
+
644
+ assert result.key?('author')
645
+ assert_nil result['author']
646
+ end
647
+
648
+ test 'empty attributes respond to empty?' do
649
+ attributes = BreezyTemplate.new({}).attributes!
650
+ assert attributes.empty?
651
+ assert attributes.blank?
652
+ assert !attributes.present?
653
+ end
654
+
655
+ test 'throws ArrayError when trying to add a key to an array' do
656
+ assert_raise BreezyTemplate::ArrayError do
657
+ jbuild do |json|
658
+ json.array! %w[foo bar]
659
+ json.fizz "buzz"
660
+ end
661
+ end
662
+ end
663
+
664
+ test 'throws NullError when trying to add properties to null' do
665
+ assert_raise BreezyTemplate::NullError do
666
+ jbuild do |json|
667
+ json.null!
668
+ json.foo 'bar'
669
+ end
670
+ end
671
+ end
672
+
673
+ # All of the below no longer happens, merge is private
674
+ # test 'throws NullError when trying to add properties to null using block syntax' do
675
+ # assert_raise BreezyTemplate::NullError do
676
+ # jbuild do |json|
677
+ # json.author do
678
+ # json.null!
679
+ # end
680
+ #
681
+ # json.author do
682
+ # json.name "Pavel"
683
+ # end
684
+ # end
685
+ # end
686
+ # end
687
+ #
688
+ # test "throws MergeError when trying to merge array with non-empty hash" do
689
+ # assert_raise BreezyTemplate::MergeError do
690
+ # jbuild do |json|
691
+ # json.name "Daniel"
692
+ # json.merge! []
693
+ # end
694
+ # end
695
+ # end
696
+ #
697
+ # test "throws MergeError when trying to merge hash with array" do
698
+ # assert_raise BreezyTemplate::MergeError do
699
+ # jbuild do |json|
700
+ # json.array!
701
+ # json.merge!({})
702
+ # end
703
+ # end
704
+ # end
705
+
706
+ # test "throws MergeError when trying to merge invalid objects" do
707
+ # assert_raise BreezyTemplate::MergeError do
708
+ # jbuild do |json|
709
+ # json.name "Daniel"
710
+ # json.merge! "Nope"
711
+ # end
712
+ # end
713
+ # end
714
+ end