actionpack 2.3.2 → 2.3.3

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 (117) hide show
  1. data/CHANGELOG +5 -0
  2. data/Rakefile +10 -9
  3. data/lib/action_controller.rb +2 -7
  4. data/lib/action_controller/assertions/response_assertions.rb +11 -3
  5. data/lib/action_controller/base.rb +7 -2
  6. data/lib/action_controller/caching.rb +1 -1
  7. data/lib/action_controller/caching/actions.rb +9 -1
  8. data/lib/action_controller/caching/sweeper.rb +45 -0
  9. data/lib/action_controller/caching/sweeping.rb +0 -42
  10. data/lib/action_controller/failsafe.rb +40 -6
  11. data/lib/action_controller/flash.rb +11 -3
  12. data/lib/action_controller/http_authentication.rb +5 -2
  13. data/lib/action_controller/integration.rb +5 -12
  14. data/lib/action_controller/middlewares.rb +0 -1
  15. data/lib/action_controller/reloader.rb +34 -3
  16. data/lib/action_controller/request.rb +6 -2
  17. data/lib/action_controller/response.rb +2 -2
  18. data/lib/action_controller/routing/route_set.rb +2 -1
  19. data/lib/action_controller/streaming.rb +1 -1
  20. data/lib/action_controller/test_process.rb +9 -1
  21. data/lib/action_pack/version.rb +1 -1
  22. data/lib/action_view/helpers.rb +1 -1
  23. data/lib/action_view/helpers/asset_tag_helper.rb +21 -9
  24. data/lib/action_view/helpers/date_helper.rb +2 -2
  25. data/lib/action_view/helpers/form_helper.rb +25 -12
  26. data/lib/action_view/helpers/form_options_helper.rb +2 -0
  27. data/lib/action_view/helpers/form_tag_helper.rb +10 -4
  28. data/lib/action_view/helpers/number_helper.rb +1 -1
  29. data/lib/action_view/helpers/prototype_helper.rb +7 -7
  30. data/lib/action_view/helpers/scriptaculous_helper.rb +5 -5
  31. data/lib/action_view/helpers/text_helper.rb +3 -3
  32. data/lib/action_view/helpers/url_helper.rb +1 -1
  33. data/lib/action_view/paths.rb +1 -1
  34. data/lib/action_view/template.rb +22 -33
  35. data/test/abstract_unit.rb +1 -1
  36. data/test/activerecord/active_record_store_test.rb +3 -3
  37. data/test/controller/action_pack_assertions_test.rb +27 -0
  38. data/test/controller/caching_test.rb +39 -0
  39. data/test/controller/cookie_test.rb +10 -0
  40. data/test/controller/dispatcher_test.rb +9 -7
  41. data/test/controller/failsafe_test.rb +60 -0
  42. data/test/controller/filter_params_test.rb +2 -1
  43. data/test/controller/flash_test.rb +6 -1
  44. data/test/controller/http_digest_authentication_test.rb +34 -3
  45. data/test/controller/integration_test.rb +31 -3
  46. data/test/controller/redirect_test.rb +4 -1
  47. data/test/controller/reloader_test.rb +97 -0
  48. data/test/controller/render_test.rb +19 -9
  49. data/test/controller/request/multipart_params_parsing_test.rb +1 -62
  50. data/test/controller/request/test_request_test.rb +35 -0
  51. data/test/controller/request/url_encoded_params_parsing_test.rb +0 -38
  52. data/test/controller/request_test.rb +218 -230
  53. data/test/controller/resources_test.rb +8 -0
  54. data/test/controller/routing_test.rb +21 -0
  55. data/test/controller/send_file_test.rb +1 -1
  56. data/test/controller/session/cookie_store_test.rb +9 -32
  57. data/test/controller/test_test.rb +8 -0
  58. data/test/fixtures/failsafe/500.html +1 -0
  59. data/test/template/active_record_helper_test.rb +1 -1
  60. data/test/template/asset_tag_helper_test.rb +46 -0
  61. data/test/template/form_helper_test.rb +117 -6
  62. data/test/template/form_options_helper_test.rb +22 -0
  63. data/test/template/form_tag_helper_test.rb +23 -6
  64. data/test/template/prototype_helper_test.rb +11 -11
  65. data/test/template/template_test.rb +32 -0
  66. metadata +20 -63
  67. data/lib/action_controller/rewindable_input.rb +0 -28
  68. data/lib/action_controller/vendor/rack-1.0/rack.rb +0 -89
  69. data/lib/action_controller/vendor/rack-1.0/rack/adapter/camping.rb +0 -22
  70. data/lib/action_controller/vendor/rack-1.0/rack/auth/abstract/handler.rb +0 -37
  71. data/lib/action_controller/vendor/rack-1.0/rack/auth/abstract/request.rb +0 -37
  72. data/lib/action_controller/vendor/rack-1.0/rack/auth/basic.rb +0 -58
  73. data/lib/action_controller/vendor/rack-1.0/rack/auth/digest/md5.rb +0 -124
  74. data/lib/action_controller/vendor/rack-1.0/rack/auth/digest/nonce.rb +0 -51
  75. data/lib/action_controller/vendor/rack-1.0/rack/auth/digest/params.rb +0 -55
  76. data/lib/action_controller/vendor/rack-1.0/rack/auth/digest/request.rb +0 -40
  77. data/lib/action_controller/vendor/rack-1.0/rack/auth/openid.rb +0 -480
  78. data/lib/action_controller/vendor/rack-1.0/rack/builder.rb +0 -63
  79. data/lib/action_controller/vendor/rack-1.0/rack/cascade.rb +0 -36
  80. data/lib/action_controller/vendor/rack-1.0/rack/chunked.rb +0 -49
  81. data/lib/action_controller/vendor/rack-1.0/rack/commonlogger.rb +0 -61
  82. data/lib/action_controller/vendor/rack-1.0/rack/conditionalget.rb +0 -45
  83. data/lib/action_controller/vendor/rack-1.0/rack/content_length.rb +0 -29
  84. data/lib/action_controller/vendor/rack-1.0/rack/content_type.rb +0 -23
  85. data/lib/action_controller/vendor/rack-1.0/rack/deflater.rb +0 -85
  86. data/lib/action_controller/vendor/rack-1.0/rack/directory.rb +0 -153
  87. data/lib/action_controller/vendor/rack-1.0/rack/file.rb +0 -88
  88. data/lib/action_controller/vendor/rack-1.0/rack/handler.rb +0 -48
  89. data/lib/action_controller/vendor/rack-1.0/rack/handler/cgi.rb +0 -61
  90. data/lib/action_controller/vendor/rack-1.0/rack/handler/evented_mongrel.rb +0 -8
  91. data/lib/action_controller/vendor/rack-1.0/rack/handler/fastcgi.rb +0 -89
  92. data/lib/action_controller/vendor/rack-1.0/rack/handler/lsws.rb +0 -55
  93. data/lib/action_controller/vendor/rack-1.0/rack/handler/mongrel.rb +0 -84
  94. data/lib/action_controller/vendor/rack-1.0/rack/handler/scgi.rb +0 -59
  95. data/lib/action_controller/vendor/rack-1.0/rack/handler/swiftiplied_mongrel.rb +0 -8
  96. data/lib/action_controller/vendor/rack-1.0/rack/handler/thin.rb +0 -18
  97. data/lib/action_controller/vendor/rack-1.0/rack/handler/webrick.rb +0 -67
  98. data/lib/action_controller/vendor/rack-1.0/rack/head.rb +0 -19
  99. data/lib/action_controller/vendor/rack-1.0/rack/lint.rb +0 -462
  100. data/lib/action_controller/vendor/rack-1.0/rack/lobster.rb +0 -65
  101. data/lib/action_controller/vendor/rack-1.0/rack/lock.rb +0 -16
  102. data/lib/action_controller/vendor/rack-1.0/rack/methodoverride.rb +0 -27
  103. data/lib/action_controller/vendor/rack-1.0/rack/mime.rb +0 -204
  104. data/lib/action_controller/vendor/rack-1.0/rack/mock.rb +0 -160
  105. data/lib/action_controller/vendor/rack-1.0/rack/recursive.rb +0 -57
  106. data/lib/action_controller/vendor/rack-1.0/rack/reloader.rb +0 -64
  107. data/lib/action_controller/vendor/rack-1.0/rack/request.rb +0 -241
  108. data/lib/action_controller/vendor/rack-1.0/rack/response.rb +0 -179
  109. data/lib/action_controller/vendor/rack-1.0/rack/session/abstract/id.rb +0 -142
  110. data/lib/action_controller/vendor/rack-1.0/rack/session/cookie.rb +0 -91
  111. data/lib/action_controller/vendor/rack-1.0/rack/session/memcache.rb +0 -109
  112. data/lib/action_controller/vendor/rack-1.0/rack/session/pool.rb +0 -100
  113. data/lib/action_controller/vendor/rack-1.0/rack/showexceptions.rb +0 -349
  114. data/lib/action_controller/vendor/rack-1.0/rack/showstatus.rb +0 -106
  115. data/lib/action_controller/vendor/rack-1.0/rack/static.rb +0 -38
  116. data/lib/action_controller/vendor/rack-1.0/rack/urlmap.rb +0 -55
  117. data/lib/action_controller/vendor/rack-1.0/rack/utils.rb +0 -392
@@ -120,6 +120,14 @@ class ResourcesTest < ActionController::TestCase
120
120
  end
121
121
  end
122
122
 
123
+ def test_irregular_id_requirements_should_get_passed_to_member_actions
124
+ expected_options = {:controller => 'messages', :action => 'custom', :id => '1.1.1'}
125
+
126
+ with_restful_routing(:messages, :member => {:custom => :get}, :requirements => {:id => /[0-9]\.[0-9]\.[0-9]/}) do
127
+ assert_recognizes(expected_options, :path => 'messages/1.1.1/custom', :method => :get)
128
+ end
129
+ end
130
+
123
131
  def test_with_path_prefix
124
132
  with_restful_routing :messages, :path_prefix => '/thread/:thread_id' do
125
133
  assert_simply_restful_for :messages, :path_prefix => 'thread/5/', :options => { :thread_id => '5' }
@@ -1662,6 +1662,17 @@ class RouteSetTest < Test::Unit::TestCase
1662
1662
  assert_equal 1, set.routes.size
1663
1663
  end
1664
1664
 
1665
+ def test_draw_symbol_controller_name
1666
+ assert_equal 0, set.routes.size
1667
+ set.draw do |map|
1668
+ map.connect '/users/index', :controller => :users, :action => :index
1669
+ end
1670
+ @request = ActionController::TestRequest.new
1671
+ @request.request_uri = '/users/index'
1672
+ assert_nothing_raised { set.recognize(@request) }
1673
+ assert_equal 1, set.routes.size
1674
+ end
1675
+
1665
1676
  def test_named_draw
1666
1677
  assert_equal 0, set.routes.size
1667
1678
  set.draw do |map|
@@ -2476,6 +2487,16 @@ class RouteSetTest < Test::Unit::TestCase
2476
2487
  end
2477
2488
  assert_equal({:controller => 'pages', :action => 'show', :name => 'JAMIS'}, set.recognize_path('/page/JAMIS'))
2478
2489
  end
2490
+
2491
+ def test_routes_with_symbols
2492
+ set.draw do |map|
2493
+ map.connect 'unnamed', :controller => :pages, :action => :show, :name => :as_symbol
2494
+ map.named 'named', :controller => :pages, :action => :show, :name => :as_symbol
2495
+ end
2496
+ assert_equal({:controller => 'pages', :action => 'show', :name => :as_symbol}, set.recognize_path('/unnamed'))
2497
+ assert_equal({:controller => 'pages', :action => 'show', :name => :as_symbol}, set.recognize_path('/named'))
2498
+ end
2499
+
2479
2500
  end
2480
2501
 
2481
2502
  class RouteLoadingTest < Test::Unit::TestCase
@@ -108,7 +108,7 @@ class SendFileTest < ActionController::TestCase
108
108
  @controller.send(:send_file_headers!, options)
109
109
 
110
110
  h = @controller.headers
111
- assert_equal 1, h['Content-Length']
111
+ assert_equal '1', h['Content-Length']
112
112
  assert_equal 'image/png', h['Content-Type']
113
113
  assert_equal 'disposition; filename="filename"', h['Content-Disposition']
114
114
  assert_equal 'binary', h['Content-Transfer-Encoding']
@@ -193,38 +193,6 @@ class CookieStoreTest < ActionController::IntegrationTest
193
193
  end
194
194
  end
195
195
 
196
- def test_session_store_with_expire_after
197
- app = ActionController::Session::CookieStore.new(DispatcherApp, :key => SessionKey, :secret => SessionSecret, :expire_after => 5.hours)
198
- @integration_session = open_session(app)
199
-
200
- with_test_route_set do
201
- # First request accesses the session
202
- time = Time.local(2008, 4, 24)
203
- Time.stubs(:now).returns(time)
204
- expected_expiry = (time + 5.hours).gmtime.strftime("%a, %d-%b-%Y %H:%M:%S GMT")
205
-
206
- cookies[SessionKey] = SignedBar
207
-
208
- get '/set_session_value'
209
- assert_response :success
210
-
211
- cookie_body = response.body
212
- assert_equal "_myapp_session=#{cookie_body}; path=/; expires=#{expected_expiry}; HttpOnly",
213
- headers['Set-Cookie']
214
-
215
- # Second request does not access the session
216
- time = Time.local(2008, 4, 25)
217
- Time.stubs(:now).returns(time)
218
- expected_expiry = (time + 5.hours).gmtime.strftime("%a, %d-%b-%Y %H:%M:%S GMT")
219
-
220
- get '/no_session_access'
221
- assert_response :success
222
-
223
- assert_equal "_myapp_session=#{cookie_body}; path=/; expires=#{expected_expiry}; HttpOnly",
224
- headers['Set-Cookie']
225
- end
226
- end
227
-
228
196
  private
229
197
  def with_test_route_set
230
198
  with_routing do |set|
@@ -236,4 +204,13 @@ class CookieStoreTest < ActionController::IntegrationTest
236
204
  yield
237
205
  end
238
206
  end
207
+
208
+ def unmarshal_session(cookie_string)
209
+ session = Rack::Utils.parse_query(cookie_string, ';,').inject({}) {|h,(k,v)|
210
+ h[k] = Array === v ? v.first : v
211
+ h
212
+ }[SessionKey]
213
+ verifier = ActiveSupport::MessageVerifier.new(SessionSecret, 'SHA1')
214
+ verifier.verify(session)
215
+ end
239
216
  end
@@ -515,6 +515,14 @@ XML
515
515
  assert_nil @request.instance_variable_get("@request_method")
516
516
  end
517
517
 
518
+ def test_params_reset_after_post_request
519
+ post :no_op, :foo => "bar"
520
+ assert_equal "bar", @request.params[:foo]
521
+ @request.recycle!
522
+ post :no_op
523
+ assert @request.params[:foo].blank?
524
+ end
525
+
518
526
  %w(controller response request).each do |variable|
519
527
  %w(get post put delete head process).each do |method|
520
528
  define_method("test_#{variable}_missing_for_#{method}_raises_error") do
@@ -0,0 +1 @@
1
+ hello <%= "my" %> world
@@ -170,7 +170,7 @@ class ActiveRecordHelperTest < ActionView::TestCase
170
170
  @request_forgery_protection_token = 'authenticity_token'
171
171
  @form_authenticity_token = '123'
172
172
  assert_dom_equal(
173
- %(<form action="create" method="post"><div style='margin:0;padding:0'><input type='hidden' name='authenticity_token' value='123' /></div><p><label for="post_title">Title</label><br /><input id="post_title" name="post[title]" size="30" type="text" value="Hello World" /></p>\n<p><label for="post_body">Body</label><br /><div class="fieldWithErrors"><textarea cols="40" id="post_body" name="post[body]" rows="20">Back to the hill and over it again!</textarea></div></p><input name="commit" type="submit" value="Create" /></form>),
173
+ %(<form action="create" method="post"><div style='margin:0;padding:0;display:inline'><input type='hidden' name='authenticity_token' value='123' /></div><p><label for="post_title">Title</label><br /><input id="post_title" name="post[title]" size="30" type="text" value="Hello World" /></p>\n<p><label for="post_body">Body</label><br /><div class="fieldWithErrors"><textarea cols="40" id="post_body" name="post[body]" rows="20">Back to the hill and over it again!</textarea></div></p><input name="commit" type="submit" value="Create" /></form>),
174
174
  form("post")
175
175
  )
176
176
  end
@@ -316,9 +316,17 @@ class AssetTagHelperTest < ActionView::TestCase
316
316
 
317
317
  assert File.exist?(File.join(ActionView::Helpers::AssetTagHelper::JAVASCRIPTS_DIR, 'money.js'))
318
318
 
319
+ assert_dom_equal(
320
+ %(<script src="http://a0.example.com/absolute/test.js" type="text/javascript"></script>),
321
+ javascript_include_tag(:all, :cache => "/absolute/test")
322
+ )
323
+
324
+ assert File.exist?(File.join(ActionView::Helpers::AssetTagHelper::ASSETS_DIR, 'absolute', 'test.js'))
325
+
319
326
  ensure
320
327
  FileUtils.rm_f(File.join(ActionView::Helpers::AssetTagHelper::JAVASCRIPTS_DIR, 'all.js'))
321
328
  FileUtils.rm_f(File.join(ActionView::Helpers::AssetTagHelper::JAVASCRIPTS_DIR, 'money.js'))
329
+ FileUtils.rm_f(File.join(ActionView::Helpers::AssetTagHelper::ASSETS_DIR, 'absolute'))
322
330
  end
323
331
 
324
332
  def test_caching_javascript_include_tag_when_caching_on_with_proc_asset_host
@@ -546,9 +554,47 @@ class AssetTagHelperTest < ActionView::TestCase
546
554
  )
547
555
 
548
556
  assert File.exist?(File.join(ActionView::Helpers::AssetTagHelper::STYLESHEETS_DIR, 'money.css'))
557
+
558
+ assert_dom_equal(
559
+ %(<link href="http://a0.example.com/absolute/test.css" media="screen" rel="stylesheet" type="text/css" />),
560
+ stylesheet_link_tag(:all, :cache => "/absolute/test")
561
+ )
562
+
563
+ assert File.exist?(File.join(ActionView::Helpers::AssetTagHelper::ASSETS_DIR, 'absolute', 'test.css'))
564
+ ensure
565
+ FileUtils.rm_f(File.join(ActionView::Helpers::AssetTagHelper::STYLESHEETS_DIR, 'all.css'))
566
+ FileUtils.rm_f(File.join(ActionView::Helpers::AssetTagHelper::STYLESHEETS_DIR, 'money.css'))
567
+ FileUtils.rm_f(File.join(ActionView::Helpers::AssetTagHelper::ASSETS_DIR, 'absolute'))
568
+ end
569
+
570
+ def test_concat_stylesheet_link_tag_when_caching_off
571
+ ENV["RAILS_ASSET_ID"] = ""
572
+
573
+ assert_dom_equal(
574
+ %(<link href="/stylesheets/all.css" media="screen" rel="stylesheet" type="text/css" />),
575
+ stylesheet_link_tag(:all, :concat => true)
576
+ )
577
+
578
+ expected = Dir["#{ActionView::Helpers::AssetTagHelper::STYLESHEETS_DIR}/*.css"].map { |p| File.mtime(p) }.max
579
+ assert_equal expected, File.mtime(File.join(ActionView::Helpers::AssetTagHelper::STYLESHEETS_DIR, 'all.css'))
580
+
581
+ assert_dom_equal(
582
+ %(<link href="/stylesheets/money.css" media="screen" rel="stylesheet" type="text/css" />),
583
+ stylesheet_link_tag(:all, :concat => "money")
584
+ )
585
+
586
+ assert File.exist?(File.join(ActionView::Helpers::AssetTagHelper::STYLESHEETS_DIR, 'money.css'))
587
+
588
+ assert_dom_equal(
589
+ %(<link href="/absolute/test.css" media="screen" rel="stylesheet" type="text/css" />),
590
+ stylesheet_link_tag(:all, :concat => "/absolute/test")
591
+ )
592
+
593
+ assert File.exist?(File.join(ActionView::Helpers::AssetTagHelper::ASSETS_DIR, 'absolute', 'test.css'))
549
594
  ensure
550
595
  FileUtils.rm_f(File.join(ActionView::Helpers::AssetTagHelper::STYLESHEETS_DIR, 'all.css'))
551
596
  FileUtils.rm_f(File.join(ActionView::Helpers::AssetTagHelper::STYLESHEETS_DIR, 'money.css'))
597
+ FileUtils.rm_f(File.join(ActionView::Helpers::AssetTagHelper::ASSETS_DIR, 'absolute'))
552
598
  end
553
599
 
554
600
  def test_caching_stylesheet_link_tag_when_caching_on_with_proc_asset_host
@@ -21,6 +21,9 @@ silence_warnings do
21
21
 
22
22
  attr_accessor :comments
23
23
  def comments_attributes=(attributes); end
24
+
25
+ attr_accessor :tags
26
+ def tags_attributes=(attributes); end
24
27
  end
25
28
 
26
29
  class Comment
@@ -33,6 +36,50 @@ silence_warnings do
33
36
  def name
34
37
  @id.nil? ? "new #{self.class.name.downcase}" : "#{self.class.name.downcase} ##{@id}"
35
38
  end
39
+
40
+ attr_accessor :relevances
41
+ def relevances_attributes=(attributes); end
42
+
43
+ end
44
+
45
+ class Tag
46
+ attr_reader :id
47
+ attr_reader :post_id
48
+ def initialize(id = nil, post_id = nil); @id, @post_id = id, post_id end
49
+ def save; @id = 1; @post_id = 1 end
50
+ def new_record?; @id.nil? end
51
+ def to_param; @id; end
52
+ def value
53
+ @id.nil? ? "new #{self.class.name.downcase}" : "#{self.class.name.downcase} ##{@id}"
54
+ end
55
+
56
+ attr_accessor :relevances
57
+ def relevances_attributes=(attributes); end
58
+
59
+ end
60
+
61
+ class CommentRelevance
62
+ attr_reader :id
63
+ attr_reader :comment_id
64
+ def initialize(id = nil, comment_id = nil); @id, @comment_id = id, comment_id end
65
+ def save; @id = 1; @comment_id = 1 end
66
+ def new_record?; @id.nil? end
67
+ def to_param; @id; end
68
+ def value
69
+ @id.nil? ? "new #{self.class.name.downcase}" : "#{self.class.name.downcase} ##{@id}"
70
+ end
71
+ end
72
+
73
+ class TagRelevance
74
+ attr_reader :id
75
+ attr_reader :tag_id
76
+ def initialize(id = nil, tag_id = nil); @id, @tag_id = id, tag_id end
77
+ def save; @id = 1; @tag_id = 1 end
78
+ def new_record?; @id.nil? end
79
+ def to_param; @id; end
80
+ def value
81
+ @id.nil? ? "new #{self.class.name.downcase}" : "#{self.class.name.downcase} ##{@id}"
82
+ end
36
83
  end
37
84
 
38
85
  class Author < Comment
@@ -98,6 +145,11 @@ class FormHelperTest < ActionView::TestCase
98
145
  assert_dom_equal('<label for="my_for">Title</label>', label(:post, :title, nil, "for" => "my_for"))
99
146
  end
100
147
 
148
+ def test_label_for_radio_buttons_with_value
149
+ assert_dom_equal('<label for="post_title_great_title">The title goes here</label>', label("post", "title", "The title goes here", :value => "great_title"))
150
+ assert_dom_equal('<label for="post_title_great_title">The title goes here</label>', label("post", "title", "The title goes here", :value => "great title"))
151
+ end
152
+
101
153
  def test_text_field
102
154
  assert_dom_equal(
103
155
  '<input id="post_title" name="post[title]" size="30" type="text" value="Hello World" />', text_field("post", "title")
@@ -377,7 +429,7 @@ class FormHelperTest < ActionView::TestCase
377
429
 
378
430
  expected =
379
431
  "<form action='http://www.example.com' id='create-post' method='post'>" +
380
- "<div style='margin:0;padding:0'><input name='_method' type='hidden' value='put' /></div>" +
432
+ "<div style='margin:0;padding:0;display:inline'><input name='_method' type='hidden' value='put' /></div>" +
381
433
  "<input name='post[title]' size='30' type='text' id='post_title' value='Hello World' />" +
382
434
  "<textarea name='post[body]' id='post_body' rows='20' cols='40'>Back to the hill and over it again!</textarea>" +
383
435
  "<input name='post[secret]' type='hidden' value='0' />" +
@@ -531,6 +583,20 @@ class FormHelperTest < ActionView::TestCase
531
583
  assert_dom_equal expected, output_buffer
532
584
  end
533
585
 
586
+ def test_nested_fields_for_with_index_radio_button
587
+ form_for(:post, @post) do |f|
588
+ f.fields_for(:comment, @post, :index => 5) do |c|
589
+ concat c.radio_button(:title, "hello")
590
+ end
591
+ end
592
+
593
+ expected = "<form action='http://www.example.com' method='post'>" +
594
+ "<input name='post[comment][5][title]' type='radio' id='post_comment_5_title_hello' value='hello' />" +
595
+ "</form>"
596
+
597
+ assert_dom_equal expected, output_buffer
598
+ end
599
+
534
600
  def test_nested_fields_for_with_auto_index_on_both
535
601
  form_for("post[]", @post) do |f|
536
602
  f.fields_for("comment[]", @post) do |c|
@@ -720,6 +786,51 @@ class FormHelperTest < ActionView::TestCase
720
786
  assert_dom_equal expected, output_buffer
721
787
  end
722
788
 
789
+ def test_nested_fields_uses_unique_indices_for_different_collection_associations
790
+ @post.comments = [Comment.new(321)]
791
+ @post.tags = [Tag.new(123), Tag.new(456)]
792
+ @post.comments[0].relevances = []
793
+ @post.tags[0].relevances = []
794
+ @post.tags[1].relevances = []
795
+ form_for(:post, @post) do |f|
796
+ f.fields_for(:comments, @post.comments[0]) do |cf|
797
+ concat cf.text_field(:name)
798
+ cf.fields_for(:relevances, CommentRelevance.new(314)) do |crf|
799
+ concat crf.text_field(:value)
800
+ end
801
+ end
802
+ f.fields_for(:tags, @post.tags[0]) do |tf|
803
+ concat tf.text_field(:value)
804
+ tf.fields_for(:relevances, TagRelevance.new(3141)) do |trf|
805
+ concat trf.text_field(:value)
806
+ end
807
+ end
808
+ f.fields_for('tags', @post.tags[1]) do |tf|
809
+ concat tf.text_field(:value)
810
+ tf.fields_for(:relevances, TagRelevance.new(31415)) do |trf|
811
+ concat trf.text_field(:value)
812
+ end
813
+ end
814
+ end
815
+
816
+ expected = '<form action="http://www.example.com" method="post">' +
817
+ '<input id="post_comments_attributes_0_id" name="post[comments_attributes][0][id]" type="hidden" value="321" />' +
818
+ '<input id="post_comments_attributes_0_name" name="post[comments_attributes][0][name]" size="30" type="text" value="comment #321" />' +
819
+ '<input id="post_comments_attributes_0_relevances_attributes_0_id" name="post[comments_attributes][0][relevances_attributes][0][id]" type="hidden" value="314" />' +
820
+ '<input id="post_comments_attributes_0_relevances_attributes_0_value" name="post[comments_attributes][0][relevances_attributes][0][value]" size="30" type="text" value="commentrelevance #314" />' +
821
+ '<input id="post_tags_attributes_0_id" name="post[tags_attributes][0][id]" type="hidden" value="123" />' +
822
+ '<input id="post_tags_attributes_0_value" name="post[tags_attributes][0][value]" size="30" type="text" value="tag #123" />' +
823
+ '<input id="post_tags_attributes_0_relevances_attributes_0_id" name="post[tags_attributes][0][relevances_attributes][0][id]" type="hidden" value="3141" />' +
824
+ '<input id="post_tags_attributes_0_relevances_attributes_0_value" name="post[tags_attributes][0][relevances_attributes][0][value]" size="30" type="text" value="tagrelevance #3141" />' +
825
+ '<input id="post_tags_attributes_1_id" name="post[tags_attributes][1][id]" type="hidden" value="456" />' +
826
+ '<input id="post_tags_attributes_1_value" name="post[tags_attributes][1][value]" size="30" type="text" value="tag #456" />' +
827
+ '<input id="post_tags_attributes_1_relevances_attributes_0_id" name="post[tags_attributes][1][relevances_attributes][0][id]" type="hidden" value="31415" />' +
828
+ '<input id="post_tags_attributes_1_relevances_attributes_0_value" name="post[tags_attributes][1][relevances_attributes][0][value]" size="30" type="text" value="tagrelevance #31415" />' +
829
+ '</form>'
830
+
831
+ assert_dom_equal expected, output_buffer
832
+ end
833
+
723
834
  def test_fields_for
724
835
  fields_for(:post, @post) do |f|
725
836
  concat f.text_field(:title)
@@ -1072,7 +1183,7 @@ class FormHelperTest < ActionView::TestCase
1072
1183
  def test_form_for_with_existing_object
1073
1184
  form_for(@post) do |f| end
1074
1185
 
1075
- expected = "<form action=\"/posts/123\" class=\"edit_post\" id=\"edit_post_123\" method=\"post\"><div style=\"margin:0;padding:0\"><input name=\"_method\" type=\"hidden\" value=\"put\" /></div></form>"
1186
+ expected = "<form action=\"/posts/123\" class=\"edit_post\" id=\"edit_post_123\" method=\"post\"><div style=\"margin:0;padding:0;display:inline\"><input name=\"_method\" type=\"hidden\" value=\"put\" /></div></form>"
1076
1187
  assert_equal expected, output_buffer
1077
1188
  end
1078
1189
 
@@ -1093,7 +1204,7 @@ class FormHelperTest < ActionView::TestCase
1093
1204
 
1094
1205
  form_for([@post, @comment]) {}
1095
1206
 
1096
- expected = %(<form action="#{comment_path(@post, @comment)}" class="edit_comment" id="edit_comment_1" method="post"><div style="margin:0;padding:0"><input name="_method" type="hidden" value="put" /></div></form>)
1207
+ expected = %(<form action="#{comment_path(@post, @comment)}" class="edit_comment" id="edit_comment_1" method="post"><div style="margin:0;padding:0;display:inline"><input name="_method" type="hidden" value="put" /></div></form>)
1097
1208
  assert_dom_equal expected, output_buffer
1098
1209
  end
1099
1210
 
@@ -1112,7 +1223,7 @@ class FormHelperTest < ActionView::TestCase
1112
1223
 
1113
1224
  form_for([:admin, @post, @comment]) {}
1114
1225
 
1115
- expected = %(<form action="#{admin_comment_path(@post, @comment)}" class="edit_comment" id="edit_comment_1" method="post"><div style="margin:0;padding:0"><input name="_method" type="hidden" value="put" /></div></form>)
1226
+ expected = %(<form action="#{admin_comment_path(@post, @comment)}" class="edit_comment" id="edit_comment_1" method="post"><div style="margin:0;padding:0;display:inline"><input name="_method" type="hidden" value="put" /></div></form>)
1116
1227
  assert_dom_equal expected, output_buffer
1117
1228
  end
1118
1229
 
@@ -1128,7 +1239,7 @@ class FormHelperTest < ActionView::TestCase
1128
1239
  def test_form_for_with_existing_object_and_custom_url
1129
1240
  form_for(@post, :url => "/super_posts") do |f| end
1130
1241
 
1131
- expected = "<form action=\"/super_posts\" class=\"edit_post\" id=\"edit_post_123\" method=\"post\"><div style=\"margin:0;padding:0\"><input name=\"_method\" type=\"hidden\" value=\"put\" /></div></form>"
1242
+ expected = "<form action=\"/super_posts\" class=\"edit_post\" id=\"edit_post_123\" method=\"post\"><div style=\"margin:0;padding:0;display:inline\"><input name=\"_method\" type=\"hidden\" value=\"put\" /></div></form>"
1132
1243
  assert_equal expected, output_buffer
1133
1244
  end
1134
1245
 
@@ -1173,4 +1284,4 @@ class FormHelperTest < ActionView::TestCase
1173
1284
  def protect_against_forgery?
1174
1285
  false
1175
1286
  end
1176
- end
1287
+ end
@@ -80,6 +80,14 @@ class FormOptionsHelperTest < ActionView::TestCase
80
80
  )
81
81
  end
82
82
 
83
+ def test_string_options_for_select
84
+ options = "<option value=\"Denmark\">Denmark</option><option value=\"USA\">USA</option><option value=\"Sweden\">Sweden</option>"
85
+ assert_dom_equal(
86
+ options,
87
+ options_for_select(options)
88
+ )
89
+ end
90
+
83
91
  def test_array_options_for_select
84
92
  assert_dom_equal(
85
93
  "<option value=\"&lt;Denmark&gt;\">&lt;Denmark&gt;</option>\n<option value=\"USA\">USA</option>\n<option value=\"Sweden\">Sweden</option>",
@@ -324,6 +332,20 @@ class FormOptionsHelperTest < ActionView::TestCase
324
332
  )
325
333
  end
326
334
 
335
+ def test_select_under_fields_for_with_string_and_given_prompt
336
+ @post = Post.new
337
+ options = "<option value=\"abe\">abe</option><option value=\"mus\">mus</option><option value=\"hest\">hest</option>"
338
+
339
+ fields_for :post, @post do |f|
340
+ concat f.select(:category, options, :prompt => 'The prompt')
341
+ end
342
+
343
+ assert_dom_equal(
344
+ "<select id=\"post_category\" name=\"post[category]\"><option value=\"\">The prompt</option>\n#{options}</select>",
345
+ output_buffer
346
+ )
347
+ end
348
+
327
349
  def test_select_with_blank
328
350
  @post = Post.new
329
351
  @post.category = "<mus>"
@@ -39,13 +39,13 @@ class FormTagHelperTest < ActionView::TestCase
39
39
 
40
40
  def test_form_tag_with_method_put
41
41
  actual = form_tag({}, { :method => :put })
42
- expected = %(<form action="http://www.example.com" method="post"><div style='margin:0;padding:0'><input type="hidden" name="_method" value="put" /></div>)
42
+ expected = %(<form action="http://www.example.com" method="post"><div style='margin:0;padding:0;display:inline'><input type="hidden" name="_method" value="put" /></div>)
43
43
  assert_dom_equal expected, actual
44
44
  end
45
45
 
46
46
  def test_form_tag_with_method_delete
47
47
  actual = form_tag({}, { :method => :delete })
48
- expected = %(<form action="http://www.example.com" method="post"><div style='margin:0;padding:0'><input type="hidden" name="_method" value="delete" /></div>)
48
+ expected = %(<form action="http://www.example.com" method="post"><div style='margin:0;padding:0;display:inline'><input type="hidden" name="_method" value="delete" /></div>)
49
49
  assert_dom_equal expected, actual
50
50
  end
51
51
 
@@ -61,7 +61,7 @@ class FormTagHelperTest < ActionView::TestCase
61
61
  __in_erb_template = ''
62
62
  form_tag("http://example.com", :method => :put) { concat "Hello world!" }
63
63
 
64
- expected = %(<form action="http://example.com" method="post"><div style='margin:0;padding:0'><input type="hidden" name="_method" value="put" /></div>Hello world!</form>)
64
+ expected = %(<form action="http://example.com" method="post"><div style='margin:0;padding:0;display:inline'><input type="hidden" name="_method" value="put" /></div>Hello world!</form>)
65
65
  assert_dom_equal expected, output_buffer
66
66
  end
67
67
 
@@ -153,6 +153,23 @@ class FormTagHelperTest < ActionView::TestCase
153
153
  assert_dom_equal expected, actual
154
154
  end
155
155
 
156
+ def test_text_area_tag_id_sanitized
157
+ input_elem = root_elem(text_area_tag("item[][description]"))
158
+ assert_match VALID_HTML_ID, input_elem['id']
159
+ end
160
+
161
+ def test_text_area_tag_escape_content
162
+ actual = text_area_tag "body", "<b>hello world</b>", :size => "20x40"
163
+ expected = %(<textarea cols="20" id="body" name="body" rows="40">&lt;b&gt;hello world&lt;/b&gt;</textarea>)
164
+ assert_dom_equal expected, actual
165
+ end
166
+
167
+ def test_text_area_tag_unescaped_content
168
+ actual = text_area_tag "body", "<b>hello world</b>", :size => "20x40", :escape => false
169
+ expected = %(<textarea cols="20" id="body" name="body" rows="40"><b>hello world</b></textarea>)
170
+ assert_dom_equal expected, actual
171
+ end
172
+
156
173
  def test_text_field_tag
157
174
  actual = text_field_tag "title", "Hello!"
158
175
  expected = %(<input id="title" name="title" type="text" value="Hello!" />)
@@ -252,14 +269,14 @@ class FormTagHelperTest < ActionView::TestCase
252
269
 
253
270
  def test_submit_tag
254
271
  assert_dom_equal(
255
- %(<input name='commit' type='submit' value='Save' onclick="if (window.hiddenCommit) { window.hiddenCommit.setAttribute('value', this.value); }else { hiddenCommit = this.cloneNode(false);hiddenCommit.setAttribute('type', 'hidden');this.form.appendChild(hiddenCommit); }this.setAttribute('originalValue', this.value);this.disabled = true;this.value='Saving...';alert('hello!');result = (this.form.onsubmit ? (this.form.onsubmit() ? this.form.submit() : false) : this.form.submit());if (result == false) { this.value = this.getAttribute('originalValue');this.disabled = false; }return result;" />),
272
+ %(<input name='commit' onclick="if (window.hiddenCommit) { window.hiddenCommit.setAttribute('value', this.value); }else { hiddenCommit = document.createElement('input');hiddenCommit.type = 'hidden';hiddenCommit.value = this.value;hiddenCommit.name = this.name;this.form.appendChild(hiddenCommit); }this.setAttribute('originalValue', this.value);this.disabled = true;this.value='Saving...';alert('hello!');result = (this.form.onsubmit ? (this.form.onsubmit() ? this.form.submit() : false) : this.form.submit());if (result == false) { this.value = this.getAttribute('originalValue');this.disabled = false; }return result;" type="submit" value="Save" />),
256
273
  submit_tag("Save", :disable_with => "Saving...", :onclick => "alert('hello!')")
257
274
  )
258
275
  end
259
276
 
260
277
  def test_submit_tag_with_no_onclick_options
261
278
  assert_dom_equal(
262
- %(<input name='commit' type='submit' value='Save' onclick="if (window.hiddenCommit) { window.hiddenCommit.setAttribute('value', this.value); }else { hiddenCommit = this.cloneNode(false);hiddenCommit.setAttribute('type', 'hidden');this.form.appendChild(hiddenCommit); }this.setAttribute('originalValue', this.value);this.disabled = true;this.value='Saving...';result = (this.form.onsubmit ? (this.form.onsubmit() ? this.form.submit() : false) : this.form.submit());if (result == false) { this.value = this.getAttribute('originalValue');this.disabled = false; }return result;" />),
279
+ %(<input name='commit' onclick="if (window.hiddenCommit) { window.hiddenCommit.setAttribute('value', this.value); }else { hiddenCommit = document.createElement('input');hiddenCommit.type = 'hidden';hiddenCommit.value = this.value;hiddenCommit.name = this.name;this.form.appendChild(hiddenCommit); }this.setAttribute('originalValue', this.value);this.disabled = true;this.value='Saving...';result = (this.form.onsubmit ? (this.form.onsubmit() ? this.form.submit() : false) : this.form.submit());if (result == false) { this.value = this.getAttribute('originalValue');this.disabled = false; }return result;" type="submit" value="Save" />),
263
280
  submit_tag("Save", :disable_with => "Saving...")
264
281
  )
265
282
  end
@@ -273,7 +290,7 @@ class FormTagHelperTest < ActionView::TestCase
273
290
 
274
291
  def test_submit_tag_with_confirmation_and_with_disable_with
275
292
  assert_dom_equal(
276
- %(<input name="commit" type="submit" value="Save" onclick="if (!confirm('Are you sure?')) return false; if (window.hiddenCommit) { window.hiddenCommit.setAttribute('value', this.value); }else { hiddenCommit = this.cloneNode(false);hiddenCommit.setAttribute('type', 'hidden');this.form.appendChild(hiddenCommit); }this.setAttribute('originalValue', this.value);this.disabled = true;this.value='Saving...';result = (this.form.onsubmit ? (this.form.onsubmit() ? this.form.submit() : false) : this.form.submit());if (result == false) { this.value = this.getAttribute('originalValue');this.disabled = false; }return result;" />),
293
+ %(<input name="commit" onclick="if (!confirm('Are you sure?')) return false; if (window.hiddenCommit) { window.hiddenCommit.setAttribute('value', this.value); }else { hiddenCommit = document.createElement('input');hiddenCommit.type = 'hidden';hiddenCommit.value = this.value;hiddenCommit.name = this.name;this.form.appendChild(hiddenCommit); }this.setAttribute('originalValue', this.value);this.disabled = true;this.value='Saving...';result = (this.form.onsubmit ? (this.form.onsubmit() ? this.form.submit() : false) : this.form.submit());if (result == false) { this.value = this.getAttribute('originalValue');this.disabled = false; }return result;" type="submit" value="Save" />),
277
294
  submit_tag("Save", :disable_with => "Saving...", :confirm => "Are you sure?")
278
295
  )
279
296
  end