jbuilder 2.7.0 → 2.11.5

Sign up to get free protection for your applications and to get access to all the features.
@@ -1,457 +1,410 @@
1
1
  require "test_helper"
2
- require "mocha/setup"
3
- require "active_model"
4
- require "action_view"
5
2
  require "action_view/testing/resolvers"
6
- require "active_support/cache"
7
- require "jbuilder/jbuilder_template"
8
-
9
- BLOG_POST_PARTIAL = <<-JBUILDER
10
- json.extract! blog_post, :id, :body
11
- json.author do
12
- first_name, last_name = blog_post.author_name.split(nil, 2)
13
- json.first_name first_name
14
- json.last_name last_name
15
- end
16
- JBUILDER
17
3
 
18
- COLLECTION_PARTIAL = <<-JBUILDER
19
- json.extract! collection, :id, :name
20
- JBUILDER
4
+ class JbuilderTemplateTest < ActiveSupport::TestCase
5
+ POST_PARTIAL = <<-JBUILDER
6
+ json.extract! post, :id, :body
7
+ json.author do
8
+ first_name, last_name = post.author_name.split(nil, 2)
9
+ json.first_name first_name
10
+ json.last_name last_name
11
+ end
12
+ JBUILDER
21
13
 
22
- RACER_PARTIAL = <<-JBUILDER
23
- json.extract! racer, :id, :name
24
- JBUILDER
14
+ COLLECTION_PARTIAL = <<-JBUILDER
15
+ json.extract! collection, :id, :name
16
+ JBUILDER
25
17
 
26
- class Racer
27
- extend ActiveModel::Naming
28
- include ActiveModel::Conversion
18
+ RACER_PARTIAL = <<-JBUILDER
19
+ json.extract! racer, :id, :name
20
+ JBUILDER
29
21
 
30
- def initialize(id, name)
31
- @id, @name = id, name
32
- end
33
-
34
- attr_reader :id, :name
35
- end
22
+ PARTIALS = {
23
+ "_partial.json.jbuilder" => "json.content content",
24
+ "_post.json.jbuilder" => POST_PARTIAL,
25
+ "racers/_racer.json.jbuilder" => RACER_PARTIAL,
26
+ "_collection.json.jbuilder" => COLLECTION_PARTIAL,
36
27
 
28
+ # Ensure we find only Jbuilder partials from within Jbuilder templates.
29
+ "_post.html.erb" => "Hello world!"
30
+ }
37
31
 
38
- BlogPost = Struct.new(:id, :body, :author_name)
39
- Collection = Struct.new(:id, :name)
40
- blog_authors = [ "David Heinemeier Hansson", "Pavel Pravosud" ].cycle
41
- BLOG_POST_COLLECTION = Array.new(10){ |i| BlogPost.new(i+1, "post body #{i+1}", blog_authors.next) }
42
- COLLECTION_COLLECTION = Array.new(5){ |i| Collection.new(i+1, "collection #{i+1}") }
32
+ AUTHORS = [ "David Heinemeier Hansson", "Pavel Pravosud" ].cycle
33
+ POSTS = (1..10).collect { |i| Post.new(i, "Post ##{i}", AUTHORS.next) }
43
34
 
44
- ActionView::Template.register_template_handler :jbuilder, JbuilderHandler
35
+ setup { Rails.cache.clear }
45
36
 
46
- PARTIALS = {
47
- "_partial.json.jbuilder" => "foo ||= 'hello'; json.content foo",
48
- "_blog_post.json.jbuilder" => BLOG_POST_PARTIAL,
49
- "racers/_racer.json.jbuilder" => RACER_PARTIAL,
50
- "_collection.json.jbuilder" => COLLECTION_PARTIAL
51
- }
37
+ test "basic template" do
38
+ result = render('json.content "hello"')
39
+ assert_equal "hello", result["content"]
40
+ end
52
41
 
53
- module Rails
54
- def self.cache
55
- @cache ||= ActiveSupport::Cache::MemoryStore.new
42
+ test "partial by name with top-level locals" do
43
+ result = render('json.partial! "partial", content: "hello"')
44
+ assert_equal "hello", result["content"]
56
45
  end
57
- end
58
46
 
59
- class JbuilderTemplateTest < ActionView::TestCase
60
- setup do
61
- @context = self
62
- Rails.cache.clear
47
+ test "partial by name with nested locals" do
48
+ result = render('json.partial! "partial", locals: { content: "hello" }')
49
+ assert_equal "hello", result["content"]
63
50
  end
64
51
 
65
- def jbuild(source, options = {})
66
- @rendered = []
67
- partials = options.fetch(:partials, PARTIALS).clone
68
- partials["test.json.jbuilder"] = source
69
- resolver = ActionView::FixtureResolver.new(partials)
70
- lookup_context.view_paths = [resolver]
71
- template = ActionView::Template.new(source, "test", JbuilderHandler, virtual_path: "test")
72
- json = template.render(self, {}).strip
73
- MultiJson.load(json)
52
+ test "partial by options containing nested locals" do
53
+ result = render('json.partial! partial: "partial", locals: { content: "hello" }')
54
+ assert_equal "hello", result["content"]
74
55
  end
75
56
 
76
- def undef_context_methods(*names)
77
- self.class_eval do
78
- names.each do |name|
79
- undef_method name.to_sym if method_defined?(name.to_sym)
80
- end
81
- end
57
+ test "partial by options containing top-level locals" do
58
+ result = render('json.partial! partial: "partial", content: "hello"')
59
+ assert_equal "hello", result["content"]
82
60
  end
83
61
 
84
- def assert_collection_rendered(result, context = nil)
85
- result = result.fetch(context) if context
62
+ test "partial for Active Model" do
63
+ result = render('json.partial! @racer', racer: Racer.new(123, "Chris Harris"))
64
+ assert_equal 123, result["id"]
65
+ assert_equal "Chris Harris", result["name"]
66
+ end
86
67
 
87
- assert_equal 10, result.length
88
- assert_equal Array, result.class
89
- assert_equal "post body 5", result[4]["body"]
68
+ test "partial collection by name with symbol local" do
69
+ result = render('json.partial! "post", collection: @posts, as: :post', posts: POSTS)
70
+ assert_equal 10, result.count
71
+ assert_equal "Post #5", result[4]["body"]
90
72
  assert_equal "Heinemeier Hansson", result[2]["author"]["last_name"]
91
- assert_equal "Pavel", result[5]["author"]["first_name"]
73
+ assert_equal "Pavel", result[5]["author"]["first_name"]
92
74
  end
93
75
 
94
- test "rendering" do
95
- result = jbuild(<<-JBUILDER)
96
- json.content "hello"
97
- JBUILDER
98
-
99
- assert_equal "hello", result["content"]
76
+ test "partial collection by name with string local" do
77
+ result = render('json.partial! "post", collection: @posts, as: "post"', posts: POSTS)
78
+ assert_equal 10, result.count
79
+ assert_equal "Post #5", result[4]["body"]
80
+ assert_equal "Heinemeier Hansson", result[2]["author"]["last_name"]
81
+ assert_equal "Pavel", result[5]["author"]["first_name"]
100
82
  end
101
83
 
102
- test "key_format! with parameter" do
103
- result = jbuild(<<-JBUILDER)
104
- json.key_format! camelize: [:lower]
105
- json.camel_style "for JS"
106
- JBUILDER
107
-
108
- assert_equal ["camelStyle"], result.keys
84
+ test "partial collection by options" do
85
+ result = render('json.partial! partial: "post", collection: @posts, as: :post', posts: POSTS)
86
+ assert_equal 10, result.count
87
+ assert_equal "Post #5", result[4]["body"]
88
+ assert_equal "Heinemeier Hansson", result[2]["author"]["last_name"]
89
+ assert_equal "Pavel", result[5]["author"]["first_name"]
109
90
  end
110
91
 
111
- test "key_format! propagates to child elements" do
112
- result = jbuild(<<-JBUILDER)
113
- json.key_format! :upcase
114
- json.level1 "one"
115
- json.level2 do
116
- json.value "two"
117
- end
118
- JBUILDER
92
+ test "nil partial collection by name" do
93
+ assert_equal [], render('json.partial! "post", collection: @posts, as: :post', posts: nil)
94
+ end
119
95
 
120
- assert_equal "one", result["LEVEL1"]
121
- assert_equal "two", result["LEVEL2"]["VALUE"]
96
+ test "nil partial collection by options" do
97
+ assert_equal [], render('json.partial! partial: "post", collection: @posts, as: :post', posts: nil)
122
98
  end
123
99
 
124
- test "partial! renders partial" do
125
- result = jbuild(<<-JBUILDER)
126
- json.partial! "partial"
127
- JBUILDER
100
+ test "array of partials" do
101
+ result = render('json.array! @posts, partial: "post", as: :post', posts: POSTS)
102
+ assert_equal 10, result.count
103
+ assert_equal "Post #5", result[4]["body"]
104
+ assert_equal "Heinemeier Hansson", result[2]["author"]["last_name"]
105
+ assert_equal "Pavel", result[5]["author"]["first_name"]
106
+ end
128
107
 
129
- assert_equal "hello", result["content"]
108
+ test "empty array of partials from nil collection" do
109
+ assert_equal [], render('json.array! @posts, partial: "post", as: :post', posts: nil)
130
110
  end
131
111
 
132
- test "partial! + locals via :locals option" do
133
- result = jbuild(<<-JBUILDER)
134
- json.partial! "partial", locals: { foo: "howdy" }
135
- JBUILDER
112
+ test "array of partials under key" do
113
+ result = render('json.posts @posts, partial: "post", as: :post', posts: POSTS)
114
+ assert_equal 10, result["posts"].count
115
+ assert_equal "Post #5", result["posts"][4]["body"]
116
+ assert_equal "Heinemeier Hansson", result["posts"][2]["author"]["last_name"]
117
+ assert_equal "Pavel", result["posts"][5]["author"]["first_name"]
118
+ end
136
119
 
137
- assert_equal "howdy", result["content"]
120
+ test "empty array of partials under key from nil collection" do
121
+ result = render('json.posts @posts, partial: "post", as: :post', posts: nil)
122
+ assert_equal [], result["posts"]
138
123
  end
139
124
 
140
- test "partial! + locals without :locals key" do
141
- result = jbuild(<<-JBUILDER)
142
- json.partial! "partial", foo: "goodbye"
125
+ test "object fragment caching" do
126
+ render(<<-JBUILDER)
127
+ json.cache! "cache-key" do
128
+ json.name "Hit"
129
+ end
143
130
  JBUILDER
144
131
 
145
- assert_equal "goodbye", result["content"]
132
+ hit = render('json.cache! "cache-key" do; end')
133
+ assert_equal "Hit", hit["name"]
146
134
  end
147
135
 
148
- test "partial! renders collections" do
149
- result = jbuild(<<-JBUILDER)
150
- json.partial! "blog_post", collection: BLOG_POST_COLLECTION, as: :blog_post
136
+ test "conditional object fragment caching" do
137
+ render(<<-JBUILDER)
138
+ json.cache_if! true, "cache-key" do
139
+ json.a "Hit"
140
+ end
141
+
142
+ json.cache_if! false, "cache-key" do
143
+ json.b "Hit"
144
+ end
151
145
  JBUILDER
152
146
 
153
- assert_collection_rendered result
154
- end
147
+ result = render(<<-JBUILDER)
148
+ json.cache_if! true, "cache-key" do
149
+ json.a "Miss"
150
+ end
155
151
 
156
- test "partial! renders collections when as argument is a string" do
157
- result = jbuild(<<-JBUILDER)
158
- json.partial! "blog_post", collection: BLOG_POST_COLLECTION, as: "blog_post"
152
+ json.cache_if! false, "cache-key" do
153
+ json.b "Miss"
154
+ end
159
155
  JBUILDER
160
156
 
161
- assert_collection_rendered result
157
+ assert_equal "Hit", result["a"]
158
+ assert_equal "Miss", result["b"]
162
159
  end
163
160
 
164
- test "partial! renders collections as collections" do
165
- result = jbuild(<<-JBUILDER)
166
- json.partial! "collection", collection: COLLECTION_COLLECTION, as: :collection
161
+ test "object fragment caching with expiry" do
162
+ travel_to Time.iso8601("2018-05-12T11:29:00-04:00")
163
+
164
+ render <<-JBUILDER
165
+ json.cache! "cache-key", expires_in: 1.minute do
166
+ json.name "Hit"
167
+ end
167
168
  JBUILDER
168
169
 
169
- assert_equal 5, result.length
170
- end
170
+ travel 30.seconds
171
171
 
172
- test "partial! renders as empty array for nil-collection" do
173
- result = jbuild(<<-JBUILDER)
174
- json.partial! "blog_post", collection: nil, as: :blog_post
172
+ result = render(<<-JBUILDER)
173
+ json.cache! "cache-key", expires_in: 1.minute do
174
+ json.name "Miss"
175
+ end
175
176
  JBUILDER
176
177
 
177
- assert_equal [], result
178
- end
178
+ assert_equal "Hit", result["name"]
179
+
180
+ travel 31.seconds
179
181
 
180
- test "partial! renders collection (alt. syntax)" do
181
- result = jbuild(<<-JBUILDER)
182
- json.partial! partial: "blog_post", collection: BLOG_POST_COLLECTION, as: :blog_post
182
+ result = render(<<-JBUILDER)
183
+ json.cache! "cache-key", expires_in: 1.minute do
184
+ json.name "Miss"
185
+ end
183
186
  JBUILDER
184
187
 
185
- assert_collection_rendered result
188
+ assert_equal "Miss", result["name"]
186
189
  end
187
190
 
188
- test "partial! renders as empty array for nil-collection (alt. syntax)" do
189
- result = jbuild(<<-JBUILDER)
190
- json.partial! partial: "blog_post", collection: nil, as: :blog_post
191
+ test "object root caching" do
192
+ render <<-JBUILDER
193
+ json.cache_root! "cache-key" do
194
+ json.name "Hit"
195
+ end
191
196
  JBUILDER
192
197
 
193
- assert_equal [], result
194
- end
198
+ assert_equal JSON.dump(name: "Hit"), Rails.cache.read("jbuilder/root/cache-key")
195
199
 
196
- test "render array of partials" do
197
- result = jbuild(<<-JBUILDER)
198
- json.array! BLOG_POST_COLLECTION, partial: "blog_post", as: :blog_post
200
+ result = render(<<-JBUILDER)
201
+ json.cache_root! "cache-key" do
202
+ json.name "Miss"
203
+ end
199
204
  JBUILDER
200
205
 
201
- assert_collection_rendered result
206
+ assert_equal "Hit", result["name"]
202
207
  end
203
208
 
204
- test "render array of partials as empty array with nil-collection" do
205
- result = jbuild(<<-JBUILDER)
206
- json.array! nil, partial: "blog_post", as: :blog_post
209
+ test "array fragment caching" do
210
+ render <<-JBUILDER
211
+ json.cache! "cache-key" do
212
+ json.array! %w[ a b c ]
213
+ end
207
214
  JBUILDER
208
215
 
209
- assert_equal [], result
216
+ assert_equal %w[ a b c ], render('json.cache! "cache-key" do; end')
210
217
  end
211
218
 
212
- test "render array of partials as a value" do
213
- result = jbuild(<<-JBUILDER)
214
- json.posts BLOG_POST_COLLECTION, partial: "blog_post", as: :blog_post
219
+ test "array root caching" do
220
+ render <<-JBUILDER
221
+ json.cache_root! "cache-key" do
222
+ json.array! %w[ a b c ]
223
+ end
215
224
  JBUILDER
216
225
 
217
- assert_collection_rendered result, "posts"
218
- end
226
+ assert_equal JSON.dump(%w[ a b c ]), Rails.cache.read("jbuilder/root/cache-key")
219
227
 
220
- test "render as empty array if partials as a nil value" do
221
- result = jbuild <<-JBUILDER
222
- json.posts nil, partial: "blog_post", as: :blog_post
228
+ assert_equal %w[ a b c ], render(<<-JBUILDER)
229
+ json.cache_root! "cache-key" do
230
+ json.array! %w[ d e f ]
231
+ end
223
232
  JBUILDER
224
-
225
- assert_equal [], result["posts"]
226
233
  end
227
234
 
228
- test "cache an empty block" do
229
- undef_context_methods :fragment_name_with_digest, :cache_fragment_name
235
+ test "failing to cache root after JSON structures have been defined" do
236
+ assert_raises ActionView::Template::Error, "cache_root! can't be used after JSON structures have been defined" do
237
+ render <<-JBUILDER
238
+ json.name "Kaboom"
239
+ json.cache_root! "cache-key" do
240
+ json.name "Miss"
241
+ end
242
+ JBUILDER
243
+ end
244
+ end
230
245
 
231
- jbuild <<-JBUILDER
232
- json.cache! "nothing" do
233
- end
234
- JBUILDER
246
+ test "empty fragment caching" do
247
+ render 'json.cache! "nothing" do; end'
235
248
 
236
249
  result = nil
237
250
 
238
251
  assert_nothing_raised do
239
- result = jbuild(<<-JBUILDER)
252
+ result = render(<<-JBUILDER)
240
253
  json.foo "bar"
241
- json.cache! "nothing" do
242
- end
254
+ json.cache! "nothing" do; end
243
255
  JBUILDER
244
256
  end
245
257
 
246
258
  assert_equal "bar", result["foo"]
247
259
  end
248
260
 
249
- test "fragment caching a JSON object" do
250
- undef_context_methods :fragment_name_with_digest, :cache_fragment_name
261
+ test "cache instrumentation" do
262
+ payloads = {}
251
263
 
252
- jbuild <<-JBUILDER
253
- json.cache! "cachekey" do
254
- json.name "Cache"
255
- end
256
- JBUILDER
264
+ ActiveSupport::Notifications.subscribe("read_fragment.action_controller") { |*args| payloads[:read] = args.last }
265
+ ActiveSupport::Notifications.subscribe("write_fragment.action_controller") { |*args| payloads[:write] = args.last }
257
266
 
258
- result = jbuild(<<-JBUILDER)
259
- json.cache! "cachekey" do
260
- json.name "Miss"
267
+ render <<-JBUILDER
268
+ json.cache! "cache-key" do
269
+ json.name "Cache"
261
270
  end
262
271
  JBUILDER
263
272
 
264
- assert_equal "Cache", result["name"]
273
+ assert_equal "jbuilder/cache-key", payloads[:read][:key]
274
+ assert_equal "jbuilder/cache-key", payloads[:write][:key]
265
275
  end
266
276
 
267
- test "conditionally fragment caching a JSON object" do
268
- undef_context_methods :fragment_name_with_digest, :cache_fragment_name
269
-
270
- jbuild <<-JBUILDER
271
- json.cache_if! true, "cachekey" do
272
- json.test1 "Cache"
273
- end
274
- json.cache_if! false, "cachekey" do
275
- json.test2 "Cache"
276
- end
277
- JBUILDER
278
-
279
- result = jbuild(<<-JBUILDER)
280
- json.cache_if! true, "cachekey" do
281
- json.test1 "Miss"
282
- end
283
- json.cache_if! false, "cachekey" do
284
- json.test2 "Miss"
285
- end
277
+ test "camelized keys" do
278
+ result = render(<<-JBUILDER)
279
+ json.key_format! camelize: [:lower]
280
+ json.first_name "David"
286
281
  JBUILDER
287
282
 
288
- assert_equal "Cache", result["test1"]
289
- assert_equal "Miss", result["test2"]
283
+ assert_equal "David", result["firstName"]
290
284
  end
291
285
 
292
- test "fragment caching deserializes an array" do
293
- undef_context_methods :fragment_name_with_digest, :cache_fragment_name
286
+ if JbuilderTemplate::CollectionRenderer.supported?
287
+ test "returns an empty array for an empty collection" do
288
+ result = render('json.array! @posts, partial: "post", as: :post, cached: true', posts: [])
294
289
 
295
- jbuild <<-JBUILDER
296
- json.cache! "cachekey" do
297
- json.array! %w[a b c]
298
- end
299
- JBUILDER
300
-
301
- result = jbuild(<<-JBUILDER)
302
- json.cache! "cachekey" do
303
- json.array! %w[1 2 3]
304
- end
305
- JBUILDER
306
-
307
- assert_equal %w[a b c], result
308
- end
309
-
310
- test "fragment caching works with current cache digests" do
311
- undef_context_methods :fragment_name_with_digest
290
+ # Do not use #assert_empty as it is important to ensure that the type of the JSON result is an array.
291
+ assert_equal [], result
292
+ end
312
293
 
313
- @context.expects :cache_fragment_name
314
- ActiveSupport::Cache.expects :expand_cache_key
294
+ test "works with an enumerable object" do
295
+ enumerable_class = Class.new do
296
+ include Enumerable
297
+ alias length count # Rails 6.1 requires this.
315
298
 
316
- jbuild <<-JBUILDER
317
- json.cache! "cachekey" do
318
- json.name "Cache"
299
+ def each(&block)
300
+ [].each(&block)
301
+ end
319
302
  end
320
- JBUILDER
321
- end
322
303
 
323
- test "fragment caching uses fragment_cache_key" do
324
- undef_context_methods :fragment_name_with_digest, :cache_fragment_name
304
+ result = render('json.array! @posts, partial: "post", as: :post, cached: true', posts: enumerable_class.new)
325
305
 
326
- @context.expects(:fragment_cache_key).with("cachekey")
306
+ # Do not use #assert_empty as it is important to ensure that the type of the JSON result is an array.
307
+ assert_equal [], result
308
+ end
327
309
 
328
- jbuild <<-JBUILDER
329
- json.cache! "cachekey" do
330
- json.name "Cache"
331
- end
332
- JBUILDER
333
- end
310
+ test "supports the cached: true option" do
311
+ result = render('json.array! @posts, partial: "post", as: :post, cached: true', posts: POSTS)
334
312
 
335
- test "fragment caching instrumentation" do
336
- undef_context_methods :fragment_name_with_digest, :cache_fragment_name
313
+ assert_equal 10, result.count
314
+ assert_equal "Post #5", result[4]["body"]
315
+ assert_equal "Heinemeier Hansson", result[2]["author"]["last_name"]
316
+ assert_equal "Pavel", result[5]["author"]["first_name"]
337
317
 
338
- payloads = {}
339
- ActiveSupport::Notifications.subscribe("read_fragment.action_controller") { |*args| payloads[:read_fragment] = args.last }
340
- ActiveSupport::Notifications.subscribe("write_fragment.action_controller") { |*args| payloads[:write_fragment] = args.last }
318
+ expected = {
319
+ "id" => 1,
320
+ "body" => "Post #1",
321
+ "author" => {
322
+ "first_name" => "David",
323
+ "last_name" => "Heinemeier Hansson"
324
+ }
325
+ }
341
326
 
342
- jbuild <<-JBUILDER
343
- json.cache! "cachekey" do
344
- json.name "Cache"
345
- end
346
- JBUILDER
327
+ assert_equal expected, Rails.cache.read("post-1")
347
328
 
348
- assert_equal "jbuilder/cachekey", payloads[:read_fragment][:key]
349
- assert_equal "jbuilder/cachekey", payloads[:write_fragment][:key]
350
- end
329
+ result = render('json.array! @posts, partial: "post", as: :post, cached: true', posts: POSTS)
351
330
 
352
- test "current cache digest option accepts options" do
353
- undef_context_methods :fragment_name_with_digest
331
+ assert_equal 10, result.count
332
+ assert_equal "Post #5", result[4]["body"]
333
+ assert_equal "Heinemeier Hansson", result[2]["author"]["last_name"]
334
+ assert_equal "Pavel", result[5]["author"]["first_name"]
335
+ end
354
336
 
355
- @context.expects(:cache_fragment_name).with("cachekey", skip_digest: true)
356
- ActiveSupport::Cache.expects :expand_cache_key
337
+ test "supports the cached: ->() {} option" do
338
+ result = render('json.array! @posts, partial: "post", as: :post, cached: ->(post) { [post, "foo"] }', posts: POSTS)
357
339
 
358
- jbuild <<-JBUILDER
359
- json.cache! "cachekey", skip_digest: true do
360
- json.name "Cache"
361
- end
362
- JBUILDER
363
- end
340
+ assert_equal 10, result.count
341
+ assert_equal "Post #5", result[4]["body"]
342
+ assert_equal "Heinemeier Hansson", result[2]["author"]["last_name"]
343
+ assert_equal "Pavel", result[5]["author"]["first_name"]
364
344
 
365
- test "fragment caching accepts expires_in option" do
366
- undef_context_methods :fragment_name_with_digest
345
+ expected = {
346
+ "id" => 1,
347
+ "body" => "Post #1",
348
+ "author" => {
349
+ "first_name" => "David",
350
+ "last_name" => "Heinemeier Hansson"
351
+ }
352
+ }
367
353
 
368
- @context.expects(:cache_fragment_name).with("cachekey", {})
354
+ assert_equal expected, Rails.cache.read("post-1/foo")
369
355
 
370
- jbuild <<-JBUILDER
371
- json.cache! "cachekey", expires_in: 1.minute do
372
- json.name "Cache"
373
- end
374
- JBUILDER
375
- end
356
+ result = render('json.array! @posts, partial: "post", as: :post, cached: ->(post) { [post, "foo"] }', posts: POSTS)
376
357
 
377
- test "caching root structure" do
378
- undef_context_methods :fragment_name_with_digest, :cache_fragment_name
379
-
380
- cache_miss_result = jbuild <<-JBUILDER
381
- json.cache_root! "cachekey" do
382
- json.name "Miss"
383
- end
384
- JBUILDER
358
+ assert_equal 10, result.count
359
+ assert_equal "Post #5", result[4]["body"]
360
+ assert_equal "Heinemeier Hansson", result[2]["author"]["last_name"]
361
+ assert_equal "Pavel", result[5]["author"]["first_name"]
362
+ end
385
363
 
386
- cache_hit_result = jbuild <<-JBUILDER
387
- json.cache_root! "cachekey" do
388
- json.name "Hit"
364
+ test "raises an error on a render call with the :layout option" do
365
+ error = assert_raises NotImplementedError do
366
+ render('json.array! @posts, partial: "post", as: :post, layout: "layout"', posts: POSTS)
389
367
  end
390
- JBUILDER
391
368
 
392
- assert_equal cache_miss_result, cache_hit_result
393
- end
394
-
395
- test "failing to cache root after attributes have been defined" do
396
- assert_raises ActionView::Template::Error, "cache_root! can't be used after JSON structures have been defined" do
397
- jbuild <<-JBUILDER
398
- json.name "Kaboom"
399
- json.cache_root! "cachekey" do
400
- json.name "Miss"
401
- end
402
- JBUILDER
369
+ assert_equal "The `:layout' option is not supported in collection rendering.", error.message
403
370
  end
404
- end
405
-
406
- test "does not perform caching when controller.perform_caching is false" do
407
- controller.perform_caching = false
408
371
 
409
- jbuild <<-JBUILDER
410
- json.cache! "cachekey" do
411
- json.name "Cache"
372
+ test "raises an error on a render call with the :spacer_template option" do
373
+ error = assert_raises NotImplementedError do
374
+ render('json.array! @posts, partial: "post", as: :post, spacer_template: "template"', posts: POSTS)
412
375
  end
413
- JBUILDER
414
-
415
- assert_equal Rails.cache.inspect[/entries=(\d+)/, 1], "0"
416
- end
417
-
418
- test "invokes templates via params via set!" do
419
- @post = BLOG_POST_COLLECTION.first
420
376
 
421
- result = jbuild(<<-JBUILDER)
422
- json.post @post, partial: "blog_post", as: :blog_post
423
- JBUILDER
424
-
425
- assert_equal 1, result["post"]["id"]
426
- assert_equal "post body 1", result["post"]["body"]
427
- assert_equal "David", result["post"]["author"]["first_name"]
377
+ assert_equal "The `:spacer_template' option is not supported in collection rendering.", error.message
378
+ end
428
379
  end
429
380
 
430
- test "invokes templates implicitly for ActiveModel objects" do
431
- @racer = Racer.new(123, "Chris Harris")
432
-
433
- result = jbuild(<<-JBUILDER)
434
- json.partial! @racer
435
- JBUILDER
381
+ private
382
+ def render(*args)
383
+ JSON.load render_without_parsing(*args)
384
+ end
436
385
 
437
- assert_equal %w[id name], result.keys
438
- assert_equal 123, result["id"]
439
- assert_equal "Chris Harris", result["name"]
440
- end
386
+ def render_without_parsing(source, assigns = {})
387
+ view = build_view(fixtures: PARTIALS.merge("source.json.jbuilder" => source), assigns: assigns)
388
+ view.render(template: "source")
389
+ end
441
390
 
442
- test "renders partial via set! with same name as HTML partial" do
443
- partials = {
444
- "_blog_post.html.erb" => "Hello!",
445
- "_blog_post.json.jbuilder" => BLOG_POST_PARTIAL
446
- }
391
+ def build_view(options = {})
392
+ resolver = ActionView::FixtureResolver.new(options.fetch(:fixtures))
393
+ lookup_context = ActionView::LookupContext.new([ resolver ], {}, [""])
394
+ controller = ActionView::TestCase::TestController.new
447
395
 
448
- @post = BLOG_POST_COLLECTION.first
396
+ # TODO: Use with_empty_template_cache unconditionally after dropping support for Rails <6.0.
397
+ view = if ActionView::Base.respond_to?(:with_empty_template_cache)
398
+ ActionView::Base.with_empty_template_cache.new(lookup_context, options.fetch(:assigns, {}), controller)
399
+ else
400
+ ActionView::Base.new(lookup_context, options.fetch(:assigns, {}), controller)
401
+ end
449
402
 
450
- result = jbuild(<<-JBUILDER, partials: partials)
451
- json.post @post, partial: "blog_post", as: :blog_post
452
- JBUILDER
403
+ def view.view_cache_dependencies; []; end
404
+ def view.combined_fragment_cache_key(key) [ key ] end
405
+ def view.cache_fragment_name(key, *) key end
406
+ def view.fragment_name_with_digest(key) key end
453
407
 
454
- assert_not_nil result["post"]
455
- assert_equal 1, result["post"]["id"]
456
- end
408
+ view
409
+ end
457
410
  end