actionpack 2.1.2 → 2.2.2

Sign up to get free protection for your applications and to get access to all the features.

Potentially problematic release.


This version of actionpack might be problematic. Click here for more details.

Files changed (200) hide show
  1. data/CHANGELOG +223 -7
  2. data/README +6 -12
  3. data/Rakefile +11 -11
  4. data/lib/action_controller.rb +9 -9
  5. data/lib/action_controller/assertions/response_assertions.rb +29 -78
  6. data/lib/action_controller/assertions/routing_assertions.rb +33 -33
  7. data/lib/action_controller/assertions/selector_assertions.rb +9 -5
  8. data/lib/action_controller/base.rb +227 -161
  9. data/lib/action_controller/benchmarking.rb +37 -24
  10. data/lib/action_controller/caching/actions.rb +53 -21
  11. data/lib/action_controller/caching/fragments.rb +10 -36
  12. data/lib/action_controller/caching/sweeping.rb +3 -3
  13. data/lib/action_controller/cgi_ext/session.rb +2 -22
  14. data/lib/action_controller/cgi_process.rb +8 -46
  15. data/lib/action_controller/components.rb +4 -1
  16. data/lib/action_controller/cookies.rb +10 -0
  17. data/lib/action_controller/dispatcher.rb +49 -15
  18. data/lib/action_controller/filters.rb +48 -10
  19. data/lib/action_controller/headers.rb +16 -14
  20. data/lib/action_controller/helpers.rb +2 -2
  21. data/lib/action_controller/http_authentication.rb +1 -1
  22. data/lib/action_controller/integration.rb +57 -60
  23. data/lib/action_controller/layout.rb +27 -53
  24. data/lib/action_controller/mime_responds.rb +5 -1
  25. data/lib/action_controller/mime_type.rb +64 -42
  26. data/lib/action_controller/mime_types.rb +2 -1
  27. data/lib/action_controller/performance_test.rb +16 -0
  28. data/lib/action_controller/polymorphic_routes.rb +16 -9
  29. data/lib/action_controller/rack_process.rb +303 -0
  30. data/lib/action_controller/request.rb +205 -97
  31. data/lib/action_controller/request_forgery_protection.rb +2 -2
  32. data/lib/action_controller/request_profiler.rb +0 -0
  33. data/lib/action_controller/rescue.rb +20 -115
  34. data/lib/action_controller/resources.rb +186 -83
  35. data/lib/action_controller/response.rb +140 -26
  36. data/lib/action_controller/routing.rb +28 -30
  37. data/lib/action_controller/routing/builder.rb +45 -54
  38. data/lib/action_controller/routing/optimisations.rb +31 -21
  39. data/lib/action_controller/routing/recognition_optimisation.rb +33 -27
  40. data/lib/action_controller/routing/route.rb +162 -147
  41. data/lib/action_controller/routing/route_set.rb +8 -7
  42. data/lib/action_controller/routing/routing_ext.rb +4 -1
  43. data/lib/action_controller/routing/segments.rb +50 -21
  44. data/lib/action_controller/session/cookie_store.rb +3 -2
  45. data/lib/action_controller/session/drb_server.rb +7 -7
  46. data/lib/action_controller/session_management.rb +6 -2
  47. data/lib/action_controller/streaming.rb +15 -8
  48. data/lib/action_controller/templates/rescues/diagnostics.erb +2 -2
  49. data/lib/action_controller/templates/rescues/template_error.erb +2 -2
  50. data/lib/action_controller/test_case.rb +66 -2
  51. data/lib/action_controller/test_process.rb +71 -66
  52. data/lib/action_controller/translation.rb +13 -0
  53. data/lib/action_controller/url_rewriter.rb +90 -13
  54. data/lib/action_controller/vendor/html-scanner/html/node.rb +9 -2
  55. data/lib/action_controller/vendor/html-scanner/html/sanitizer.rb +1 -1
  56. data/lib/action_controller/vendor/html-scanner/html/selector.rb +2 -2
  57. data/lib/action_controller/verification.rb +2 -2
  58. data/lib/action_pack/version.rb +1 -1
  59. data/lib/action_view.rb +19 -11
  60. data/lib/action_view/base.rb +184 -150
  61. data/lib/action_view/helpers.rb +38 -0
  62. data/lib/action_view/helpers/active_record_helper.rb +56 -27
  63. data/lib/action_view/helpers/asset_tag_helper.rb +356 -153
  64. data/lib/action_view/helpers/atom_feed_helper.rb +74 -19
  65. data/lib/action_view/helpers/benchmark_helper.rb +3 -3
  66. data/lib/action_view/helpers/cache_helper.rb +1 -2
  67. data/lib/action_view/helpers/capture_helper.rb +19 -44
  68. data/lib/action_view/helpers/date_helper.rb +486 -296
  69. data/lib/action_view/helpers/debug_helper.rb +20 -13
  70. data/lib/action_view/helpers/form_helper.rb +71 -30
  71. data/lib/action_view/helpers/form_options_helper.rb +15 -85
  72. data/lib/action_view/helpers/form_tag_helper.rb +61 -38
  73. data/lib/action_view/helpers/javascript_helper.rb +80 -89
  74. data/lib/action_view/helpers/number_helper.rb +179 -74
  75. data/lib/action_view/helpers/prototype_helper.rb +216 -201
  76. data/lib/action_view/helpers/record_tag_helper.rb +4 -5
  77. data/lib/action_view/helpers/sanitize_helper.rb +65 -33
  78. data/lib/action_view/helpers/scriptaculous_helper.rb +2 -2
  79. data/lib/action_view/helpers/tag_helper.rb +39 -22
  80. data/lib/action_view/helpers/text_helper.rb +212 -118
  81. data/lib/action_view/helpers/translation_helper.rb +21 -0
  82. data/lib/action_view/helpers/url_helper.rb +100 -58
  83. data/lib/action_view/inline_template.rb +13 -14
  84. data/lib/action_view/locale/en.yml +91 -0
  85. data/lib/action_view/partials.rb +100 -55
  86. data/lib/action_view/paths.rb +125 -0
  87. data/lib/action_view/renderable.rb +102 -0
  88. data/lib/action_view/renderable_partial.rb +48 -0
  89. data/lib/action_view/template.rb +90 -101
  90. data/lib/action_view/template_error.rb +11 -21
  91. data/lib/action_view/template_handler.rb +8 -28
  92. data/lib/action_view/template_handlers.rb +45 -0
  93. data/lib/action_view/template_handlers/builder.rb +5 -15
  94. data/lib/action_view/template_handlers/erb.rb +9 -6
  95. data/lib/action_view/template_handlers/rjs.rb +2 -17
  96. data/lib/action_view/test_case.rb +7 -4
  97. data/test/abstract_unit.rb +4 -1
  98. data/test/active_record_unit.rb +28 -30
  99. data/test/activerecord/render_partial_with_record_identification_test.rb +25 -12
  100. data/test/controller/action_pack_assertions_test.rb +8 -37
  101. data/test/controller/addresses_render_test.rb +0 -3
  102. data/test/controller/assert_select_test.rb +51 -24
  103. data/test/controller/base_test.rb +4 -4
  104. data/test/controller/caching_test.rb +136 -66
  105. data/test/controller/capture_test.rb +1 -21
  106. data/test/controller/cgi_test.rb +157 -10
  107. data/test/controller/components_test.rb +41 -25
  108. data/test/controller/content_type_test.rb +49 -17
  109. data/test/controller/cookie_test.rb +1 -1
  110. data/test/controller/deprecation/deprecated_base_methods_test.rb +0 -3
  111. data/test/controller/dispatcher_test.rb +9 -1
  112. data/test/controller/filter_params_test.rb +2 -2
  113. data/test/controller/filters_test.rb +13 -13
  114. data/test/controller/html-scanner/cdata_node_test.rb +15 -0
  115. data/test/controller/html-scanner/node_test.rb +21 -0
  116. data/test/controller/html-scanner/sanitizer_test.rb +14 -0
  117. data/test/controller/integration_test.rb +167 -6
  118. data/test/controller/layout_test.rb +11 -68
  119. data/test/controller/logging_test.rb +46 -0
  120. data/test/controller/mime_responds_test.rb +61 -59
  121. data/test/controller/mime_type_test.rb +6 -6
  122. data/test/controller/polymorphic_routes_test.rb +37 -2
  123. data/test/controller/rack_test.rb +323 -0
  124. data/test/controller/redirect_test.rb +72 -71
  125. data/test/controller/render_test.rb +1120 -108
  126. data/test/controller/request_forgery_protection_test.rb +66 -52
  127. data/test/controller/request_test.rb +103 -146
  128. data/test/controller/rescue_test.rb +20 -24
  129. data/test/controller/resources_test.rb +408 -25
  130. data/test/controller/routing_test.rb +1774 -1774
  131. data/test/controller/send_file_test.rb +0 -4
  132. data/test/controller/session/cookie_store_test.rb +53 -1
  133. data/test/controller/test_test.rb +15 -37
  134. data/test/controller/translation_test.rb +26 -0
  135. data/test/controller/url_rewriter_test.rb +27 -28
  136. data/test/controller/view_paths_test.rb +48 -47
  137. data/test/fixtures/_top_level_partial.html.erb +1 -0
  138. data/test/fixtures/_top_level_partial_only.erb +1 -0
  139. data/test/fixtures/developers/_developer.erb +1 -0
  140. data/test/fixtures/fun/games/_game.erb +1 -0
  141. data/test/fixtures/fun/serious/games/_game.erb +1 -0
  142. data/test/fixtures/functional_caching/formatted_fragment_cached.html.erb +3 -0
  143. data/test/fixtures/functional_caching/formatted_fragment_cached.js.rjs +6 -0
  144. data/test/fixtures/functional_caching/formatted_fragment_cached.xml.builder +5 -0
  145. data/test/fixtures/functional_caching/inline_fragment_cached.html.erb +2 -0
  146. data/test/fixtures/layouts/_column.html.erb +2 -0
  147. data/test/fixtures/projects/_project.erb +1 -0
  148. data/test/fixtures/public/javascripts/subdir/subdir.js +1 -0
  149. data/test/fixtures/public/stylesheets/subdir/subdir.css +1 -0
  150. data/test/fixtures/replies/_reply.erb +1 -0
  151. data/test/fixtures/test/_counter.html.erb +1 -0
  152. data/test/fixtures/test/_customer.erb +1 -1
  153. data/test/fixtures/test/_customer_with_var.erb +1 -0
  154. data/test/fixtures/test/_layout_for_block_with_args.html.erb +3 -0
  155. data/test/fixtures/test/_local_inspector.html.erb +1 -0
  156. data/test/fixtures/test/_partial_with_only_html_version.html.erb +1 -0
  157. data/test/fixtures/test/hello.builder +1 -1
  158. data/test/fixtures/test/hyphen-ated.erb +1 -0
  159. data/test/fixtures/test/implicit_content_type.atom.builder +2 -0
  160. data/test/fixtures/test/nested_layout.erb +3 -0
  161. data/test/fixtures/test/non_erb_block_content_for.builder +1 -1
  162. data/test/fixtures/test/sub_template_raise.html.erb +1 -0
  163. data/test/fixtures/test/template.erb +1 -0
  164. data/test/fixtures/test/using_layout_around_block_with_args.html.erb +1 -0
  165. data/test/template/active_record_helper_i18n_test.rb +46 -0
  166. data/test/template/active_record_helper_test.rb +24 -24
  167. data/test/template/asset_tag_helper_test.rb +161 -29
  168. data/test/template/atom_feed_helper_test.rb +114 -5
  169. data/test/template/compiled_templates_test.rb +59 -0
  170. data/test/template/date_helper_i18n_test.rb +113 -0
  171. data/test/template/date_helper_test.rb +403 -109
  172. data/test/template/form_helper_test.rb +213 -154
  173. data/test/template/form_options_helper_test.rb +249 -897
  174. data/test/template/form_tag_helper_test.rb +80 -32
  175. data/test/template/javascript_helper_test.rb +17 -18
  176. data/test/template/number_helper_i18n_test.rb +54 -0
  177. data/test/template/number_helper_test.rb +43 -13
  178. data/test/template/prototype_helper_test.rb +101 -84
  179. data/test/template/record_tag_helper_test.rb +24 -20
  180. data/test/template/render_test.rb +193 -0
  181. data/test/template/sanitize_helper_test.rb +3 -3
  182. data/test/template/tag_helper_test.rb +34 -14
  183. data/test/template/text_helper_test.rb +83 -9
  184. data/test/template/translation_helper_test.rb +28 -0
  185. data/test/template/url_helper_test.rb +55 -18
  186. metadata +57 -18
  187. data/lib/action_view/helpers/javascripts/controls.js +0 -963
  188. data/lib/action_view/helpers/javascripts/dragdrop.js +0 -972
  189. data/lib/action_view/helpers/javascripts/effects.js +0 -1120
  190. data/lib/action_view/helpers/javascripts/prototype.js +0 -4225
  191. data/lib/action_view/partial_template.rb +0 -70
  192. data/lib/action_view/template_finder.rb +0 -177
  193. data/lib/action_view/template_handlers/compilable.rb +0 -128
  194. data/test/controller/custom_handler_test.rb +0 -45
  195. data/test/controller/new_render_test.rb +0 -945
  196. data/test/fixtures/test/block_content_for.erb +0 -2
  197. data/test/fixtures/test/erb_content_for.erb +0 -2
  198. data/test/template/deprecated_erb_variable_test.rb +0 -9
  199. data/test/template/template_finder_test.rb +0 -73
  200. data/test/template/template_object_test.rb +0 -95
@@ -8,26 +8,64 @@ module Fun
8
8
  end
9
9
  end
10
10
 
11
+ class MockLogger
12
+ attr_reader :logged
13
+
14
+ def initialize
15
+ @logged = []
16
+ end
17
+
18
+ def method_missing(method, *args)
19
+ @logged << args.first
20
+ end
21
+ end
11
22
 
12
- # FIXME: crashes Ruby 1.9
13
23
  class TestController < ActionController::Base
24
+ class LabellingFormBuilder < ActionView::Helpers::FormBuilder
25
+ end
26
+
14
27
  layout :determine_layout
15
28
 
16
29
  def hello_world
17
30
  end
18
31
 
32
+ def conditional_hello
33
+ if stale?(:last_modified => Time.now.utc.beginning_of_day, :etag => [:foo, 123])
34
+ render :action => 'hello_world'
35
+ end
36
+ end
37
+
38
+ def conditional_hello_with_bangs
39
+ render :action => 'hello_world'
40
+ end
41
+ before_filter :handle_last_modified_and_etags, :only=>:conditional_hello_with_bangs
42
+
43
+ def handle_last_modified_and_etags
44
+ fresh_when(:last_modified => Time.now.utc.beginning_of_day, :etag => [ :foo, 123 ])
45
+ end
46
+
19
47
  def render_hello_world
20
48
  render :template => "test/hello_world"
21
49
  end
22
50
 
51
+ def render_hello_world_with_last_modified_set
52
+ response.last_modified = Date.new(2008, 10, 10).to_time
53
+ render :template => "test/hello_world"
54
+ end
55
+
56
+ def render_hello_world_with_etag_set
57
+ response.etag = "hello_world"
58
+ render :template => "test/hello_world"
59
+ end
60
+
23
61
  def render_hello_world_with_forward_slash
24
62
  render :template => "/test/hello_world"
25
63
  end
26
-
64
+
27
65
  def render_template_in_top_directory
28
66
  render :template => 'shared'
29
67
  end
30
-
68
+
31
69
  def render_template_in_top_directory_with_slash
32
70
  render :template => '/shared'
33
71
  end
@@ -49,6 +87,57 @@ class TestController < ActionController::Base
49
87
  render :text => "hello world"
50
88
  end
51
89
 
90
+ def render_text_hello_world_with_layout
91
+ @variable_for_layout = ", I'm here!"
92
+ render :text => "hello world", :layout => true
93
+ end
94
+
95
+ def hello_world_with_layout_false
96
+ render :layout => false
97
+ end
98
+
99
+ def render_file_with_instance_variables
100
+ @secret = 'in the sauce'
101
+ path = File.join(File.dirname(__FILE__), '../fixtures/test/render_file_with_ivar.erb')
102
+ render :file => path
103
+ end
104
+
105
+ def render_file_not_using_full_path
106
+ @secret = 'in the sauce'
107
+ render :file => 'test/render_file_with_ivar'
108
+ end
109
+
110
+ def render_file_not_using_full_path_with_dot_in_path
111
+ @secret = 'in the sauce'
112
+ render :file => 'test/dot.directory/render_file_with_ivar'
113
+ end
114
+
115
+ def render_file_from_template
116
+ @secret = 'in the sauce'
117
+ @path = File.expand_path(File.join(File.dirname(__FILE__), '../fixtures/test/render_file_with_ivar.erb'))
118
+ end
119
+
120
+ def render_file_with_locals
121
+ path = File.join(File.dirname(__FILE__), '../fixtures/test/render_file_with_locals.erb')
122
+ render :file => path, :locals => {:secret => 'in the sauce'}
123
+ end
124
+
125
+ def accessing_request_in_template
126
+ render :inline => "Hello: <%= request.host %>"
127
+ end
128
+
129
+ def accessing_logger_in_template
130
+ render :inline => "<%= logger.class %>"
131
+ end
132
+
133
+ def accessing_action_name_in_template
134
+ render :inline => "<%= action_name %>"
135
+ end
136
+
137
+ def accessing_controller_name_in_template
138
+ render :inline => "<%= controller_name %>"
139
+ end
140
+
52
141
  def render_json_hello_world
53
142
  render :json => {:hello => 'world'}.to_json
54
143
  end
@@ -65,6 +154,10 @@ class TestController < ActionController::Base
65
154
  render :json => {:hello => 'world'}.to_json
66
155
  end
67
156
 
157
+ def render_json_with_render_to_string
158
+ render :json => {:hello => render_to_string(:partial => 'partial')}
159
+ end
160
+
68
161
  def render_custom_code
69
162
  render :text => "hello world", :status => 404
70
163
  end
@@ -86,11 +179,15 @@ class TestController < ActionController::Base
86
179
  def render_nothing_with_appendix
87
180
  render :text => "appended"
88
181
  end
89
-
182
+
90
183
  def render_invalid_args
91
184
  render("test/hello")
92
185
  end
93
186
 
187
+ def render_vanilla_js_hello
188
+ render :js => "alert('hello')"
189
+ end
190
+
94
191
  def render_xml_hello
95
192
  @name = "David"
96
193
  render :template => "test/hello"
@@ -101,12 +198,7 @@ class TestController < ActionController::Base
101
198
  end
102
199
 
103
200
  def render_line_offset
104
- begin
105
- render :inline => '<% raise %>', :locals => {:foo => 'bar'}
106
- rescue RuntimeError => exc
107
- end
108
- line = exc.backtrace.first
109
- render :text => line
201
+ render :inline => '<% raise %>', :locals => {:foo => 'bar'}
110
202
  end
111
203
 
112
204
  def heading
@@ -122,7 +214,7 @@ class TestController < ActionController::Base
122
214
  end
123
215
 
124
216
  def builder_layout_test
125
- render :action => "hello"
217
+ render :action => "hello", :layout => "layouts/builder"
126
218
  end
127
219
 
128
220
  def builder_partial_test
@@ -154,6 +246,15 @@ class TestController < ActionController::Base
154
246
  :locals => { :local_name => name }
155
247
  end
156
248
 
249
+ def helper_method_to_render_to_string(*args)
250
+ render_to_string(*args)
251
+ end
252
+ helper_method :helper_method_to_render_to_string
253
+
254
+ def render_html_only_partial_within_inline
255
+ render :inline => "Hello world <%= helper_method_to_render_to_string :partial => 'test/partial_with_only_html_version' %>"
256
+ end
257
+
157
258
  def formatted_html_erb
158
259
  end
159
260
 
@@ -164,14 +265,243 @@ class TestController < ActionController::Base
164
265
  @foo = render_to_string :inline => "this is a test"
165
266
  end
166
267
 
167
- def partial
168
- render :partial => 'partial'
268
+ def default_render
269
+ if @alternate_default_render
270
+ @alternate_default_render.call
271
+ else
272
+ super
273
+ end
274
+ end
275
+
276
+ def render_action_hello_world_as_symbol
277
+ render :action => :hello_world
278
+ end
279
+
280
+ def layout_test_with_different_layout
281
+ render :action => "hello_world", :layout => "standard"
282
+ end
283
+
284
+ def rendering_without_layout
285
+ render :action => "hello_world", :layout => false
286
+ end
287
+
288
+ def layout_overriding_layout
289
+ render :action => "hello_world", :layout => "standard"
290
+ end
291
+
292
+ def rendering_nothing_on_layout
293
+ render :nothing => true
294
+ end
295
+
296
+ def render_to_string_with_assigns
297
+ @before = "i'm before the render"
298
+ render_to_string :text => "foo"
299
+ @after = "i'm after the render"
300
+ render :action => "test/hello_world"
301
+ end
302
+
303
+ def render_to_string_with_exception
304
+ render_to_string :file => "exception that will not be caught - this will certainly not work"
305
+ end
306
+
307
+ def render_to_string_with_caught_exception
308
+ @before = "i'm before the render"
309
+ begin
310
+ render_to_string :file => "exception that will be caught- hope my future instance vars still work!"
311
+ rescue
312
+ end
313
+ @after = "i'm after the render"
314
+ render :action => "test/hello_world"
315
+ end
316
+
317
+ def accessing_params_in_template_with_layout
318
+ render :layout => nil, :inline => "Hello: <%= params[:name] %>"
319
+ end
320
+
321
+ def render_with_explicit_template
322
+ render :template => "test/hello_world"
323
+ end
324
+
325
+ def render_with_explicit_template_with_locals
326
+ render :template => "test/render_file_with_locals", :locals => { :secret => 'area51' }
327
+ end
328
+
329
+ def double_render
330
+ render :text => "hello"
331
+ render :text => "world"
332
+ end
333
+
334
+ def double_redirect
335
+ redirect_to :action => "double_render"
336
+ redirect_to :action => "double_render"
337
+ end
338
+
339
+ def render_and_redirect
340
+ render :text => "hello"
341
+ redirect_to :action => "double_render"
342
+ end
343
+
344
+ def render_to_string_and_render
345
+ @stuff = render_to_string :text => "here is some cached stuff"
346
+ render :text => "Hi web users! #{@stuff}"
347
+ end
348
+
349
+ def render_to_string_with_inline_and_render
350
+ render_to_string :inline => "<%= 'dlrow olleh'.reverse %>"
351
+ render :template => "test/hello_world"
352
+ end
353
+
354
+ def rendering_with_conflicting_local_vars
355
+ @name = "David"
356
+ def @template.name() nil end
357
+ render :action => "potential_conflicts"
358
+ end
359
+
360
+ def hello_world_from_rxml_using_action
361
+ render :action => "hello_world_from_rxml.builder"
362
+ end
363
+
364
+ def hello_world_from_rxml_using_template
365
+ render :template => "test/hello_world_from_rxml.builder"
366
+ end
367
+
368
+ module RenderTestHelper
369
+ def rjs_helper_method_from_module
370
+ page.visual_effect :highlight
371
+ end
372
+ end
373
+
374
+ helper RenderTestHelper
375
+ helper do
376
+ def rjs_helper_method(value)
377
+ page.visual_effect :highlight, value
378
+ end
379
+ end
380
+
381
+ def enum_rjs_test
382
+ render :update do |page|
383
+ page.select('.product').each do |value|
384
+ page.rjs_helper_method_from_module
385
+ page.rjs_helper_method(value)
386
+ page.sortable(value, :url => { :action => "order" })
387
+ page.draggable(value)
388
+ end
389
+ end
390
+ end
391
+
392
+ def delete_with_js
393
+ @project_id = 4
394
+ end
395
+
396
+ def render_js_with_explicit_template
397
+ @project_id = 4
398
+ render :template => 'test/delete_with_js'
399
+ end
400
+
401
+ def render_js_with_explicit_action_template
402
+ @project_id = 4
403
+ render :action => 'delete_with_js'
404
+ end
405
+
406
+ def update_page
407
+ render :update do |page|
408
+ page.replace_html 'balance', '$37,000,000.00'
409
+ page.visual_effect :highlight, 'balance'
410
+ end
411
+ end
412
+
413
+ def update_page_with_instance_variables
414
+ @money = '$37,000,000.00'
415
+ @div_id = 'balance'
416
+ render :update do |page|
417
+ page.replace_html @div_id, @money
418
+ page.visual_effect :highlight, @div_id
419
+ end
420
+ end
421
+
422
+ def update_page_with_view_method
423
+ render :update do |page|
424
+ page.replace_html 'person', pluralize(2, 'person')
425
+ end
426
+ end
427
+
428
+ def action_talk_to_layout
429
+ # Action template sets variable that's picked up by layout
430
+ end
431
+
432
+ def render_text_with_assigns
433
+ @hello = "world"
434
+ render :text => "foo"
435
+ end
436
+
437
+ def yield_content_for
438
+ render :action => "content_for", :layout => "yield"
439
+ end
440
+
441
+ def render_content_type_from_body
442
+ response.content_type = Mime::RSS
443
+ render :text => "hello world!"
444
+ end
445
+
446
+ def head_with_location_header
447
+ head :location => "/foo"
448
+ end
449
+
450
+ def head_with_symbolic_status
451
+ head :status => params[:status].intern
452
+ end
453
+
454
+ def head_with_integer_status
455
+ head :status => params[:status].to_i
456
+ end
457
+
458
+ def head_with_string_status
459
+ head :status => params[:status]
460
+ end
461
+
462
+ def head_with_custom_header
463
+ head :x_custom_header => "something"
464
+ end
465
+
466
+ def head_with_status_code_first
467
+ head :forbidden, :x_custom_header => "something"
468
+ end
469
+
470
+ def render_with_location
471
+ render :xml => "<hello/>", :location => "http://example.com", :status => 201
472
+ end
473
+
474
+ def render_with_object_location
475
+ customer = Customer.new("Some guy", 1)
476
+ render :xml => "<customer/>", :location => customer_url(customer), :status => :created
477
+ end
478
+
479
+ def render_with_to_xml
480
+ to_xmlable = Class.new do
481
+ def to_xml
482
+ "<i-am-xml/>"
483
+ end
484
+ end.new
485
+
486
+ render :xml => to_xmlable
487
+ end
488
+
489
+ def render_using_layout_around_block
490
+ render :action => "using_layout_around_block"
491
+ end
492
+
493
+ def render_using_layout_around_block_with_args
494
+ render :action => "using_layout_around_block_with_args"
495
+ end
496
+
497
+ def render_using_layout_around_block_in_main_layout_and_within_content_for_layout
498
+ render :action => "using_layout_around_block", :layout => "layouts/block_with_layout"
169
499
  end
170
500
 
171
501
  def partial_dot_html
172
502
  render :partial => 'partial.html.erb'
173
503
  end
174
-
504
+
175
505
  def partial_as_rjs
176
506
  render :update do |page|
177
507
  page.replace :foo, :partial => 'partial'
@@ -188,51 +518,167 @@ class TestController < ActionController::Base
188
518
  end
189
519
  end
190
520
 
191
- def default_render
192
- if @alternate_default_render
193
- @alternate_default_render.call
194
- else
195
- render
196
- end
521
+ def partial
522
+ render :partial => 'partial'
197
523
  end
198
524
 
199
525
  def render_alternate_default
200
526
  # For this test, the method "default_render" is overridden:
201
- @alternate_default_render = lambda {
202
- render :update do |page|
203
- page.replace :foo, :partial => 'partial'
204
- end
205
- }
527
+ @alternate_default_render = lambda do
528
+ render :update do |page|
529
+ page.replace :foo, :partial => 'partial'
530
+ end
531
+ end
532
+ end
533
+
534
+ def partial_only_with_layout
535
+ render :partial => "partial_only", :layout => true
536
+ end
537
+
538
+ def render_to_string_with_partial
539
+ @partial_only = render_to_string :partial => "partial_only"
540
+ @partial_with_locals = render_to_string :partial => "customer", :locals => { :customer => Customer.new("david") }
541
+ render :action => "test/hello_world"
542
+ end
543
+
544
+ def partial_with_counter
545
+ render :partial => "counter", :locals => { :counter_counter => 5 }
546
+ end
547
+
548
+ def partial_with_locals
549
+ render :partial => "customer", :locals => { :customer => Customer.new("david") }
550
+ end
551
+
552
+ def partial_with_form_builder
553
+ render :partial => ActionView::Helpers::FormBuilder.new(:post, nil, @template, {}, Proc.new {})
554
+ end
555
+
556
+ def partial_with_form_builder_subclass
557
+ render :partial => LabellingFormBuilder.new(:post, nil, @template, {}, Proc.new {})
206
558
  end
207
559
 
208
- def rescue_action(e) raise end
560
+ def partial_collection
561
+ render :partial => "customer", :collection => [ Customer.new("david"), Customer.new("mary") ]
562
+ end
563
+
564
+ def partial_collection_with_as
565
+ render :partial => "customer_with_var", :collection => [ Customer.new("david"), Customer.new("mary") ], :as => :customer
566
+ end
567
+
568
+ def partial_collection_with_counter
569
+ render :partial => "customer_counter", :collection => [ Customer.new("david"), Customer.new("mary") ]
570
+ end
571
+
572
+ def partial_collection_with_locals
573
+ render :partial => "customer_greeting", :collection => [ Customer.new("david"), Customer.new("mary") ], :locals => { :greeting => "Bonjour" }
574
+ end
575
+
576
+ def partial_collection_with_spacer
577
+ render :partial => "customer", :spacer_template => "partial_only", :collection => [ Customer.new("david"), Customer.new("mary") ]
578
+ end
579
+
580
+ def partial_collection_shorthand_with_locals
581
+ render :partial => [ Customer.new("david"), Customer.new("mary") ], :locals => { :greeting => "Bonjour" }
582
+ end
583
+
584
+ def partial_collection_shorthand_with_different_types_of_records
585
+ render :partial => [
586
+ BadCustomer.new("mark"),
587
+ GoodCustomer.new("craig"),
588
+ BadCustomer.new("john"),
589
+ GoodCustomer.new("zach"),
590
+ GoodCustomer.new("brandon"),
591
+ BadCustomer.new("dan") ],
592
+ :locals => { :greeting => "Bonjour" }
593
+ end
594
+
595
+ def empty_partial_collection
596
+ render :partial => "customer", :collection => []
597
+ end
598
+
599
+ def partial_collection_shorthand_with_different_types_of_records_with_counter
600
+ partial_collection_shorthand_with_different_types_of_records
601
+ end
602
+
603
+ def missing_partial
604
+ render :partial => 'thisFileIsntHere'
605
+ end
606
+
607
+ def partial_with_hash_object
608
+ render :partial => "hash_object", :object => {:first_name => "Sam"}
609
+ end
610
+
611
+ def partial_hash_collection
612
+ render :partial => "hash_object", :collection => [ {:first_name => "Pratik"}, {:first_name => "Amy"} ]
613
+ end
614
+
615
+ def partial_hash_collection_with_locals
616
+ render :partial => "hash_greeting", :collection => [ {:first_name => "Pratik"}, {:first_name => "Amy"} ], :locals => { :greeting => "Hola" }
617
+ end
618
+
619
+ def partial_with_implicit_local_assignment
620
+ @customer = Customer.new("Marcel")
621
+ render :partial => "customer"
622
+ end
623
+
624
+ def render_call_to_partial_with_layout
625
+ render :action => "calling_partial_with_layout"
626
+ end
627
+
628
+ def render_call_to_partial_with_layout_in_main_layout_and_within_content_for_layout
629
+ render :action => "calling_partial_with_layout", :layout => "layouts/partial_with_layout"
630
+ end
631
+
632
+ def rescue_action(e)
633
+ raise
634
+ end
209
635
 
210
636
  private
211
637
  def determine_layout
212
638
  case action_name
213
- when "layout_test"; "layouts/standard"
214
- when "builder_layout_test"; "layouts/builder"
215
- when "render_symbol_json"; "layouts/standard" # to make sure layouts don't interfere
639
+ when "hello_world", "layout_test", "rendering_without_layout",
640
+ "rendering_nothing_on_layout", "render_text_hello_world",
641
+ "render_text_hello_world_with_layout",
642
+ "hello_world_with_layout_false",
643
+ "partial_only", "partial_only_with_layout",
644
+ "accessing_params_in_template",
645
+ "accessing_params_in_template_with_layout",
646
+ "render_with_explicit_template",
647
+ "render_js_with_explicit_template",
648
+ "render_js_with_explicit_action_template",
649
+ "delete_with_js", "update_page", "update_page_with_instance_variables"
650
+
651
+ "layouts/standard"
652
+ when "action_talk_to_layout", "layout_overriding_layout"
653
+ "layouts/talk_from_action"
216
654
  end
217
655
  end
218
656
  end
219
657
 
220
- TestController.view_paths = [ File.dirname(__FILE__) + "/../fixtures/" ]
221
- Fun::GamesController.view_paths = [ File.dirname(__FILE__) + "/../fixtures/" ]
222
-
223
658
  class RenderTest < Test::Unit::TestCase
224
659
  def setup
225
660
  @request = ActionController::TestRequest.new
226
661
  @response = ActionController::TestResponse.new
227
662
  @controller = TestController.new
228
663
 
664
+ # enable a logger so that (e.g.) the benchmarking stuff runs, so we can get
665
+ # a more accurate simulation of what happens in "real life".
666
+ @controller.logger = Logger.new(nil)
667
+
229
668
  @request.host = "www.nextangle.com"
230
669
  end
231
670
 
232
671
  def test_simple_show
233
672
  get :hello_world
234
673
  assert_response 200
674
+ assert_response :success
235
675
  assert_template "test/hello_world"
676
+ assert_equal "<html>Hello world!</html>", @response.body
677
+ end
678
+
679
+ def test_renders_default_template_for_missing_action
680
+ get :'hyphen-ated'
681
+ assert_template 'test/hyphen-ated'
236
682
  end
237
683
 
238
684
  def test_render
@@ -241,23 +687,28 @@ class RenderTest < Test::Unit::TestCase
241
687
  end
242
688
 
243
689
  def test_line_offset
244
- get :render_line_offset
245
- line = @response.body
246
- assert(line =~ %r{:(\d+):})
247
- assert_equal "1", $1
690
+ begin
691
+ get :render_line_offset
692
+ flunk "the action should have raised an exception"
693
+ rescue RuntimeError => exc
694
+ line = exc.backtrace.first
695
+ assert(line =~ %r{:(\d+):})
696
+ assert_equal "1", $1,
697
+ "The line offset is wrong, perhaps the wrong exception has been raised, exception was: #{exc.inspect}"
698
+ end
248
699
  end
249
700
 
250
701
  def test_render_with_forward_slash
251
702
  get :render_hello_world_with_forward_slash
252
703
  assert_template "test/hello_world"
253
704
  end
254
-
705
+
255
706
  def test_render_in_top_directory
256
707
  get :render_template_in_top_directory
257
708
  assert_template "shared"
258
709
  assert_equal "Elastica", @response.body
259
710
  end
260
-
711
+
261
712
  def test_render_in_top_directory_with_slash
262
713
  get :render_template_in_top_directory_with_slash
263
714
  assert_template "shared"
@@ -284,6 +735,41 @@ class RenderTest < Test::Unit::TestCase
284
735
  assert_equal "hello world", @response.body
285
736
  end
286
737
 
738
+ def test_do_with_render_text_and_layout
739
+ get :render_text_hello_world_with_layout
740
+ assert_equal "<html>hello world, I'm here!</html>", @response.body
741
+ end
742
+
743
+ def test_do_with_render_action_and_layout_false
744
+ get :hello_world_with_layout_false
745
+ assert_equal 'Hello world!', @response.body
746
+ end
747
+
748
+ def test_render_file_with_instance_variables
749
+ get :render_file_with_instance_variables
750
+ assert_equal "The secret is in the sauce\n", @response.body
751
+ end
752
+
753
+ def test_render_file_not_using_full_path
754
+ get :render_file_not_using_full_path
755
+ assert_equal "The secret is in the sauce\n", @response.body
756
+ end
757
+
758
+ def test_render_file_not_using_full_path_with_dot_in_path
759
+ get :render_file_not_using_full_path_with_dot_in_path
760
+ assert_equal "The secret is in the sauce\n", @response.body
761
+ end
762
+
763
+ def test_render_file_with_locals
764
+ get :render_file_with_locals
765
+ assert_equal "The secret is in the sauce\n", @response.body
766
+ end
767
+
768
+ def test_render_file_from_template
769
+ get :render_file_from_template
770
+ assert_equal "The secret is in the sauce\n", @response.body
771
+ end
772
+
287
773
  def test_render_json
288
774
  get :render_json_hello_world
289
775
  assert_equal '{"hello": "world"}', @response.body
@@ -308,9 +794,16 @@ class RenderTest < Test::Unit::TestCase
308
794
  assert_equal 'application/json', @response.content_type
309
795
  end
310
796
 
797
+ def test_render_json_with_render_to_string
798
+ get :render_json_with_render_to_string
799
+ assert_equal '{"hello": "partial html"}', @response.body
800
+ assert_equal 'application/json', @response.content_type
801
+ end
802
+
311
803
  def test_render_custom_code
312
804
  get :render_custom_code
313
805
  assert_response 404
806
+ assert_response :missing
314
807
  assert_equal 'hello world', @response.body
315
808
  end
316
809
 
@@ -323,7 +816,7 @@ class RenderTest < Test::Unit::TestCase
323
816
  def test_render_text_with_nil
324
817
  get :render_text_with_nil
325
818
  assert_response 200
326
- assert_equal '', @response.body
819
+ assert_equal ' ', @response.body
327
820
  end
328
821
 
329
822
  def test_render_text_with_false
@@ -336,11 +829,11 @@ class RenderTest < Test::Unit::TestCase
336
829
  assert_response 200
337
830
  assert_equal 'appended', @response.body
338
831
  end
339
-
832
+
340
833
  def test_attempt_to_render_with_invalid_arguments
341
834
  assert_raises(ActionController::RenderError) { get :render_invalid_args }
342
835
  end
343
-
836
+
344
837
  def test_attempt_to_access_object_method
345
838
  assert_raises(ActionController::UnknownAction, "No action responded to [clone]") { get :clone }
346
839
  end
@@ -349,9 +842,38 @@ class RenderTest < Test::Unit::TestCase
349
842
  assert_raises(ActionController::UnknownAction, "No action responded to [determine_layout]") { get :determine_layout }
350
843
  end
351
844
 
352
- def test_render_xml
353
- get :render_xml_hello
354
- assert_equal "<html>\n <p>Hello David</p>\n<p>This is grand!</p>\n</html>\n", @response.body
845
+ def test_access_to_request_in_view
846
+ get :accessing_request_in_template
847
+ assert_equal "Hello: www.nextangle.com", @response.body
848
+ end
849
+
850
+ def test_access_to_logger_in_view
851
+ get :accessing_logger_in_template
852
+ assert_equal "Logger", @response.body
853
+ end
854
+
855
+ def test_access_to_action_name_in_view
856
+ get :accessing_action_name_in_template
857
+ assert_equal "accessing_action_name_in_template", @response.body
858
+ end
859
+
860
+ def test_access_to_controller_name_in_view
861
+ get :accessing_controller_name_in_template
862
+ assert_equal "test", @response.body # name is explicitly set to 'test' inside the controller.
863
+ end
864
+
865
+ def test_render_vanilla_js
866
+ get :render_vanilla_js_hello
867
+ assert_equal "alert('hello')", @response.body
868
+ assert_equal "text/javascript", @response.content_type
869
+ end
870
+
871
+ def test_render_xml
872
+ assert_deprecated do
873
+ get :render_xml_hello
874
+ end
875
+
876
+ assert_equal "<html>\n <p>Hello David</p>\n<p>This is grand!</p>\n</html>\n", @response.body
355
877
  assert_equal "application/xml", @response.content_type
356
878
  end
357
879
 
@@ -365,24 +887,35 @@ class RenderTest < Test::Unit::TestCase
365
887
  assert_equal "<test>\n <hello/>\n</test>\n", @response.body
366
888
  end
367
889
 
890
+ def test_enum_rjs_test
891
+ get :enum_rjs_test
892
+ body = %{
893
+ $$(".product").each(function(value, index) {
894
+ new Effect.Highlight(element,{});
895
+ new Effect.Highlight(value,{});
896
+ Sortable.create(value, {onUpdate:function(){new Ajax.Request('/test/order', {asynchronous:true, evalScripts:true, parameters:Sortable.serialize(value)})}});
897
+ new Draggable(value, {});
898
+ });
899
+ }.gsub(/^ /, '').strip
900
+ assert_equal body, @response.body
901
+ end
902
+
368
903
  def test_layout_rendering
369
904
  get :layout_test
370
905
  assert_equal "<html>Hello world!</html>", @response.body
371
906
  end
372
907
 
373
908
  def test_render_xml_with_layouts
374
- get :builder_layout_test
909
+ assert_deprecated do
910
+ get :builder_layout_test
911
+ end
912
+
375
913
  assert_equal "<wrapper>\n<html>\n <p>Hello </p>\n<p>This is grand!</p>\n</html>\n</wrapper>\n", @response.body
376
914
  end
377
915
 
378
- # def test_partials_list
379
- # get :partials_list
380
- # assert_equal "goodbyeHello: davidHello: marygoodbye\n", process_request.body
381
- # end
382
-
383
- def test_partial_only
384
- get :partial_only
385
- assert_equal "only partial", @response.body
916
+ def test_partials_list
917
+ get :partials_list
918
+ assert_equal "goodbyeHello: davidHello: marygoodbye\n", @response.body
386
919
  end
387
920
 
388
921
  def test_render_to_string
@@ -395,6 +928,11 @@ class RenderTest < Test::Unit::TestCase
395
928
  assert_equal "The value of foo is: ::this is a test::\n", @response.body
396
929
  end
397
930
 
931
+ def test_render_to_string_inline
932
+ get :render_to_string_with_inline_and_render
933
+ assert_template "test/hello_world"
934
+ end
935
+
398
936
  def test_nested_rendering
399
937
  @controller = Fun::GamesController.new
400
938
  get :hello_world
@@ -411,6 +949,430 @@ class RenderTest < Test::Unit::TestCase
411
949
  assert_equal "Goodbye, Local David", @response.body
412
950
  end
413
951
 
952
+ def test_rendering_html_only_partial_within_inline_with_js
953
+ get :render_html_only_partial_within_inline, :format => :js
954
+ assert_equal "Hello world partial with only html version", @response.body
955
+ end
956
+
957
+ def test_should_render_formatted_template
958
+ get :formatted_html_erb
959
+ assert_equal 'formatted html erb', @response.body
960
+ end
961
+
962
+ def test_should_render_formatted_xml_erb_template
963
+ get :formatted_xml_erb, :format => :xml
964
+ assert_equal '<test>passed formatted xml erb</test>', @response.body
965
+ end
966
+
967
+ def test_should_render_formatted_html_erb_template
968
+ get :formatted_xml_erb
969
+ assert_equal '<test>passed formatted html erb</test>', @response.body
970
+ end
971
+
972
+ def test_should_render_formatted_html_erb_template_with_faulty_accepts_header
973
+ @request.accept = "image/gif, image/x-xbitmap, image/jpeg, image/pjpeg, appliction/x-shockwave-flash, */*"
974
+ get :formatted_xml_erb
975
+ assert_equal '<test>passed formatted html erb</test>', @response.body
976
+ end
977
+
978
+ def test_should_render_xml_but_keep_custom_content_type
979
+ get :render_xml_with_custom_content_type
980
+ assert_equal "application/atomsvc+xml", @response.content_type
981
+ end
982
+
983
+ def test_render_with_default_from_accept_header
984
+ xhr :get, :greeting
985
+ assert_equal "$(\"body\").visualEffect(\"highlight\");", @response.body
986
+ end
987
+
988
+ def test_render_rjs_with_default
989
+ get :delete_with_js
990
+ assert_equal %!Element.remove("person");\nnew Effect.Highlight(\"project-4\",{});!, @response.body
991
+ end
992
+
993
+ def test_render_rjs_template_explicitly
994
+ get :render_js_with_explicit_template
995
+ assert_equal %!Element.remove("person");\nnew Effect.Highlight(\"project-4\",{});!, @response.body
996
+ end
997
+
998
+ def test_rendering_rjs_action_explicitly
999
+ get :render_js_with_explicit_action_template
1000
+ assert_equal %!Element.remove("person");\nnew Effect.Highlight(\"project-4\",{});!, @response.body
1001
+ end
1002
+
1003
+ def test_layout_test_with_different_layout
1004
+ get :layout_test_with_different_layout
1005
+ assert_equal "<html>Hello world!</html>", @response.body
1006
+ end
1007
+
1008
+ def test_rendering_without_layout
1009
+ get :rendering_without_layout
1010
+ assert_equal "Hello world!", @response.body
1011
+ end
1012
+
1013
+ def test_layout_overriding_layout
1014
+ get :layout_overriding_layout
1015
+ assert_no_match %r{<title>}, @response.body
1016
+ end
1017
+
1018
+ def test_rendering_nothing_on_layout
1019
+ get :rendering_nothing_on_layout
1020
+ assert_equal " ", @response.body
1021
+ end
1022
+
1023
+ def test_render_to_string
1024
+ assert_not_deprecated { get :hello_in_a_string }
1025
+ assert_equal "How's there? goodbyeHello: davidHello: marygoodbye\n", @response.body
1026
+ end
1027
+
1028
+ def test_render_to_string_doesnt_break_assigns
1029
+ get :render_to_string_with_assigns
1030
+ assert_equal "i'm before the render", assigns(:before)
1031
+ assert_equal "i'm after the render", assigns(:after)
1032
+ end
1033
+
1034
+ def test_bad_render_to_string_still_throws_exception
1035
+ assert_raises(ActionView::MissingTemplate) { get :render_to_string_with_exception }
1036
+ end
1037
+
1038
+ def test_render_to_string_that_throws_caught_exception_doesnt_break_assigns
1039
+ assert_nothing_raised { get :render_to_string_with_caught_exception }
1040
+ assert_equal "i'm before the render", assigns(:before)
1041
+ assert_equal "i'm after the render", assigns(:after)
1042
+ end
1043
+
1044
+ def test_accessing_params_in_template_with_layout
1045
+ get :accessing_params_in_template_with_layout, :name => "David"
1046
+ assert_equal "<html>Hello: David</html>", @response.body
1047
+ end
1048
+
1049
+ def test_render_with_explicit_template
1050
+ get :render_with_explicit_template
1051
+ assert_response :success
1052
+ end
1053
+
1054
+ def test_double_render
1055
+ assert_raises(ActionController::DoubleRenderError) { get :double_render }
1056
+ end
1057
+
1058
+ def test_double_redirect
1059
+ assert_raises(ActionController::DoubleRenderError) { get :double_redirect }
1060
+ end
1061
+
1062
+ def test_render_and_redirect
1063
+ assert_raises(ActionController::DoubleRenderError) { get :render_and_redirect }
1064
+ end
1065
+
1066
+ # specify the one exception to double render rule - render_to_string followed by render
1067
+ def test_render_to_string_and_render
1068
+ get :render_to_string_and_render
1069
+ assert_equal("Hi web users! here is some cached stuff", @response.body)
1070
+ end
1071
+
1072
+ def test_rendering_with_conflicting_local_vars
1073
+ get :rendering_with_conflicting_local_vars
1074
+ assert_equal("First: David\nSecond: Stephan\nThird: David\nFourth: David\nFifth: ", @response.body)
1075
+ end
1076
+
1077
+ def test_action_talk_to_layout
1078
+ get :action_talk_to_layout
1079
+ assert_equal "<title>Talking to the layout</title>\nAction was here!", @response.body
1080
+ end
1081
+
1082
+ def test_render_text_with_assigns
1083
+ get :render_text_with_assigns
1084
+ assert_equal "world", assigns["hello"]
1085
+ end
1086
+
1087
+ def test_template_with_locals
1088
+ get :render_with_explicit_template_with_locals
1089
+ assert_equal "The secret is area51\n", @response.body
1090
+ end
1091
+
1092
+ def test_update_page
1093
+ get :update_page
1094
+ assert_template nil
1095
+ assert_equal 'text/javascript; charset=utf-8', @response.headers['type']
1096
+ assert_equal 2, @response.body.split($/).length
1097
+ end
1098
+
1099
+ def test_update_page_with_instance_variables
1100
+ get :update_page_with_instance_variables
1101
+ assert_template nil
1102
+ assert_equal 'text/javascript; charset=utf-8', @response.headers['type']
1103
+ assert_match /balance/, @response.body
1104
+ assert_match /\$37/, @response.body
1105
+ end
1106
+
1107
+ def test_update_page_with_view_method
1108
+ get :update_page_with_view_method
1109
+ assert_template nil
1110
+ assert_equal 'text/javascript; charset=utf-8', @response.headers['type']
1111
+ assert_match /2 people/, @response.body
1112
+ end
1113
+
1114
+ def test_yield_content_for
1115
+ assert_not_deprecated { get :yield_content_for }
1116
+ assert_equal "<title>Putting stuff in the title!</title>\n\nGreat stuff!\n", @response.body
1117
+ end
1118
+
1119
+ def test_overwritting_rendering_relative_file_with_extension
1120
+ get :hello_world_from_rxml_using_template
1121
+ assert_equal "<html>\n <p>Hello</p>\n</html>\n", @response.body
1122
+
1123
+ get :hello_world_from_rxml_using_action
1124
+ assert_equal "<html>\n <p>Hello</p>\n</html>\n", @response.body
1125
+ end
1126
+
1127
+ def test_head_with_location_header
1128
+ get :head_with_location_header
1129
+ assert @response.body.blank?
1130
+ assert_equal "/foo", @response.headers["Location"]
1131
+ assert_response :ok
1132
+ end
1133
+
1134
+ def test_head_with_custom_header
1135
+ get :head_with_custom_header
1136
+ assert @response.body.blank?
1137
+ assert_equal "something", @response.headers["X-Custom-Header"]
1138
+ assert_response :ok
1139
+ end
1140
+
1141
+ def test_head_with_symbolic_status
1142
+ get :head_with_symbolic_status, :status => "ok"
1143
+ assert_equal "200 OK", @response.headers["Status"]
1144
+ assert_response :ok
1145
+
1146
+ get :head_with_symbolic_status, :status => "not_found"
1147
+ assert_equal "404 Not Found", @response.headers["Status"]
1148
+ assert_response :not_found
1149
+
1150
+ ActionController::StatusCodes::SYMBOL_TO_STATUS_CODE.each do |status, code|
1151
+ get :head_with_symbolic_status, :status => status.to_s
1152
+ assert_equal code, @response.response_code
1153
+ assert_response status
1154
+ end
1155
+ end
1156
+
1157
+ def test_head_with_integer_status
1158
+ ActionController::StatusCodes::STATUS_CODES.each do |code, message|
1159
+ get :head_with_integer_status, :status => code.to_s
1160
+ assert_equal message, @response.message
1161
+ end
1162
+ end
1163
+
1164
+ def test_head_with_string_status
1165
+ get :head_with_string_status, :status => "404 Eat Dirt"
1166
+ assert_equal 404, @response.response_code
1167
+ assert_equal "Eat Dirt", @response.message
1168
+ assert_response :not_found
1169
+ end
1170
+
1171
+ def test_head_with_status_code_first
1172
+ get :head_with_status_code_first
1173
+ assert_equal 403, @response.response_code
1174
+ assert_equal "Forbidden", @response.message
1175
+ assert_equal "something", @response.headers["X-Custom-Header"]
1176
+ assert_response :forbidden
1177
+ end
1178
+
1179
+ def test_rendering_with_location_should_set_header
1180
+ get :render_with_location
1181
+ assert_equal "http://example.com", @response.headers["Location"]
1182
+ end
1183
+
1184
+ def test_rendering_xml_should_call_to_xml_if_possible
1185
+ get :render_with_to_xml
1186
+ assert_equal "<i-am-xml/>", @response.body
1187
+ end
1188
+
1189
+ def test_rendering_with_object_location_should_set_header_with_url_for
1190
+ ActionController::Routing::Routes.draw do |map|
1191
+ map.resources :customers
1192
+ map.connect ':controller/:action/:id'
1193
+ end
1194
+
1195
+ get :render_with_object_location
1196
+ assert_equal "http://www.nextangle.com/customers/1", @response.headers["Location"]
1197
+ end
1198
+
1199
+ def test_should_use_implicit_content_type
1200
+ get :implicit_content_type, :format => 'atom'
1201
+ assert_equal Mime::ATOM, @response.content_type
1202
+ end
1203
+
1204
+ def test_using_layout_around_block
1205
+ get :render_using_layout_around_block
1206
+ assert_equal "Before (David)\nInside from block\nAfter", @response.body
1207
+ end
1208
+
1209
+ def test_using_layout_around_block_in_main_layout_and_within_content_for_layout
1210
+ get :render_using_layout_around_block_in_main_layout_and_within_content_for_layout
1211
+ assert_equal "Before (Anthony)\nInside from first block in layout\nAfter\nBefore (David)\nInside from block\nAfter\nBefore (Ramm)\nInside from second block in layout\nAfter\n", @response.body
1212
+ end
1213
+
1214
+ def test_using_layout_around_block_with_args
1215
+ get :render_using_layout_around_block_with_args
1216
+ assert_equal "Before\narg1arg2\nAfter", @response.body
1217
+ end
1218
+
1219
+ def test_partial_only
1220
+ get :partial_only
1221
+ assert_equal "only partial", @response.body
1222
+ end
1223
+
1224
+ def test_should_render_html_formatted_partial
1225
+ get :partial
1226
+ assert_equal 'partial html', @response.body
1227
+ end
1228
+
1229
+ def test_should_render_html_partial_with_dot
1230
+ get :partial_dot_html
1231
+ assert_equal 'partial html', @response.body
1232
+ end
1233
+
1234
+ def test_should_render_html_formatted_partial_with_rjs
1235
+ xhr :get, :partial_as_rjs
1236
+ assert_equal %(Element.replace("foo", "partial html");), @response.body
1237
+ end
1238
+
1239
+ def test_should_render_html_formatted_partial_with_rjs_and_js_format
1240
+ xhr :get, :respond_to_partial_as_rjs
1241
+ assert_equal %(Element.replace("foo", "partial html");), @response.body
1242
+ end
1243
+
1244
+ def test_should_render_js_partial
1245
+ xhr :get, :partial, :format => 'js'
1246
+ assert_equal 'partial js', @response.body
1247
+ end
1248
+
1249
+ def test_should_render_with_alternate_default_render
1250
+ xhr :get, :render_alternate_default
1251
+ assert_equal %(Element.replace("foo", "partial html");), @response.body
1252
+ end
1253
+
1254
+ def test_partial_only_with_layout
1255
+ get :partial_only_with_layout
1256
+ assert_equal "<html>only partial</html>", @response.body
1257
+ end
1258
+
1259
+ def test_render_to_string_partial
1260
+ get :render_to_string_with_partial
1261
+ assert_equal "only partial", assigns(:partial_only)
1262
+ assert_equal "Hello: david", assigns(:partial_with_locals)
1263
+ end
1264
+
1265
+ def test_partial_with_counter
1266
+ get :partial_with_counter
1267
+ assert_equal "5", @response.body
1268
+ end
1269
+
1270
+ def test_partial_with_locals
1271
+ get :partial_with_locals
1272
+ assert_equal "Hello: david", @response.body
1273
+ end
1274
+
1275
+ def test_partial_with_form_builder
1276
+ get :partial_with_form_builder
1277
+ assert_match(/<label/, @response.body)
1278
+ assert_template('test/_form')
1279
+ end
1280
+
1281
+ def test_partial_with_form_builder_subclass
1282
+ get :partial_with_form_builder_subclass
1283
+ assert_match(/<label/, @response.body)
1284
+ assert_template('test/_labelling_form')
1285
+ end
1286
+
1287
+ def test_partial_collection
1288
+ get :partial_collection
1289
+ assert_equal "Hello: davidHello: mary", @response.body
1290
+ end
1291
+
1292
+ def test_partial_collection_with_as
1293
+ get :partial_collection_with_as
1294
+ assert_equal "david david davidmary mary mary", @response.body
1295
+ end
1296
+
1297
+ def test_partial_collection_with_counter
1298
+ get :partial_collection_with_counter
1299
+ assert_equal "david0mary1", @response.body
1300
+ end
1301
+
1302
+ def test_partial_collection_with_locals
1303
+ get :partial_collection_with_locals
1304
+ assert_equal "Bonjour: davidBonjour: mary", @response.body
1305
+ end
1306
+
1307
+ def test_partial_collection_with_spacer
1308
+ get :partial_collection_with_spacer
1309
+ assert_equal "Hello: davidonly partialHello: mary", @response.body
1310
+ end
1311
+
1312
+ def test_partial_collection_shorthand_with_locals
1313
+ get :partial_collection_shorthand_with_locals
1314
+ assert_equal "Bonjour: davidBonjour: mary", @response.body
1315
+ end
1316
+
1317
+ def test_partial_collection_shorthand_with_different_types_of_records
1318
+ get :partial_collection_shorthand_with_different_types_of_records
1319
+ assert_equal "Bonjour bad customer: mark0Bonjour good customer: craig1Bonjour bad customer: john2Bonjour good customer: zach3Bonjour good customer: brandon4Bonjour bad customer: dan5", @response.body
1320
+ end
1321
+
1322
+ def test_empty_partial_collection
1323
+ get :empty_partial_collection
1324
+ assert_equal " ", @response.body
1325
+ end
1326
+
1327
+ def test_partial_with_hash_object
1328
+ get :partial_with_hash_object
1329
+ assert_equal "Sam\nmaS\n", @response.body
1330
+ end
1331
+
1332
+ def test_hash_partial_collection
1333
+ get :partial_hash_collection
1334
+ assert_equal "Pratik\nkitarP\nAmy\nymA\n", @response.body
1335
+ end
1336
+
1337
+ def test_partial_hash_collection_with_locals
1338
+ get :partial_hash_collection_with_locals
1339
+ assert_equal "Hola: PratikHola: Amy", @response.body
1340
+ end
1341
+
1342
+ def test_partial_with_implicit_local_assignment
1343
+ assert_deprecated do
1344
+ get :partial_with_implicit_local_assignment
1345
+ assert_equal "Hello: Marcel", @response.body
1346
+ end
1347
+ end
1348
+
1349
+ def test_render_missing_partial_template
1350
+ assert_raises(ActionView::MissingTemplate) do
1351
+ get :missing_partial
1352
+ end
1353
+ end
1354
+
1355
+ def test_render_call_to_partial_with_layout
1356
+ get :render_call_to_partial_with_layout
1357
+ assert_equal "Before (David)\nInside from partial (David)\nAfter", @response.body
1358
+ end
1359
+
1360
+ def test_render_call_to_partial_with_layout_in_main_layout_and_within_content_for_layout
1361
+ get :render_call_to_partial_with_layout_in_main_layout_and_within_content_for_layout
1362
+ assert_equal "Before (Anthony)\nInside from partial (Anthony)\nAfter\nBefore (David)\nInside from partial (David)\nAfter\nBefore (Ramm)\nInside from partial (Ramm)\nAfter", @response.body
1363
+ end
1364
+ end
1365
+
1366
+ class EtagRenderTest < Test::Unit::TestCase
1367
+ def setup
1368
+ @request = ActionController::TestRequest.new
1369
+ @response = ActionController::TestResponse.new
1370
+ @controller = TestController.new
1371
+
1372
+ @request.host = "www.nextangle.com"
1373
+ @expected_bang_etag = etag_for(expand_key([:foo, 123]))
1374
+ end
1375
+
414
1376
  def test_render_200_should_set_etag
415
1377
  get :render_hello_world_from_variable
416
1378
  assert_equal etag_for("hello david"), @response.headers['ETag']
@@ -418,31 +1380,46 @@ class RenderTest < Test::Unit::TestCase
418
1380
  end
419
1381
 
420
1382
  def test_render_against_etag_request_should_304_when_match
421
- @request.headers["HTTP_IF_NONE_MATCH"] = etag_for("hello david")
1383
+ @request.if_none_match = etag_for("hello david")
422
1384
  get :render_hello_world_from_variable
423
- assert_equal "304 Not Modified", @response.headers['Status']
1385
+ assert_equal "304 Not Modified", @response.status
424
1386
  assert @response.body.empty?
425
1387
  end
426
1388
 
1389
+ def test_render_against_etag_request_should_have_no_content_length_when_match
1390
+ @request.if_none_match = etag_for("hello david")
1391
+ get :render_hello_world_from_variable
1392
+ assert !@response.headers.has_key?("Content-Length")
1393
+ end
1394
+
427
1395
  def test_render_against_etag_request_should_200_when_no_match
428
- @request.headers["HTTP_IF_NONE_MATCH"] = etag_for("hello somewhere else")
1396
+ @request.if_none_match = etag_for("hello somewhere else")
429
1397
  get :render_hello_world_from_variable
430
- assert_equal "200 OK", @response.headers['Status']
1398
+ assert_equal "200 OK", @response.status
431
1399
  assert !@response.body.empty?
432
1400
  end
433
1401
 
1402
+ def test_render_should_not_set_etag_when_last_modified_has_been_specified
1403
+ get :render_hello_world_with_last_modified_set
1404
+ assert_equal "200 OK", @response.status
1405
+ assert_not_nil @response.last_modified
1406
+ assert_nil @response.etag
1407
+ assert @response.body.present?
1408
+ end
1409
+
434
1410
  def test_render_with_etag
435
1411
  get :render_hello_world_from_variable
436
1412
  expected_etag = etag_for('hello david')
437
1413
  assert_equal expected_etag, @response.headers['ETag']
1414
+ @response = ActionController::TestResponse.new
438
1415
 
439
- @request.headers["HTTP_IF_NONE_MATCH"] = expected_etag
1416
+ @request.if_none_match = expected_etag
440
1417
  get :render_hello_world_from_variable
441
- assert_equal "304 Not Modified", @response.headers['Status']
1418
+ assert_equal "304 Not Modified", @response.status
442
1419
 
443
- @request.headers["HTTP_IF_NONE_MATCH"] = "\"diftag\""
1420
+ @request.if_none_match = "\"diftag\""
444
1421
  get :render_hello_world_from_variable
445
- assert_equal "200 OK", @response.headers['Status']
1422
+ assert_equal "200 OK", @response.status
446
1423
  end
447
1424
 
448
1425
  def render_with_404_shouldnt_have_etag
@@ -451,77 +1428,112 @@ class RenderTest < Test::Unit::TestCase
451
1428
  end
452
1429
 
453
1430
  def test_etag_should_not_be_changed_when_already_set
454
- expected_etag = etag_for("hello somewhere else")
455
- @response.headers["ETag"] = expected_etag
456
- get :render_hello_world_from_variable
457
- assert_equal expected_etag, @response.headers['ETag']
1431
+ get :render_hello_world_with_etag_set
1432
+ assert_equal etag_for("hello_world"), @response.headers['ETag']
458
1433
  end
459
1434
 
460
1435
  def test_etag_should_govern_renders_with_layouts_too
461
- get :builder_layout_test
1436
+ assert_deprecated do
1437
+ get :builder_layout_test
1438
+ end
1439
+
462
1440
  assert_equal "<wrapper>\n<html>\n <p>Hello </p>\n<p>This is grand!</p>\n</html>\n</wrapper>\n", @response.body
463
1441
  assert_equal etag_for("<wrapper>\n<html>\n <p>Hello </p>\n<p>This is grand!</p>\n</html>\n</wrapper>\n"), @response.headers['ETag']
464
1442
  end
465
1443
 
466
- def test_should_render_formatted_template
467
- get :formatted_html_erb
468
- assert_equal 'formatted html erb', @response.body
1444
+ def test_etag_with_bang_should_set_etag
1445
+ get :conditional_hello_with_bangs
1446
+ assert_equal @expected_bang_etag, @response.headers["ETag"]
1447
+ assert_response :success
469
1448
  end
470
-
471
- def test_should_render_formatted_xml_erb_template
472
- get :formatted_xml_erb, :format => :xml
473
- assert_equal '<test>passed formatted xml erb</test>', @response.body
1449
+
1450
+ def test_etag_with_bang_should_obey_if_none_match
1451
+ @request.if_none_match = @expected_bang_etag
1452
+ get :conditional_hello_with_bangs
1453
+ assert_response :not_modified
474
1454
  end
475
-
476
- def test_should_render_formatted_html_erb_template
477
- get :formatted_xml_erb
478
- assert_equal '<test>passed formatted html erb</test>', @response.body
1455
+
1456
+ protected
1457
+ def etag_for(text)
1458
+ %("#{Digest::MD5.hexdigest(text)}")
1459
+ end
1460
+
1461
+ def expand_key(args)
1462
+ ActiveSupport::Cache.expand_cache_key(args)
1463
+ end
1464
+ end
1465
+
1466
+ class LastModifiedRenderTest < Test::Unit::TestCase
1467
+ def setup
1468
+ @request = ActionController::TestRequest.new
1469
+ @response = ActionController::TestResponse.new
1470
+ @controller = TestController.new
1471
+
1472
+ @request.host = "www.nextangle.com"
1473
+ @last_modified = Time.now.utc.beginning_of_day.httpdate
479
1474
  end
480
-
481
- def test_should_render_formatted_html_erb_template_with_faulty_accepts_header
482
- @request.env["HTTP_ACCEPT"] = "image/gif, image/x-xbitmap, image/jpeg, image/pjpeg, appliction/x-shockwave-flash, */*"
483
- get :formatted_xml_erb
484
- assert_equal '<test>passed formatted html erb</test>', @response.body
1475
+
1476
+ def test_responds_with_last_modified
1477
+ get :conditional_hello
1478
+ assert_equal @last_modified, @response.headers['Last-Modified']
485
1479
  end
486
1480
 
487
- def test_should_render_html_formatted_partial
488
- get :partial
489
- assert_equal 'partial html', @response.body
1481
+ def test_request_not_modified
1482
+ @request.if_modified_since = @last_modified
1483
+ get :conditional_hello
1484
+ assert_equal "304 Not Modified", @response.status
1485
+ assert @response.body.blank?, @response.body
1486
+ assert_equal @last_modified, @response.headers['Last-Modified']
490
1487
  end
491
1488
 
492
- def test_should_render_html_partial_with_dot
493
- get :partial_dot_html
494
- assert_equal 'partial html', @response.body
1489
+ def test_request_not_modified_but_etag_differs
1490
+ @request.if_modified_since = @last_modified
1491
+ @request.if_none_match = "234"
1492
+ get :conditional_hello
1493
+ assert_response :success
495
1494
  end
496
1495
 
497
- def test_should_render_html_formatted_partial_with_rjs
498
- xhr :get, :partial_as_rjs
499
- assert_equal %(Element.replace("foo", "partial html");), @response.body
1496
+ def test_request_modified
1497
+ @request.if_modified_since = 'Thu, 16 Jul 2008 00:00:00 GMT'
1498
+ get :conditional_hello
1499
+ assert_equal "200 OK", @response.status
1500
+ assert !@response.body.blank?
1501
+ assert_equal @last_modified, @response.headers['Last-Modified']
500
1502
  end
501
1503
 
502
- def test_should_render_html_formatted_partial_with_rjs_and_js_format
503
- xhr :get, :respond_to_partial_as_rjs
504
- assert_equal %(Element.replace("foo", "partial html");), @response.body
1504
+ def test_request_with_bang_gets_last_modified
1505
+ get :conditional_hello_with_bangs
1506
+ assert_equal @last_modified, @response.headers['Last-Modified']
1507
+ assert_response :success
505
1508
  end
506
1509
 
507
- def test_should_render_js_partial
508
- xhr :get, :partial, :format => 'js'
509
- assert_equal 'partial js', @response.body
1510
+ def test_request_with_bang_obeys_last_modified
1511
+ @request.if_modified_since = @last_modified
1512
+ get :conditional_hello_with_bangs
1513
+ assert_response :not_modified
510
1514
  end
511
1515
 
512
- def test_should_render_with_alternate_default_render
513
- xhr :get, :render_alternate_default
514
- assert_equal %(Element.replace("foo", "partial html");), @response.body
1516
+ def test_last_modified_works_with_less_than_too
1517
+ @request.if_modified_since = 5.years.ago.httpdate
1518
+ get :conditional_hello_with_bangs
1519
+ assert_response :success
515
1520
  end
1521
+ end
516
1522
 
517
- def test_should_render_xml_but_keep_custom_content_type
518
- get :render_xml_with_custom_content_type
519
- assert_equal "application/atomsvc+xml", @response.content_type
1523
+ class RenderingLoggingTest < Test::Unit::TestCase
1524
+ def setup
1525
+ @request = ActionController::TestRequest.new
1526
+ @response = ActionController::TestResponse.new
1527
+ @controller = TestController.new
1528
+
1529
+ @request.host = "www.nextangle.com"
520
1530
  end
521
1531
 
522
- protected
523
-
524
- def etag_for(text)
525
- %("#{Digest::MD5.hexdigest(text)}")
526
- end
1532
+ def test_logger_prints_layout_and_template_rendering_info
1533
+ @controller.logger = MockLogger.new
1534
+ get :layout_test
1535
+ logged = @controller.logger.logged.find_all {|l| l =~ /render/i }
1536
+ assert_equal "Rendering template within layouts/standard", logged[0]
1537
+ assert_equal "Rendering test/hello_world", logged[1]
1538
+ end
527
1539
  end