breezy_template 0.2.0 → 0.3.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -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