breezy_template 0.10.1 → 0.11.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 196103d517bfc16643b1bc270edf634b9ec60d72
4
- data.tar.gz: 7af3f57a2e858036f9b9a45051e2816539b45a52
3
+ metadata.gz: fd735e59d268c9b87e7bc62528a0a5fb848a23c0
4
+ data.tar.gz: 4064dde7ecda53a3c53564e04001d59389f5e6d5
5
5
  SHA512:
6
- metadata.gz: 0227c106472a3e605ebfbe4cafd22392ad93d70ffbf79a0fadfe12814e3741c6ce01256486620a36fb06361ae01e13066399fce8242b485a1b981ea95db366e8
7
- data.tar.gz: f9e1d92f429733c66db0d76307111ee388af65c697a3484a76e6a6a9886c174373f80c585aaba48c99e115eda9d0f3c721906716a1c2e3627c2f0ab731d98857
6
+ metadata.gz: a538e32972a47d82750036f7163c447dd68a964878c591a52f9a16f6ab3cd9693638cd23af36496e61b951bd7e848f9ed9881a274cda3557da9d55813a54b9e0
7
+ data.tar.gz: 334ff1aa1d34964f882e2ad8b10e91a534edcd934e7ec63c8b7229ce7844bf4429a8675a5f16c7e7473f7db757f8955ca7a22f1c2e960c996c4dea55828e540f
@@ -81,7 +81,7 @@ class BreezyTemplate
81
81
  end
82
82
 
83
83
  def _cache_options(options)
84
- return nil if !options
84
+ return nil if !options || options.blank?
85
85
  options = [*options[:cache]]
86
86
  key, options = options
87
87
 
@@ -18,7 +18,7 @@ class BreezyTemplate
18
18
 
19
19
  def _breezy_visit_current(path)
20
20
  uri = ::URI.parse(@request_path)
21
- qry = ::URI.decode_www_form(uri.query || '') << ["_bz", path.join('.')]
21
+ qry = ::URI.decode_www_form(uri.query || '') << ["bzq", path.join('.')]
22
22
  uri.query = ::URI.encode_www_form(qry)
23
23
  "defers.push({url:'#{uri}'});"
24
24
  end
@@ -28,4 +28,11 @@ class BreezyTemplate
28
28
  new(message)
29
29
  end
30
30
  end
31
+
32
+ class LeafTraversalError < ::StandardError
33
+ def self.build(key, value, options, search_path)
34
+ message = "Attempted to traverse into node named #{key} but got a value. This may happen if you forgot to use nil as a first value if you're using a partial, e.g, json.foo nil, partial: 'footer'. Key: #{key} Value: #{value} Options: #{options} Remaining search path: #{search_path}."
35
+ new(message)
36
+ end
37
+ end
31
38
  end
@@ -17,7 +17,7 @@ class BreezyTemplate
17
17
  options = _normalize_options_for_partial(options)
18
18
 
19
19
  if attributes.one? && _partial_options?(options)
20
- _render_partial_with_options(collection, options)
20
+ _render_partial_with_collection(collection, options)
21
21
  else
22
22
  super
23
23
  end
@@ -47,7 +47,7 @@ class BreezyTemplate
47
47
 
48
48
  def _partial_digest(partial)
49
49
  lookup_context = @context.lookup_context
50
- name = lookup_context.find(partial, lookup_context.prefixes, true).virtual_path
50
+ name = lookup_context.find(partial, [], true).virtual_path
51
51
  _partial_digestor({name: name, finder: lookup_context})
52
52
  end
53
53
 
@@ -64,12 +64,10 @@ class BreezyTemplate
64
64
  locals.merge!(partial_opts[:locals]) if partial_opts.key? :locals
65
65
  partial_opts.merge!(locals: locals)
66
66
 
67
- _scope{ _render_partial(options) }
67
+ _result(BLANK, options){ _render_partial(options) }
68
68
  end
69
69
 
70
- options = options.dup
71
- options.delete(:partial)
72
- set! name, value, options
70
+ set! name, value
73
71
  end
74
72
 
75
73
  def _render_partial(options)
@@ -86,7 +84,7 @@ class BreezyTemplate
86
84
  @context.render options.merge(partial: partial)
87
85
  end
88
86
 
89
- def _render_partial_with_options(collection, options)
87
+ def _render_partial_with_collection(collection, options)
90
88
  options = _normalize_options_for_partial(options)
91
89
  partial, partial_opts = options[:partial]
92
90
  array_opts = options.dup
@@ -70,10 +70,12 @@ class BreezyTemplate
70
70
  if ::Kernel.block_given?
71
71
  yield self
72
72
  elsif _partial_options?(options)
73
- without_track = args.dup
74
- super(key, value, *without_track)
73
+ without = options.dup
74
+ without.delete(:cache)
75
+
76
+ super(key, value, without)
75
77
  else
76
- ::Kernel.raise 'This should not happen'
78
+ ::Kernel.raise LeafTraversalError.build(key, value, options, @search_path)
77
79
  end
78
80
  end
79
81
 
@@ -0,0 +1,334 @@
1
+ require "test_helper"
2
+
3
+
4
+ class CacheExtensionTest < BreezyTemplateTestCase
5
+ test "caching a value at a node" do
6
+ undef_context_methods :fragment_name_with_digest, :cache_fragment_name
7
+
8
+ result = jbuild(<<-JBUILDER)
9
+ opts = {
10
+ cache: [['b', 'c']]
11
+ }
12
+ json.hello 32, opts
13
+ JBUILDER
14
+
15
+ expected = strip_format(<<-JS)
16
+ (function(){
17
+ var fragments={};
18
+ var lastFragmentName;
19
+ var lastFragmentPath;
20
+ var cache={};
21
+ var defers=[];
22
+ cache["#{cache_keys[0]}"]=32;
23
+ return ({"data":{"hello":cache["#{cache_keys[0]}"]},"screen":"test","fragments":fragments,"privateOpts":{"lastFragmentName":lastFragmentName,"lastFragmentPath":lastFragmentPath,"defers":defers}});
24
+ })()
25
+ JS
26
+
27
+ assert_equal expected, result
28
+ end
29
+
30
+ test "caching elements in a list" do
31
+ undef_context_methods :fragment_name_with_digest, :cache_fragment_name
32
+
33
+ result = jbuild(<<-JBUILDER)
34
+ json.hello do
35
+ opts = {
36
+ cache: ->(i){ ['a', i] }
37
+ }
38
+ json.array! [4,5], opts do |x|
39
+ json.top "hello" + x.to_s
40
+ end
41
+ end
42
+ JBUILDER
43
+
44
+ expected = strip_format(<<-JS)
45
+ (function(){
46
+ var fragments={};
47
+ var lastFragmentName;
48
+ var lastFragmentPath;
49
+ var cache={};
50
+ var defers=[];
51
+ cache["#{cache_keys[0]}"]={"top":"hello4"};
52
+ cache["#{cache_keys[1]}"]={"top":"hello5"};
53
+ return ({"data":{"hello":[cache["#{cache_keys[0]}"],cache["#{cache_keys[1]}"]]},"screen":"test","fragments":fragments,"privateOpts":{"lastFragmentName":lastFragmentName,"lastFragmentPath":lastFragmentPath,"defers":defers}});
54
+ })()
55
+ JS
56
+
57
+ assert_equal expected, result
58
+ end
59
+
60
+ test "nested caching generates a depth-first list of cache nodes" do
61
+ undef_context_methods :fragment_name_with_digest, :cache_fragment_name
62
+
63
+ result = jbuild(<<-JBUILDER)
64
+ json.hello cache: [['a', 'b']] do
65
+ json.content cache: [['d', 'z']] do
66
+ json.subcontent 'inner'
67
+ end
68
+ json.other cache: [['e', 'z']] do
69
+ json.subcontent 'other'
70
+ end
71
+ end
72
+ JBUILDER
73
+
74
+ expected = strip_format(<<-JS)
75
+ (function(){
76
+ var fragments={};
77
+ var lastFragmentName;
78
+ var lastFragmentPath;
79
+ var cache={};
80
+ var defers=[];
81
+ cache["#{cache_keys[0]}"]={"subcontent":"inner"};
82
+ cache["#{cache_keys[1]}"]={"subcontent":"other"};
83
+ cache["#{cache_keys[2]}"]={"content":cache["#{cache_keys[0]}"],"other":cache["#{cache_keys[1]}"]};
84
+ return ({"data":{"hello":cache["#{cache_keys[2]}"]},"screen":"test","fragments":fragments,"privateOpts":{"lastFragmentName":lastFragmentName,"lastFragmentPath":lastFragmentPath,"defers":defers}});
85
+ })()
86
+ JS
87
+
88
+ assert_equal expected, result
89
+ end
90
+
91
+ test "caching an empty block generates no cache and no errors" do
92
+ undef_context_methods :fragment_name_with_digest, :cache_fragment_name
93
+
94
+ result = nil
95
+
96
+ assert_nothing_raised do
97
+ result = jbuild(<<-JBUILDER)
98
+ json.hello do
99
+ json.array! [4,5], cache: ->(i){['a', i]} do |x|
100
+ end
101
+ end
102
+ JBUILDER
103
+ end
104
+
105
+ expected = strip_format(<<-JS)
106
+ (function(){
107
+ var fragments={};
108
+ var lastFragmentName;
109
+ var lastFragmentPath;
110
+ var cache={};
111
+ var defers=[];
112
+ return ({\"data\":{\"hello\":[]},"screen":"test","fragments":fragments,"privateOpts":{"lastFragmentName":lastFragmentName,"lastFragmentPath":lastFragmentPath,"defers":defers}});
113
+ })()
114
+ JS
115
+
116
+ assert_equal expected, result
117
+ end
118
+
119
+ test "fragment caching" do
120
+ undef_context_methods :fragment_name_with_digest, :cache_fragment_name
121
+
122
+ jbuild(<<-JBUILDER)
123
+ opts = {cache: ['cachekey']}
124
+ json.post opts do
125
+ json.name "Cache"
126
+ end
127
+ JBUILDER
128
+
129
+ result = jbuild(<<-JBUILDER)
130
+ opts = {cache: ['cachekey']}
131
+ json.post opts do
132
+ json.name "Miss"
133
+ end
134
+ JBUILDER
135
+
136
+ expected = strip_format(<<-JS)
137
+ (function(){
138
+ var fragments={};
139
+ var lastFragmentName;
140
+ var lastFragmentPath;
141
+ var cache={};
142
+ var defers=[];
143
+ cache["#{cache_keys[0]}"]={"name":"Cache"};
144
+ return ({"data":{"post":cache["#{cache_keys[0]}"]},"screen":"test","fragments":fragments,"privateOpts":{"lastFragmentName":lastFragmentName,"lastFragmentPath":lastFragmentPath,"defers":defers}});
145
+ })()
146
+ JS
147
+
148
+ assert_equal expected, result
149
+ end
150
+
151
+ test "fragment caching deserializes an array" do
152
+ undef_context_methods :fragment_name_with_digest, :cache_fragment_name
153
+
154
+ result = jbuild <<-JBUILDER
155
+ json.content cache: "cachekey" do
156
+ json.array! %w[a b c]
157
+ end
158
+ JBUILDER
159
+
160
+ expected = strip_format(<<-JS)
161
+ (function(){
162
+ var fragments={};
163
+ var lastFragmentName;
164
+ var lastFragmentPath;
165
+ var cache={};
166
+ var defers=[];
167
+ cache["#{cache_keys[0]}"]=["a","b","c"];
168
+ return ({"data":{"content":cache["#{cache_keys[0]}"]},"screen":"test","fragments":fragments,"privateOpts":{"lastFragmentName":lastFragmentName,"lastFragmentPath":lastFragmentPath,"defers":defers}});
169
+ })()
170
+ JS
171
+
172
+ assert_equal expected, result
173
+ end
174
+
175
+ test "fragment caching works with previous version of cache digests" do
176
+ undef_context_methods :cache_fragment_name
177
+
178
+ if !@context.class.method_defined? :fragment_name_with_digest
179
+ @context.class_eval do
180
+ def fragment_name_with_digest
181
+ end
182
+ end
183
+ end
184
+
185
+ @context.expects :fragment_name_with_digest
186
+
187
+ jbuild <<-JBUILDER
188
+ json.content cache: 'cachekey' do
189
+ json.name "Cache"
190
+ end
191
+ JBUILDER
192
+ end
193
+
194
+ test "fragment caching works with current cache digests" do
195
+ undef_context_methods :fragment_name_with_digest
196
+
197
+ @context.expects :cache_fragment_name
198
+ ActiveSupport::Cache.expects :expand_cache_key
199
+
200
+ jbuild <<-JBUILDER
201
+ json.content cache: 'cachekey' do
202
+ json.name "Cache"
203
+ end
204
+ JBUILDER
205
+ end
206
+
207
+ test "does not perform caching when controller.perform_caching is false" do
208
+ controller.perform_caching = false
209
+
210
+ result = jbuild <<-JBUILDER
211
+ json.content cache: 'cachekey' do
212
+ json.name "Cache"
213
+ end
214
+ JBUILDER
215
+
216
+ expected = strip_format(<<-JS)
217
+ (function(){
218
+ var fragments={};
219
+ var lastFragmentName;
220
+ var lastFragmentPath;
221
+ var cache={};
222
+ var defers=[];
223
+ return ({"data":{"content":{"name":"Cache"}},"screen":"test","fragments":fragments,"privateOpts":{"lastFragmentName":lastFragmentName,"lastFragmentPath":lastFragmentPath,"defers":defers}});
224
+ })()
225
+ JS
226
+
227
+ assert_equal expected, result
228
+ end
229
+
230
+ test "caches and runs a partial exactly once" do
231
+ jbuild(<<-JBUILDER)
232
+ json.hit nil, partial: ["raise_if_used", locals: {used: false}], cache: 'once'
233
+ json.miss nil, partial: ["raise_if_used", locals: {used: true}], cache: 'once'
234
+ JBUILDER
235
+ end
236
+
237
+ test "invokes templates via params via set! and caches" do
238
+ @post = BLOG_POST_COLLECTION.first
239
+
240
+ result = jbuild(<<-JBUILDER)
241
+ json.post @post, partial: ["blog_post", as: :blog_post], cache: [['a', 'b']]
242
+ JBUILDER
243
+
244
+ expected = strip_format(<<-JS)
245
+ (function(){
246
+ var fragments={};
247
+ var lastFragmentName;
248
+ var lastFragmentPath;
249
+ var cache={};
250
+ var defers=[];
251
+ cache["#{cache_keys[0]}"]={"id":1,"body":"post body 1","author":{"firstName":"David","lastName":"Heinemeier Hansson"}};
252
+ return ({"data":{"post":cache["#{cache_keys[0]}"]},"screen":"test","fragments":fragments,"privateOpts":{"lastFragmentName":lastFragmentName,"lastFragmentPath":lastFragmentPath,"defers":defers}});
253
+ })()
254
+ JS
255
+
256
+ assert_equal expected, result
257
+ end
258
+
259
+ test "shares partial caches (via the partial's digest) across multiple templates" do
260
+ undef_context_methods :fragment_name_with_digest, :cache_fragment_name
261
+
262
+ @hit = BlogPost.new(1, "hit", "John Smith")
263
+ @miss = BlogPost.new(2, "miss", "John Smith")
264
+
265
+ cat = jbuild(<<-JBUILDER)
266
+ opts = {
267
+ cache: [['a', 'b']],
268
+ partial: ["blog_post", as: :blog_post]
269
+ }
270
+
271
+ json.post @hit, opts
272
+ JBUILDER
273
+
274
+ result = jbuild(<<-JBUILDER)
275
+ opts = {
276
+ cache: [['a', 'b']],
277
+ partial: ["blog_post", as: :blog_post]
278
+ }
279
+
280
+ json.post @miss, opts
281
+ JBUILDER
282
+
283
+ expected = strip_format(<<-JS)
284
+ (function(){
285
+ var fragments={};
286
+ var lastFragmentName;
287
+ var lastFragmentPath;
288
+ var cache={};
289
+ var defers=[];
290
+ cache["#{cache_keys[0]}"]={"id":1,"body":"hit","author":{"firstName":"John","lastName":"Smith"}};
291
+ return ({"data":{"post":cache["#{cache_keys[0]}"]},"screen":"test","fragments":fragments,"privateOpts":{"lastFragmentName":lastFragmentName,"lastFragmentPath":lastFragmentPath,"defers":defers}});
292
+ })()
293
+ JS
294
+
295
+ assert_equal expected, result
296
+ end
297
+
298
+
299
+ test "render array of partials and caches" do
300
+ result = jbuild(<<-JBUILDER)
301
+ opts = {
302
+ cache: (->(d){ ['a', d.id] }),
303
+ partial: ["blog_post", as: :blog_post]
304
+ }
305
+ json.array! BLOG_POST_COLLECTION, opts
306
+ JBUILDER
307
+ Rails.cache.clear
308
+
309
+ expected = strip_format(<<-JS)
310
+ (function(){
311
+ var fragments={};
312
+ var lastFragmentName;
313
+ var lastFragmentPath;
314
+ var cache={};
315
+ var defers=[];
316
+ cache["#{cache_keys[0]}"]={"id":1,"body":"post body 1","author":{"firstName":"David","lastName":"Heinemeier Hansson"}};
317
+ cache["#{cache_keys[1]}"]={"id":2,"body":"post body 2","author":{"firstName":"Pavel","lastName":"Pravosud"}};
318
+ cache["#{cache_keys[2]}"]={"id":3,"body":"post body 3","author":{"firstName":"David","lastName":"Heinemeier Hansson"}};
319
+ cache["#{cache_keys[3]}"]={"id":4,"body":"post body 4","author":{"firstName":"Pavel","lastName":"Pravosud"}};
320
+ cache["#{cache_keys[4]}"]={"id":5,"body":"post body 5","author":{"firstName":"David","lastName":"Heinemeier Hansson"}};
321
+ cache["#{cache_keys[5]}"]={"id":6,"body":"post body 6","author":{"firstName":"Pavel","lastName":"Pravosud"}};
322
+ cache["#{cache_keys[6]}"]={"id":7,"body":"post body 7","author":{"firstName":"David","lastName":"Heinemeier Hansson"}};
323
+ cache["#{cache_keys[7]}"]={"id":8,"body":"post body 8","author":{"firstName":"Pavel","lastName":"Pravosud"}};
324
+ cache["#{cache_keys[8]}"]={"id":9,"body":"post body 9","author":{"firstName":"David","lastName":"Heinemeier Hansson"}};
325
+ cache["#{cache_keys[9]}"]={"id":10,"body":"post body 10","author":{"firstName":"Pavel","lastName":"Pravosud"}};
326
+ return ({"data":[cache["#{cache_keys[0]}"],cache["#{cache_keys[1]}"],cache["#{cache_keys[2]}"],cache["#{cache_keys[3]}"],cache["#{cache_keys[4]}"],cache["#{cache_keys[5]}"],cache["#{cache_keys[6]}"],cache["#{cache_keys[7]}"],cache["#{cache_keys[8]}"],cache["#{cache_keys[9]}"]],"screen":"test","fragments":fragments,"privateOpts":{"lastFragmentName":lastFragmentName,"lastFragmentPath":lastFragmentPath,"defers":defers}});
327
+ })()
328
+ JS
329
+ assert_equal expected, result
330
+ end
331
+ end
332
+
333
+
334
+
@@ -0,0 +1,322 @@
1
+ require "test_helper"
2
+
3
+ class DefermentExtensionTest < BreezyTemplateTestCase
4
+ test "rendering with node deferement" do
5
+ req = action_controller_test_request
6
+ req.path = '/some_url'
7
+
8
+ result = jbuild(<<-JBUILDER, request: req)
9
+ json.hit do
10
+ json.hit2(defer: :auto)do
11
+ json.hit3 do
12
+ json.greeting 'hello world'
13
+ end
14
+ end
15
+ end
16
+ JBUILDER
17
+ Rails.cache.clear
18
+
19
+ expected = strip_format(<<-JS)
20
+ (function(){
21
+ var fragments={};
22
+ var lastFragmentName;
23
+ var lastFragmentPath;
24
+ var cache={};
25
+ var defers=[];
26
+ defers.push({url:'/some_url?bzq=hit.hit2'});
27
+ return (
28
+ {"data":{"hit":{"hit2":undefined}},"screen":"test","fragments":fragments,"privateOpts":{"lastFragmentName":lastFragmentName,"lastFragmentPath":lastFragmentPath,"defers":defers}}
29
+ );
30
+ })()
31
+ JS
32
+
33
+ assert_equal expected, result
34
+ end
35
+
36
+ test "rendering with manual node deferement" do
37
+ req = action_controller_test_request
38
+ req.path = '/some_url'
39
+
40
+ result = jbuild(<<-JBUILDER, request: req)
41
+ json.hit do
42
+ json.hit2 defer: :manual do
43
+ json.hit3 do
44
+ json.greeting 'hello world'
45
+ end
46
+ end
47
+ end
48
+ JBUILDER
49
+ Rails.cache.clear
50
+
51
+ expected = strip_format(<<-JS)
52
+ (function(){
53
+ var fragments={};
54
+ var lastFragmentName;
55
+ var lastFragmentPath;
56
+ var cache={};
57
+ var defers=[];
58
+ return (
59
+ {"data":{"hit":{"hit2":undefined}},"screen":"test","fragments":fragments,"privateOpts":{"lastFragmentName":lastFragmentName,"lastFragmentPath":lastFragmentPath,"defers":defers}}
60
+ );
61
+ })()
62
+ JS
63
+
64
+ assert_equal expected, result
65
+ end
66
+
67
+ test "rendering with selective array node deferment" do
68
+ req = action_controller_test_request
69
+ req.path = '/some_url'
70
+
71
+ result = jbuild(<<-JBUILDER, request: req)
72
+ keep_first = lambda do |item|
73
+ if item[:id] == 1
74
+ false
75
+ else
76
+ :auto
77
+ end
78
+ end
79
+
80
+ json.hit do
81
+ json.hit2 do
82
+ data = [{id: 1, name: 'foo'}, {id: 2, name: 'bar'}]
83
+ json.array! data, key: :id, defer: keep_first do |item|
84
+ json.name item[:name]
85
+ end
86
+ end
87
+ end
88
+ JBUILDER
89
+ Rails.cache.clear
90
+
91
+ expected = strip_format(<<-JS)
92
+ (function(){
93
+ var fragments={};
94
+ var lastFragmentName;
95
+ var lastFragmentPath;
96
+ var cache={};
97
+ var defers=[];
98
+ defers.push({url:'/some_url?bzq=hit.hit2.id%3D2'});
99
+ return (
100
+ {"data":{"hit":{"hit2":[{"name":"foo"},{"id":2}]}},"screen":"test","fragments":fragments,"privateOpts":{"lastFragmentName":lastFragmentName,"lastFragmentPath":lastFragmentPath,"defers":defers}}
101
+ );
102
+ })()
103
+ JS
104
+
105
+ assert_equal expected, result
106
+ end
107
+
108
+ test "rendering with node array partial deferment" do
109
+ req = action_controller_test_request
110
+ req.path = '/some_url'
111
+
112
+ result = jbuild(<<-JBUILDER, request: req)
113
+ keep_first = lambda do |item|
114
+ if item[:id] == 1
115
+ false
116
+ else
117
+ :auto
118
+ end
119
+ end
120
+
121
+ json.hit do
122
+ json.hit2 do
123
+ data = [{id: 1, email: 'foo'}, {id: 2, email: 'bar'}]
124
+ json.array! data, key: :id, defer: keep_first, partial: ['record', as: :record]
125
+ end
126
+ end
127
+ JBUILDER
128
+ Rails.cache.clear
129
+
130
+ expected = strip_format(<<-JS)
131
+ (function(){
132
+ var fragments={};
133
+ var lastFragmentName;
134
+ var lastFragmentPath;
135
+ var cache={};
136
+ var defers=[];
137
+ defers.push({url:'/some_url?bzq=hit.hit2.id%3D2'});
138
+ return (
139
+ {"data":{"hit":{"hit2":[{"email":"foo"},{"id":2}]}},"screen":"test","fragments":fragments,"privateOpts":{"lastFragmentName":lastFragmentName,"lastFragmentPath":lastFragmentPath,"defers":defers}}
140
+ );
141
+ })()
142
+ JS
143
+
144
+ assert_equal expected, result
145
+ end
146
+
147
+ test "rendering with node array deferment" do
148
+ req = action_controller_test_request
149
+ req.path = '/some_url'
150
+
151
+ result = jbuild(<<-JBUILDER, request: req)
152
+ json.hit do
153
+ json.hit2 do
154
+ data = [{id: 1, name: 'foo'}, {id: 2, name: 'bar'}]
155
+ json.array! data, key: :id, defer: :auto do |item|
156
+ json.name item[:name]
157
+ end
158
+ end
159
+ end
160
+ JBUILDER
161
+ Rails.cache.clear
162
+
163
+ expected = strip_format(<<-JS)
164
+ (function(){
165
+ var fragments={};
166
+ var lastFragmentName;
167
+ var lastFragmentPath;
168
+ var cache={};
169
+ var defers=[];
170
+ defers.push({url:'/some_url?bzq=hit.hit2.id%3D1'});
171
+ defers.push({url:'/some_url?bzq=hit.hit2.id%3D2'});
172
+ return (
173
+ {"data":{"hit":{"hit2":[{"id":1},{"id":2}]}},"screen":"test","fragments":fragments,"privateOpts":{"lastFragmentName":lastFragmentName,"lastFragmentPath":lastFragmentPath,"defers":defers}}
174
+ );
175
+ })()
176
+ JS
177
+
178
+ assert_equal expected, result
179
+ end
180
+
181
+ test "rendering with node array deferment using index" do
182
+ req = action_controller_test_request
183
+ req.path = '/some_url'
184
+
185
+ result = jbuild(<<-JBUILDER, request: req)
186
+ json.hit do
187
+ json.hit2 do
188
+ data = [{id: 1, name: 'foo'}, {id: 2, name: 'bar'}]
189
+ json.array! data, defer: :auto do |item|
190
+ json.name item[:name]
191
+ end
192
+ end
193
+ end
194
+ JBUILDER
195
+ Rails.cache.clear
196
+
197
+ expected = strip_format(<<-JS)
198
+ (function(){
199
+ var fragments={};
200
+ var lastFragmentName;
201
+ var lastFragmentPath;
202
+ var cache={};
203
+ var defers=[];
204
+ defers.push({url:'/some_url?bzq=hit.hit2.0'});
205
+ defers.push({url:'/some_url?bzq=hit.hit2.1'});
206
+ return (
207
+ {"data":{"hit":{"hit2":[undefined,undefined]}},"screen":"test","fragments":fragments,"privateOpts":{"lastFragmentName":lastFragmentName,"lastFragmentPath":lastFragmentPath,"defers":defers}}
208
+ );
209
+ })()
210
+ JS
211
+
212
+ assert_equal expected, result
213
+ end
214
+
215
+ test "rendering with node array deferment on nested node" do
216
+ req = action_controller_test_request
217
+ req.path = '/some_url'
218
+
219
+ result = jbuild(<<-JBUILDER, request: req)
220
+ json.hit do
221
+ json.hit2 do
222
+ data = [{id: 1, name: 'foo'}, {id: 2, name: 'bar'}]
223
+ json.array! data, key: :id do
224
+ json.greeting defer: :auto do
225
+ json.gree 'hi'
226
+ end
227
+ end
228
+ end
229
+ end
230
+ JBUILDER
231
+ Rails.cache.clear
232
+
233
+ expected = strip_format(<<-JS)
234
+ (function(){
235
+ var fragments={};
236
+ var lastFragmentName;
237
+ var lastFragmentPath;
238
+ var cache={};
239
+ var defers=[];
240
+ defers.push({url:'/some_url?bzq=hit.hit2.id%3D1.greeting'});
241
+ defers.push({url:'/some_url?bzq=hit.hit2.id%3D2.greeting'});
242
+ return (
243
+ {"data":{"hit":{"hit2":[{"greeting":undefined},{"greeting":undefined}]}},"screen":"test","fragments":fragments,"privateOpts":{"lastFragmentName":lastFragmentName,"lastFragmentPath":lastFragmentPath,"defers":defers}}
244
+ );
245
+ })()
246
+ JS
247
+
248
+ assert_equal expected, result
249
+ end
250
+
251
+ test 'deferment does not work on values' do
252
+ undef_context_methods :fragment_name_with_digest, :cache_fragment_name
253
+
254
+ result = jbuild(<<-JBUILDER)
255
+ json.hello(32, defer: :auto)
256
+ JBUILDER
257
+
258
+ expected = strip_format(<<-JS)
259
+ (function(){
260
+ var fragments={};
261
+ var lastFragmentName;
262
+ var lastFragmentPath;
263
+ var cache={};
264
+ var defers=[];
265
+ return ({"data":{"hello":32},"screen":"test","fragments":fragments,"privateOpts":{"lastFragmentName":lastFragmentName,"lastFragmentPath":lastFragmentPath,"defers":defers}});
266
+ })()
267
+ JS
268
+
269
+ assert_equal expected, result
270
+ end
271
+
272
+ test 'deferment is disabled when filtering by keypath' do
273
+ undef_context_methods :fragment_name_with_digest, :cache_fragment_name
274
+ result = jbuild(<<-JBUILDER, breezy_filter: 'hello.world')
275
+ json.hello defer: :auto do
276
+ json.world 32
277
+ end
278
+ JBUILDER
279
+
280
+ expected = strip_format(<<-JS)
281
+ (function(){
282
+ var fragments={};
283
+ var lastFragmentName;
284
+ var lastFragmentPath;
285
+ var cache={};
286
+ var defers=[];
287
+ return ({"data":32,"screen":"test","fragments":fragments,"privateOpts":{"action":"graft","path":"hello.world","lastFragmentName":lastFragmentName,"lastFragmentPath":lastFragmentPath,"defers":defers}});
288
+ })()
289
+ JS
290
+
291
+ assert_equal expected, result
292
+
293
+ end
294
+
295
+ test 'deferment is enabled at the end of a keypath when filtering' do
296
+ undef_context_methods :fragment_name_with_digest, :cache_fragment_name
297
+ result = jbuild(<<-JBUILDER, breezy_filter: 'hello')
298
+ json.hello do
299
+ json.content defer: :auto do
300
+ json.world 32
301
+ end
302
+ end
303
+ JBUILDER
304
+
305
+ expected = strip_format(<<-JS)
306
+ (function(){
307
+ var fragments={};
308
+ var lastFragmentName;
309
+ var lastFragmentPath;
310
+ var cache={};
311
+ var defers=[];
312
+ defers.push({url:'?bzq=hello.content'});
313
+ return ({"data":{"content":undefined},"screen":"test","fragments":fragments,"privateOpts":{"action":"graft","path":"hello","lastFragmentName":lastFragmentName,"lastFragmentPath":lastFragmentPath,"defers":defers}});
314
+ })()
315
+ JS
316
+
317
+ assert_equal expected, result
318
+ end
319
+ end
320
+
321
+
322
+