actionpack 2.1.0 → 2.1.1

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 (60) hide show
  1. data/CHANGELOG +17 -0
  2. data/Rakefile +10 -6
  3. data/lib/action_controller.rb +0 -0
  4. data/lib/action_controller/assertions/response_assertions.rb +1 -1
  5. data/lib/action_controller/assertions/selector_assertions.rb +26 -46
  6. data/lib/action_controller/base.rb +8 -4
  7. data/lib/action_controller/dispatcher.rb +1 -1
  8. data/lib/action_controller/filters.rb +194 -195
  9. data/lib/action_controller/polymorphic_routes.rb +25 -12
  10. data/lib/action_controller/record_identifier.rb +20 -13
  11. data/lib/action_controller/request.rb +9 -6
  12. data/lib/action_controller/request_profiler.rb +0 -0
  13. data/lib/action_controller/response.rb +0 -0
  14. data/lib/action_controller/routing.rb +5 -1
  15. data/lib/action_controller/routing/builder.rb +1 -2
  16. data/lib/action_controller/routing/segments.rb +1 -1
  17. data/lib/action_controller/templates/rescues/layout.erb +1 -1
  18. data/lib/action_controller/test_process.rb +4 -2
  19. data/lib/action_controller/vendor/html-scanner/html/document.rb +1 -1
  20. data/lib/action_controller/verification.rb +1 -1
  21. data/lib/action_pack/version.rb +1 -1
  22. data/lib/action_view/base.rb +7 -3
  23. data/lib/action_view/helpers/asset_tag_helper.rb +14 -11
  24. data/lib/action_view/helpers/date_helper.rb +3 -3
  25. data/lib/action_view/helpers/form_helper.rb +5 -1
  26. data/lib/action_view/helpers/form_options_helper.rb +2 -2
  27. data/lib/action_view/helpers/form_tag_helper.rb +5 -3
  28. data/lib/action_view/helpers/javascript_helper.rb +4 -4
  29. data/lib/action_view/helpers/prototype_helper.rb +7 -7
  30. data/lib/action_view/helpers/tag_helper.rb +4 -3
  31. data/lib/action_view/helpers/text_helper.rb +1 -1
  32. data/lib/action_view/helpers/url_helper.rb +3 -5
  33. data/lib/action_view/partial_template.rb +1 -1
  34. data/test/controller/action_pack_assertions_test.rb +24 -5
  35. data/test/controller/assert_select_test.rb +6 -1
  36. data/test/controller/base_test.rb +37 -1
  37. data/test/controller/cgi_test.rb +0 -0
  38. data/test/controller/dispatcher_test.rb +2 -2
  39. data/test/controller/html-scanner/document_test.rb +25 -0
  40. data/test/controller/integration_upload_test.rb +1 -1
  41. data/test/controller/new_render_test.rb +22 -3
  42. data/test/controller/polymorphic_routes_test.rb +33 -0
  43. data/test/controller/redirect_test.rb +0 -0
  44. data/test/controller/render_test.rb +1 -1
  45. data/test/controller/request_test.rb +6 -0
  46. data/test/controller/resources_test.rb +15 -17
  47. data/test/controller/routing_test.rb +22 -2
  48. data/test/controller/session/cookie_store_test.rb +0 -0
  49. data/test/controller/test_test.rb +11 -2
  50. data/test/controller/verification_test.rb +34 -17
  51. data/test/fixtures/test/render_file_from_template.html.erb +1 -0
  52. data/test/template/date_helper_test.rb +59 -8
  53. data/test/template/deprecated_erb_variable_test.rb +9 -0
  54. data/test/template/form_options_helper_test.rb +505 -514
  55. data/test/template/form_tag_helper_test.rb +13 -0
  56. data/test/template/javascript_helper_test.rb +7 -4
  57. data/test/template/prototype_helper_test.rb +14 -6
  58. data/test/template/text_helper_test.rb +1 -0
  59. data/test/template/url_helper_test.rb +11 -1
  60. metadata +8 -4
@@ -80,10 +80,9 @@ module ActionView
80
80
  # return false;">Show me more</a>
81
81
  #
82
82
  def link_to_function(name, *args, &block)
83
- html_options = args.extract_options!
83
+ html_options = args.extract_options!.symbolize_keys
84
84
  function = args[0] || ''
85
85
 
86
- html_options.symbolize_keys!
87
86
  function = update_page(&block) if block_given?
88
87
  content_tag(
89
88
  "a", name,
@@ -111,10 +110,9 @@ module ActionView
111
110
  # page[:details].visual_effect :toggle_slide
112
111
  # end
113
112
  def button_to_function(name, *args, &block)
114
- html_options = args.extract_options!
113
+ html_options = args.extract_options!.symbolize_keys
115
114
  function = args[0] || ''
116
115
 
117
- html_options.symbolize_keys!
118
116
  function = update_page(&block) if block_given?
119
117
  tag(:input, html_options.merge({
120
118
  :type => "button", :value => name,
@@ -147,6 +145,8 @@ module ActionView
147
145
  javascript << '</script>'
148
146
  end
149
147
 
148
+ deprecate :define_javascript_functions=>"use javascript_include_tag instead"
149
+
150
150
  # Escape carrier returns and single and double quotes for JavaScript segments.
151
151
  def escape_javascript(javascript)
152
152
  (javascript || '').gsub('\\','\0\0').gsub('</','<\/').gsub(/\r\n|\n|\r/, "\\n").gsub(/["']/) { |m| "\\#{m}" }
@@ -111,7 +111,7 @@ module ActionView
111
111
  (100..599).to_a)
112
112
  AJAX_OPTIONS = Set.new([ :before, :after, :condition, :url,
113
113
  :asynchronous, :method, :insertion, :position,
114
- :form, :with, :update, :script ]).merge(CALLBACKS)
114
+ :form, :with, :update, :script, :type ]).merge(CALLBACKS)
115
115
  end
116
116
 
117
117
  # Returns a link to a remote action defined by <tt>options[:url]</tt>
@@ -603,7 +603,7 @@ module ActionView
603
603
  # Example:
604
604
  #
605
605
  # # Generates:
606
- # # new Insertion.Bottom("list", "<li>Some item</li>");
606
+ # # new Element.insert("list", { bottom: <li>Some item</li>" });
607
607
  # # new Effect.Highlight("list");
608
608
  # # ["status-indicator", "cancel-link"].each(Element.hide);
609
609
  # update_page do |page|
@@ -736,16 +736,16 @@ module ActionView
736
736
  #
737
737
  # # Insert the rendered 'navigation' partial just before the DOM
738
738
  # # element with ID 'content'.
739
- # # Generates: new Insertion.Before("content", "-- Contents of 'navigation' partial --");
739
+ # # Generates: Element.insert("content", { before: "-- Contents of 'navigation' partial --" });
740
740
  # page.insert_html :before, 'content', :partial => 'navigation'
741
741
  #
742
742
  # # Add a list item to the bottom of the <ul> with ID 'list'.
743
- # # Generates: new Insertion.Bottom("list", "<li>Last item</li>");
743
+ # # Generates: Element.insert("list", { bottom: "<li>Last item</li>" });
744
744
  # page.insert_html :bottom, 'list', '<li>Last item</li>'
745
745
  #
746
746
  def insert_html(position, id, *options_for_render)
747
- insertion = position.to_s.camelize
748
- call "new Insertion.#{insertion}", id, render(*options_for_render)
747
+ content = javascript_object_for(render(*options_for_render))
748
+ record "Element.insert(\"#{id}\", { #{position.to_s.downcase}: #{content} });"
749
749
  end
750
750
 
751
751
  # Replaces the inner HTML of the DOM element with the given +id+.
@@ -1039,7 +1039,7 @@ module ActionView
1039
1039
 
1040
1040
  js_options['asynchronous'] = options[:type] != :synchronous
1041
1041
  js_options['method'] = method_option_to_s(options[:method]) if options[:method]
1042
- js_options['insertion'] = "Insertion.#{options[:position].to_s.camelize}" if options[:position]
1042
+ js_options['insertion'] = "'#{options[:position].to_s.downcase}'" if options[:position]
1043
1043
  js_options['evalScripts'] = options[:script].nil? || options[:script]
1044
1044
 
1045
1045
  if options[:form]
@@ -1,5 +1,6 @@
1
1
  require 'cgi'
2
2
  require 'erb'
3
+ require 'set'
3
4
 
4
5
  module ActionView
5
6
  module Helpers #:nodoc:
@@ -8,7 +9,8 @@ module ActionView
8
9
  module TagHelper
9
10
  include ERB::Util
10
11
 
11
- BOOLEAN_ATTRIBUTES = Set.new(%w(disabled readonly multiple))
12
+ BOOLEAN_ATTRIBUTES = %w(disabled readonly multiple).to_set
13
+ BOOLEAN_ATTRIBUTES.merge(BOOLEAN_ATTRIBUTES.map(&:to_sym))
12
14
 
13
15
  # Returns an empty HTML tag of type +name+ which by default is XHTML
14
16
  # compliant. Set +open+ to true to create an open tag compatible
@@ -37,7 +39,7 @@ module ActionView
37
39
  # tag("img", { :src => "open &amp; shut.png" }, false, false)
38
40
  # # => <img src="open &amp; shut.png" />
39
41
  def tag(name, options = nil, open = false, escape = true)
40
- "<#{name}#{tag_options(options, escape) if options}" + (open ? ">" : " />")
42
+ "<#{name}#{tag_options(options, escape) if options}#{open ? ">" : " />"}"
41
43
  end
42
44
 
43
45
  # Returns an HTML block tag of type +name+ surrounding the +content+. Add
@@ -114,7 +116,6 @@ module ActionView
114
116
  if escape
115
117
  options.each do |key, value|
116
118
  next unless value
117
- key = key.to_s
118
119
  value = BOOLEAN_ATTRIBUTES.include?(key) ? key : escape_once(value)
119
120
  attrs << %(#{key}="#{value}")
120
121
  end
@@ -464,7 +464,7 @@ module ActionView
464
464
  [-\w]+ # subdomain or domain
465
465
  (?:\.[-\w]+)* # remaining subdomains or domain
466
466
  (?::\d+)? # port
467
- (?:/(?:(?:[~\w\+@%=\(\)-]|(?:[,.;:][^\s$]))+)?)* # path
467
+ (?:/(?:(?:[~\w\+@%=\(\)-]|(?:[,.;:'][^\s$]))+)?)* # path
468
468
  (?:\?[\w\+@%&=.;-]+)? # query string
469
469
  (?:\#[\w\-]*)? # trailing anchor
470
470
  )
@@ -63,17 +63,15 @@ module ActionView
63
63
  # # calls @workshop.to_s
64
64
  # # => /workshops/5
65
65
  def url_for(options = {})
66
+ options ||= {}
66
67
  case options
67
68
  when Hash
68
- show_path = options[:host].nil? ? true : false
69
- options = { :only_path => show_path }.update(options.symbolize_keys)
69
+ options = { :only_path => options[:host].nil? }.update(options.symbolize_keys)
70
70
  escape = options.key?(:escape) ? options.delete(:escape) : true
71
71
  url = @controller.send(:url_for, options)
72
72
  when String
73
73
  escape = true
74
74
  url = options
75
- when NilClass
76
- url = @controller.send(:url_for, nil)
77
75
  else
78
76
  escape = false
79
77
  url = polymorphic_path(options)
@@ -444,7 +442,7 @@ module ActionView
444
442
  email_address_obfuscated.gsub!(/\./, html_options.delete("replace_dot")) if html_options.has_key?("replace_dot")
445
443
 
446
444
  if encode == "javascript"
447
- "document.write('#{content_tag("a", name || email_address, html_options.merge({ "href" => "mailto:"+email_address+extras }))}');".each_byte do |c|
445
+ "document.write('#{content_tag("a", name || email_address_obfuscated, html_options.merge({ "href" => "mailto:"+email_address+extras }))}');".each_byte do |c|
448
446
  string << sprintf("%%%x", c)
449
447
  end
450
448
  "<script type=\"#{Mime::JS}\">eval(unescape('#{string}'))</script>"
@@ -22,10 +22,10 @@ module ActionView #:nodoc:
22
22
  end
23
23
 
24
24
  def render_member(object)
25
- @locals[@counter_name] += 1
26
25
  @locals[:object] = @locals[@variable_name] = object
27
26
 
28
27
  template = render_template
28
+ @locals[@counter_name] += 1
29
29
  @locals.delete(@variable_name)
30
30
  @locals.delete(:object)
31
31
 
@@ -137,6 +137,9 @@ class AssertResponseWithUnexpectedErrorController < ActionController::Base
137
137
  end
138
138
  end
139
139
 
140
+ class UserController < ActionController::Base
141
+ end
142
+
140
143
  module Admin
141
144
  class InnerModuleController < ActionController::Base
142
145
  def index
@@ -174,7 +177,7 @@ class ActionPackAssertionsControllerTest < Test::Unit::TestCase
174
177
  # let's get this party started
175
178
  def setup
176
179
  ActionController::Routing::Routes.reload
177
- ActionController::Routing.use_controllers!(%w(action_pack_assertions admin/inner_module content admin/user))
180
+ ActionController::Routing.use_controllers!(%w(action_pack_assertions admin/inner_module user content admin/user))
178
181
  @controller = ActionPackAssertionsController.new
179
182
  @request, @response = ActionController::TestRequest.new, ActionController::TestResponse.new
180
183
  end
@@ -268,7 +271,7 @@ class ActionPackAssertionsControllerTest < Test::Unit::TestCase
268
271
  assert_redirected_to admin_inner_module_path
269
272
  end
270
273
  end
271
-
274
+
272
275
  def test_assert_redirected_to_top_level_named_route_from_nested_controller
273
276
  with_routing do |set|
274
277
  set.draw do |map|
@@ -277,11 +280,25 @@ class ActionPackAssertionsControllerTest < Test::Unit::TestCase
277
280
  end
278
281
  @controller = Admin::InnerModuleController.new
279
282
  process :redirect_to_top_level_named_route
280
- # passes -> assert_redirected_to "http://test.host/action_pack_assertions/foo"
283
+ # assert_redirected_to "http://test.host/action_pack_assertions/foo" would pass because of exact match early return
281
284
  assert_redirected_to "/action_pack_assertions/foo"
282
285
  end
283
286
  end
284
287
 
288
+ def test_assert_redirected_to_top_level_named_route_with_same_controller_name_in_both_namespaces
289
+ with_routing do |set|
290
+ set.draw do |map|
291
+ # this controller exists in the admin namespace as well which is the only difference from previous test
292
+ map.top_level '/user/:id', :controller => 'user', :action => 'index'
293
+ map.connect ':controller/:action/:id'
294
+ end
295
+ @controller = Admin::InnerModuleController.new
296
+ process :redirect_to_top_level_named_route
297
+ # assert_redirected_to top_level_url('foo') would pass because of exact match early return
298
+ assert_redirected_to top_level_path('foo')
299
+ end
300
+ end
301
+
285
302
  # -- standard request/response object testing --------------------------------
286
303
 
287
304
  # make sure that the template objects exist
@@ -406,7 +423,7 @@ class ActionPackAssertionsControllerTest < Test::Unit::TestCase
406
423
  process :redirect_to_action
407
424
  assert_redirected_to :action => "flash_me"
408
425
 
409
- follow_redirect
426
+ assert_deprecated { follow_redirect }
410
427
  assert_equal 1, @request.parameters["id"].to_i
411
428
 
412
429
  assert "Inconceivable!", @response.body
@@ -416,7 +433,9 @@ class ActionPackAssertionsControllerTest < Test::Unit::TestCase
416
433
  process :redirect_to_controller
417
434
  assert_redirected_to :controller => "elsewhere", :action => "flash_me"
418
435
 
419
- assert_raises(RuntimeError, "Can't follow redirects outside of current controller (elsewhere)") { follow_redirect }
436
+ assert_raises(RuntimeError, "Can't follow redirects outside of current controller (elsewhere)") do
437
+ assert_deprecated { follow_redirect }
438
+ end
420
439
  end
421
440
 
422
441
  def test_assert_redirection_fails_with_incorrect_controller
@@ -568,7 +568,12 @@ class AssertSelectTest < Test::Unit::TestCase
568
568
  assert_select "div", 4
569
569
  end
570
570
  end
571
-
571
+
572
+ def test_assert_select_rjs_raise_errors
573
+ assert_raises(ArgumentError) { assert_select_rjs(:destroy) }
574
+ assert_raises(ArgumentError) { assert_select_rjs(:insert, :left) }
575
+ end
576
+
572
577
  # Simple selection from a single result.
573
578
  def test_nested_assert_select_rjs_with_single_result
574
579
  render_rjs do |page|
@@ -7,6 +7,7 @@ module Submodule
7
7
  end
8
8
  class ContainedNonEmptyController < ActionController::Base
9
9
  def public_action
10
+ render :nothing => true
10
11
  end
11
12
 
12
13
  hide_action :hidden_action
@@ -105,6 +106,18 @@ end
105
106
 
106
107
 
107
108
  class PerformActionTest < Test::Unit::TestCase
109
+ class MockLogger
110
+ attr_reader :logged
111
+
112
+ def initialize
113
+ @logged = []
114
+ end
115
+
116
+ def method_missing(method, *args)
117
+ @logged << args.first
118
+ end
119
+ end
120
+
108
121
  def use_controller(controller_class)
109
122
  @controller = controller_class.new
110
123
 
@@ -142,6 +155,13 @@ class PerformActionTest < Test::Unit::TestCase
142
155
  get :another_hidden_action
143
156
  assert_response 404
144
157
  end
158
+
159
+ def test_namespaced_action_should_log_module_name
160
+ use_controller Submodule::ContainedNonEmptyController
161
+ @controller.logger = MockLogger.new
162
+ get :public_action
163
+ assert_match /Processing\sSubmodule::ContainedNonEmptyController#public_action/, @controller.logger.logged[1]
164
+ end
145
165
  end
146
166
 
147
167
  class DefaultUrlOptionsTest < Test::Unit::TestCase
@@ -169,6 +189,22 @@ class DefaultUrlOptionsTest < Test::Unit::TestCase
169
189
  end
170
190
  end
171
191
 
192
+ class EmptyUrlOptionsTest < Test::Unit::TestCase
193
+ def setup
194
+ @controller = NonEmptyController.new
195
+
196
+ @request = ActionController::TestRequest.new
197
+ @response = ActionController::TestResponse.new
198
+
199
+ @request.host = 'www.example.com'
200
+ end
201
+
202
+ def test_ensure_url_for_works_as_expected_when_called_with_no_options_if_default_url_options_is_not_set
203
+ get :public_action
204
+ assert_equal "http://www.example.com/non_empty/public_action", @controller.url_for
205
+ end
206
+ end
207
+
172
208
  class EnsureNamedRoutesWorksTicket22BugTest < Test::Unit::TestCase
173
209
  def test_named_routes_still_work
174
210
  ActionController::Routing::Routes.draw do |map|
@@ -180,4 +216,4 @@ class EnsureNamedRoutesWorksTicket22BugTest < Test::Unit::TestCase
180
216
  ensure
181
217
  ActionController::Routing::Routes.load!
182
218
  end
183
- end
219
+ end
File without changes
@@ -27,14 +27,14 @@ class DispatcherTest < Test::Unit::TestCase
27
27
 
28
28
  def test_clears_dependencies_after_dispatch_if_in_loading_mode
29
29
  ActionController::Routing::Routes.expects(:reload).once
30
- Dependencies.expects(:clear).once
30
+ ActiveSupport::Dependencies.expects(:clear).once
31
31
 
32
32
  dispatch(@output, false)
33
33
  end
34
34
 
35
35
  def test_leaves_dependencies_after_dispatch_if_not_in_loading_mode
36
36
  ActionController::Routing::Routes.expects(:reload).never
37
- Dependencies.expects(:clear).never
37
+ ActiveSupport::Dependencies.expects(:clear).never
38
38
 
39
39
  dispatch
40
40
  end
@@ -120,4 +120,29 @@ HTML
120
120
  assert doc.find(:tag => "div", :attributes => { :id => "map" }, :content => "")
121
121
  assert doc.find(:tag => "div", :attributes => { :id => "map" }, :content => nil)
122
122
  end
123
+
124
+ def test_parse_invalid_document
125
+ assert_nothing_raised do
126
+ doc = HTML::Document.new("<html>
127
+ <table>
128
+ <tr>
129
+ <td style=\"color: #FFFFFF; height: 17px; onclick=\"window.location.href='http://www.rmeinc.com/about_rme.aspx'\" style=\"cursor:pointer; height: 17px;\"; nowrap onclick=\"window.location.href='http://www.rmeinc.com/about_rme.aspx'\" onmouseout=\"this.bgColor='#0066cc'; this.style.color='#FFFFFF'\" onmouseover=\"this.bgColor='#ffffff'; this.style.color='#0033cc'\">About Us</td>
130
+ </tr>
131
+ </table>
132
+ </html>")
133
+ end
134
+ end
135
+
136
+ def test_invalid_document_raises_exception_when_strict
137
+ assert_raises RuntimeError do
138
+ doc = HTML::Document.new("<html>
139
+ <table>
140
+ <tr>
141
+ <td style=\"color: #FFFFFF; height: 17px; onclick=\"window.location.href='http://www.rmeinc.com/about_rme.aspx'\" style=\"cursor:pointer; height: 17px;\"; nowrap onclick=\"window.location.href='http://www.rmeinc.com/about_rme.aspx'\" onmouseout=\"this.bgColor='#0066cc'; this.style.color='#FFFFFF'\" onmouseover=\"this.bgColor='#ffffff'; this.style.color='#0033cc'\">About Us</td>
142
+ </tr>
143
+ </table>
144
+ </html>", true)
145
+ end
146
+ end
147
+
123
148
  end
@@ -28,7 +28,7 @@ class SessionUploadTest < ActionController::IntegrationTest
28
28
  # end
29
29
  def test_post_with_upload
30
30
  uses_mocha "test_post_with_upload" do
31
- Dependencies.stubs(:load?).returns(false)
31
+ ActiveSupport::Dependencies.stubs(:load?).returns(false)
32
32
  with_routing do |set|
33
33
  set.draw do |map|
34
34
  map.update 'update', :controller => "upload_test", :action => "update", :method => :post
@@ -68,6 +68,11 @@ class NewRenderTestController < ActionController::Base
68
68
  path = File.join(File.dirname(__FILE__), '../fixtures/test/render_file_with_ivar.erb')
69
69
  render :file => path
70
70
  end
71
+
72
+ def render_file_from_template
73
+ @secret = 'in the sauce'
74
+ @path = File.expand_path(File.join(File.dirname(__FILE__), '../fixtures/test/render_file_with_ivar.erb'))
75
+ end
71
76
 
72
77
  def render_file_with_locals
73
78
  path = File.join(File.dirname(__FILE__), '../fixtures/test/render_file_with_locals.erb')
@@ -259,6 +264,10 @@ class NewRenderTestController < ActionController::Base
259
264
  render :template => "test/hello_world"
260
265
  end
261
266
 
267
+ def render_with_explicit_template_with_locals
268
+ render :template => "test/render_file_with_locals", :locals => { :secret => 'area51' }
269
+ end
270
+
262
271
  def double_render
263
272
  render :text => "hello"
264
273
  render :text => "world"
@@ -531,6 +540,11 @@ class NewRenderTest < Test::Unit::TestCase
531
540
  get :render_file_with_locals
532
541
  assert_equal "The secret is in the sauce\n", @response.body
533
542
  end
543
+
544
+ def test_render_file_from_template
545
+ get :render_file_from_template
546
+ assert_equal "The secret is in the sauce\n", @response.body
547
+ end
534
548
 
535
549
  def test_attempt_to_access_object_method
536
550
  assert_raises(ActionController::UnknownAction, "No action responded to [clone]") { get :clone }
@@ -742,7 +756,7 @@ EOS
742
756
 
743
757
  def test_partial_collection_with_counter
744
758
  get :partial_collection_with_counter
745
- assert_equal "david1mary2", @response.body
759
+ assert_equal "david0mary1", @response.body
746
760
  end
747
761
 
748
762
  def test_partial_collection_with_locals
@@ -762,7 +776,7 @@ EOS
762
776
 
763
777
  def test_partial_collection_shorthand_with_different_types_of_records
764
778
  get :partial_collection_shorthand_with_different_types_of_records
765
- assert_equal "Bonjour bad customer: mark1Bonjour good customer: craig2Bonjour bad customer: john3Bonjour good customer: zach4Bonjour good customer: brandon5Bonjour bad customer: dan6", @response.body
779
+ assert_equal "Bonjour bad customer: mark0Bonjour good customer: craig1Bonjour bad customer: john2Bonjour good customer: zach3Bonjour good customer: brandon4Bonjour bad customer: dan5", @response.body
766
780
  end
767
781
 
768
782
  def test_empty_partial_collection
@@ -800,7 +814,12 @@ EOS
800
814
  get :render_text_with_assigns
801
815
  assert_equal "world", assigns["hello"]
802
816
  end
803
-
817
+
818
+ def test_template_with_locals
819
+ get :render_with_explicit_template_with_locals
820
+ assert_equal "The secret is area51\n", @response.body
821
+ end
822
+
804
823
  def test_update_page
805
824
  get :update_page
806
825
  assert_template nil
@@ -118,6 +118,39 @@ uses_mocha 'polymorphic URL helpers' do
118
118
  polymorphic_url([:site, :admin, @article, @response, @tag])
119
119
  end
120
120
 
121
+ def test_nesting_with_array_ending_in_singleton_resource
122
+ expects(:article_response_url).with(@article)
123
+ polymorphic_url([@article, :response])
124
+ end
125
+
126
+ def test_nesting_with_array_containing_singleton_resource
127
+ @tag = Tag.new
128
+ @tag.save
129
+ expects(:article_response_tag_url).with(@article, @tag)
130
+ polymorphic_url([@article, :response, @tag])
131
+ end
132
+
133
+ def test_nesting_with_array_containing_namespace_and_singleton_resource
134
+ @tag = Tag.new
135
+ @tag.save
136
+ expects(:admin_article_response_tag_url).with(@article, @tag)
137
+ polymorphic_url([:admin, @article, :response, @tag])
138
+ end
139
+
140
+ def test_nesting_with_array_containing_singleton_resource_and_format
141
+ @tag = Tag.new
142
+ @tag.save
143
+ expects(:formatted_article_response_tag_url).with(@article, @tag, :pdf)
144
+ formatted_polymorphic_url([@article, :response, @tag, :pdf])
145
+ end
146
+
147
+ def test_nesting_with_array_containing_singleton_resource_and_format_option
148
+ @tag = Tag.new
149
+ @tag.save
150
+ expects(:article_response_tag_url).with(@article, @tag, :pdf)
151
+ polymorphic_url([@article, :response, @tag], :format => :pdf)
152
+ end
153
+
121
154
  # TODO: Needs to be updated to correctly know about whether the object is in a hash or not
122
155
  def xtest_with_hash
123
156
  expects(:article_url).with(@article)