actionpack 1.12.5 → 1.13.0

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 (179) hide show
  1. data/CHANGELOG +517 -15
  2. data/MIT-LICENSE +1 -1
  3. data/README +18 -20
  4. data/Rakefile +7 -4
  5. data/examples/address_book_controller.rb +3 -3
  6. data/examples/blog_controller.cgi +3 -3
  7. data/examples/debate_controller.cgi +5 -5
  8. data/lib/action_controller.rb +2 -2
  9. data/lib/action_controller/assertions.rb +73 -311
  10. data/lib/action_controller/{deprecated_assertions.rb → assertions/deprecated_assertions.rb} +32 -8
  11. data/lib/action_controller/assertions/dom_assertions.rb +25 -0
  12. data/lib/action_controller/assertions/model_assertions.rb +12 -0
  13. data/lib/action_controller/assertions/response_assertions.rb +140 -0
  14. data/lib/action_controller/assertions/routing_assertions.rb +82 -0
  15. data/lib/action_controller/assertions/selector_assertions.rb +571 -0
  16. data/lib/action_controller/assertions/tag_assertions.rb +117 -0
  17. data/lib/action_controller/base.rb +334 -163
  18. data/lib/action_controller/benchmarking.rb +3 -6
  19. data/lib/action_controller/caching.rb +83 -22
  20. data/lib/action_controller/cgi_ext/cgi_ext.rb +0 -7
  21. data/lib/action_controller/cgi_ext/cgi_methods.rb +167 -173
  22. data/lib/action_controller/cgi_ext/raw_post_data_fix.rb +43 -22
  23. data/lib/action_controller/cgi_process.rb +50 -27
  24. data/lib/action_controller/components.rb +21 -25
  25. data/lib/action_controller/cookies.rb +10 -9
  26. data/lib/action_controller/{dependencies.rb → deprecated_dependencies.rb} +9 -27
  27. data/lib/action_controller/filters.rb +448 -225
  28. data/lib/action_controller/flash.rb +24 -20
  29. data/lib/action_controller/helpers.rb +2 -5
  30. data/lib/action_controller/integration.rb +40 -16
  31. data/lib/action_controller/layout.rb +11 -8
  32. data/lib/action_controller/macros/auto_complete.rb +3 -2
  33. data/lib/action_controller/macros/in_place_editing.rb +3 -2
  34. data/lib/action_controller/mime_responds.rb +41 -29
  35. data/lib/action_controller/mime_type.rb +68 -10
  36. data/lib/action_controller/pagination.rb +4 -3
  37. data/lib/action_controller/request.rb +22 -14
  38. data/lib/action_controller/rescue.rb +25 -22
  39. data/lib/action_controller/resources.rb +302 -0
  40. data/lib/action_controller/response.rb +20 -2
  41. data/lib/action_controller/response.rb.rej +17 -0
  42. data/lib/action_controller/routing.rb +1165 -567
  43. data/lib/action_controller/scaffolding.rb +30 -31
  44. data/lib/action_controller/session/active_record_store.rb +2 -0
  45. data/lib/action_controller/session/drb_store.rb +4 -0
  46. data/lib/action_controller/session/mem_cache_store.rb +4 -0
  47. data/lib/action_controller/session_management.rb +6 -9
  48. data/lib/action_controller/status_codes.rb +89 -0
  49. data/lib/action_controller/streaming.rb +6 -15
  50. data/lib/action_controller/templates/rescues/_request_and_response.rhtml +5 -5
  51. data/lib/action_controller/templates/rescues/diagnostics.rhtml +2 -2
  52. data/lib/action_controller/templates/rescues/routing_error.rhtml +4 -4
  53. data/lib/action_controller/templates/rescues/template_error.rhtml +1 -1
  54. data/lib/action_controller/templates/scaffolds/list.rhtml +1 -1
  55. data/lib/action_controller/test_process.rb +52 -30
  56. data/lib/action_controller/url_rewriter.rb +63 -29
  57. data/lib/action_controller/vendor/html-scanner/html/document.rb +1 -0
  58. data/lib/action_controller/vendor/html-scanner/html/node.rb +3 -4
  59. data/lib/action_controller/vendor/html-scanner/html/selector.rb +822 -0
  60. data/lib/action_controller/verification.rb +22 -11
  61. data/lib/action_pack.rb +1 -1
  62. data/lib/action_pack/version.rb +2 -2
  63. data/lib/action_view.rb +1 -1
  64. data/lib/action_view/base.rb +46 -43
  65. data/lib/action_view/compiled_templates.rb +1 -1
  66. data/lib/action_view/helpers/active_record_helper.rb +54 -17
  67. data/lib/action_view/helpers/asset_tag_helper.rb +97 -46
  68. data/lib/action_view/helpers/capture_helper.rb +1 -1
  69. data/lib/action_view/helpers/date_helper.rb +258 -136
  70. data/lib/action_view/helpers/debug_helper.rb +1 -1
  71. data/lib/action_view/helpers/deprecated_helper.rb +34 -0
  72. data/lib/action_view/helpers/form_helper.rb +75 -35
  73. data/lib/action_view/helpers/form_options_helper.rb +7 -5
  74. data/lib/action_view/helpers/form_tag_helper.rb +44 -6
  75. data/lib/action_view/helpers/java_script_macros_helper.rb +59 -46
  76. data/lib/action_view/helpers/javascript_helper.rb +71 -10
  77. data/lib/action_view/helpers/javascripts/controls.js +41 -23
  78. data/lib/action_view/helpers/javascripts/dragdrop.js +105 -76
  79. data/lib/action_view/helpers/javascripts/effects.js +293 -163
  80. data/lib/action_view/helpers/javascripts/prototype.js +897 -389
  81. data/lib/action_view/helpers/javascripts/prototype.js.rej +561 -0
  82. data/lib/action_view/helpers/number_helper.rb +111 -65
  83. data/lib/action_view/helpers/prototype_helper.rb +84 -109
  84. data/lib/action_view/helpers/scriptaculous_helper.rb +5 -0
  85. data/lib/action_view/helpers/tag_helper.rb +69 -16
  86. data/lib/action_view/helpers/text_helper.rb +149 -112
  87. data/lib/action_view/helpers/url_helper.rb +200 -107
  88. data/lib/action_view/template_error.rb +66 -42
  89. data/test/abstract_unit.rb +4 -2
  90. data/test/active_record_unit.rb +84 -56
  91. data/test/activerecord/active_record_assertions_test.rb +26 -18
  92. data/test/activerecord/active_record_store_test.rb +4 -36
  93. data/test/activerecord/pagination_test.rb +1 -6
  94. data/test/controller/action_pack_assertions_test.rb +230 -113
  95. data/test/controller/addresses_render_test.rb +2 -6
  96. data/test/controller/assert_select_test.rb +576 -0
  97. data/test/controller/base_test.rb +73 -3
  98. data/test/controller/caching_test.rb +228 -0
  99. data/test/controller/capture_test.rb +12 -10
  100. data/test/controller/cgi_test.rb +89 -12
  101. data/test/controller/components_test.rb +24 -2
  102. data/test/controller/content_type_test.rb +139 -0
  103. data/test/controller/controller_fixtures/app/controllers/admin/user_controller.rb +0 -0
  104. data/test/controller/controller_fixtures/app/controllers/user_controller.rb +0 -0
  105. data/test/controller/controller_fixtures/vendor/plugins/bad_plugin/lib/plugin_controller.rb +0 -0
  106. data/test/controller/cookie_test.rb +33 -25
  107. data/test/controller/deprecated_instance_variables_test.rb +48 -0
  108. data/test/controller/deprecation/deprecated_base_methods_test.rb +60 -0
  109. data/test/controller/fake_controllers.rb +0 -1
  110. data/test/controller/filters_test.rb +301 -16
  111. data/test/controller/flash_test.rb +19 -2
  112. data/test/controller/helper_test.rb +2 -2
  113. data/test/controller/integration_test.rb +154 -0
  114. data/test/controller/layout_test.rb +115 -1
  115. data/test/controller/mime_responds_test.rb +94 -0
  116. data/test/controller/mime_type_test.rb +9 -0
  117. data/test/controller/new_render_test.rb +161 -11
  118. data/test/controller/raw_post_test.rb +52 -15
  119. data/test/controller/redirect_test.rb +27 -14
  120. data/test/controller/render_test.rb +76 -29
  121. data/test/controller/request_test.rb +55 -4
  122. data/test/controller/resources_test.rb +274 -0
  123. data/test/controller/routing_test.rb +1533 -824
  124. data/test/controller/selector_test.rb +628 -0
  125. data/test/controller/send_file_test.rb +9 -1
  126. data/test/controller/session_management_test.rb +51 -0
  127. data/test/controller/test_test.rb +113 -29
  128. data/test/controller/url_rewriter_test.rb +86 -17
  129. data/test/controller/verification_test.rb +19 -17
  130. data/test/controller/webservice_test.rb +0 -7
  131. data/test/fixtures/content_type/render_default_content_types_for_respond_to.rhtml +1 -0
  132. data/test/fixtures/content_type/render_default_for_rhtml.rhtml +1 -0
  133. data/test/fixtures/content_type/render_default_for_rjs.rjs +1 -0
  134. data/test/fixtures/content_type/render_default_for_rxml.rxml +1 -0
  135. data/test/fixtures/deprecated_instance_variables/_cookies_ivar.rhtml +1 -0
  136. data/test/fixtures/deprecated_instance_variables/_cookies_method.rhtml +1 -0
  137. data/test/fixtures/deprecated_instance_variables/_flash_ivar.rhtml +1 -0
  138. data/test/fixtures/deprecated_instance_variables/_flash_method.rhtml +1 -0
  139. data/test/fixtures/deprecated_instance_variables/_headers_ivar.rhtml +1 -0
  140. data/test/fixtures/deprecated_instance_variables/_headers_method.rhtml +1 -0
  141. data/test/fixtures/deprecated_instance_variables/_params_ivar.rhtml +1 -0
  142. data/test/fixtures/deprecated_instance_variables/_params_method.rhtml +1 -0
  143. data/test/fixtures/deprecated_instance_variables/_request_ivar.rhtml +1 -0
  144. data/test/fixtures/deprecated_instance_variables/_request_method.rhtml +1 -0
  145. data/test/fixtures/deprecated_instance_variables/_response_ivar.rhtml +1 -0
  146. data/test/fixtures/deprecated_instance_variables/_response_method.rhtml +1 -0
  147. data/test/fixtures/deprecated_instance_variables/_session_ivar.rhtml +1 -0
  148. data/test/fixtures/deprecated_instance_variables/_session_method.rhtml +1 -0
  149. data/test/fixtures/multipart/binary_file +0 -0
  150. data/test/fixtures/public/javascripts/application.js +1 -0
  151. data/test/fixtures/test/_hello.rxml +1 -0
  152. data/test/fixtures/test/hello_world_container.rxml +3 -0
  153. data/test/fixtures/topic.rb +2 -2
  154. data/test/template/active_record_helper_test.rb +83 -12
  155. data/test/template/asset_tag_helper_test.rb +75 -95
  156. data/test/template/compiled_templates_test.rb +1 -0
  157. data/test/template/date_helper_test.rb +873 -181
  158. data/test/template/deprecated_helper_test.rb +36 -0
  159. data/test/template/deprecated_instance_variables_test.rb +43 -0
  160. data/test/template/form_helper_test.rb +77 -1
  161. data/test/template/form_options_helper_test.rb +4 -0
  162. data/test/template/form_tag_helper_test.rb +66 -2
  163. data/test/template/java_script_macros_helper_test.rb +4 -1
  164. data/test/template/javascript_helper_test.rb +29 -0
  165. data/test/template/number_helper_test.rb +63 -27
  166. data/test/template/prototype_helper_test.rb +77 -34
  167. data/test/template/tag_helper_test.rb +34 -6
  168. data/test/template/text_helper_test.rb +69 -34
  169. data/test/template/url_helper_test.rb +168 -16
  170. data/test/testing_sandbox.rb +7 -22
  171. metadata +66 -20
  172. data/filler.txt +0 -50
  173. data/lib/action_controller/code_generation.rb +0 -235
  174. data/lib/action_controller/vendor/xml_simple.rb +0 -1019
  175. data/test/controller/caching_filestore.rb +0 -74
  176. data/test/fixtures/application_root/app/controllers/a_class_that_contains_a_controller/poorly_placed_controller.rb +0 -7
  177. data/test/fixtures/application_root/app/controllers/module_that_holds_controllers/nested_controller.rb +0 -3
  178. data/test/fixtures/application_root/app/models/a_class_that_contains_a_controller.rb +0 -7
  179. data/test/fixtures/dont_load.rb +0 -3
@@ -1,4 +1,4 @@
1
- Copyright (c) 2004 David Heinemeier Hansson
1
+ Copyright (c) 2004-2006 David Heinemeier Hansson
2
2
 
3
3
  Permission is hereby granted, free of charge, to any person obtaining
4
4
  a copy of this software and associated documentation files (the
data/README CHANGED
@@ -34,7 +34,7 @@ A short rundown of the major features:
34
34
  and can therefore share helper methods.
35
35
 
36
36
  BlogController < ActionController::Base
37
- def display
37
+ def show
38
38
  @customer = find_customer
39
39
  end
40
40
 
@@ -100,7 +100,7 @@ A short rundown of the major features:
100
100
  after_filter { |c| c.response.body = GZip::compress(c.response.body) }
101
101
  after_filter LocalizeFilter
102
102
 
103
- def list
103
+ def index
104
104
  # Before this action is run, the user will be authenticated, the cache
105
105
  # will be examined to see if a valid copy of the results already
106
106
  # exists, and the action will be logged for auditing.
@@ -139,7 +139,7 @@ A short rundown of the major features:
139
139
  end
140
140
 
141
141
  Layout file (called weblog_layout):
142
- <html><body><%= @content_for_layout %></body></html>
142
+ <html><body><%= yield %></body></html>
143
143
 
144
144
  Template for hello_world action:
145
145
  <h1>Hello world</h1>
@@ -155,7 +155,7 @@ A short rundown of the major features:
155
155
  map.connect 'clients/:client_name/:project_name/:controller/:action'
156
156
 
157
157
  Accessing /clients/37signals/basecamp/project/dash calls ProjectController#dash with
158
- { "client_name" => "37signals", "project_name" => "basecamp" } in @params["params"]
158
+ { "client_name" => "37signals", "project_name" => "basecamp" } in params[:params]
159
159
 
160
160
  From that URL, you can rewrite the redirect in a number of ways:
161
161
 
@@ -296,9 +296,8 @@ A short rundown of the major features:
296
296
  {Learn more}[link:classes/ActionController/Rescue.html]
297
297
 
298
298
 
299
- * Scaffolding for Action Record model objects
299
+ * Scaffolding for Active Record model objects
300
300
 
301
- require 'account' # must be an Active Record class
302
301
  class AccountController < ActionController::Base
303
302
  scaffold :account
304
303
  end
@@ -306,7 +305,7 @@ A short rundown of the major features:
306
305
  The AccountController now has the full CRUD range of actions and default
307
306
  templates: list, show, destroy, new, create, edit, update
308
307
 
309
- {Learn more}link:classes/ActionController/Scaffolding/ClassMethods.html
308
+ {Learn more}[link:classes/ActionController/Scaffolding/ClassMethods.html]
310
309
 
311
310
 
312
311
  * Form building for Active Record model objects
@@ -338,10 +337,10 @@ A short rundown of the major features:
338
337
  <input type="submit" value="Create">
339
338
  </form>
340
339
 
341
- This form generates a @params["post"] array that can be used directly in a save action:
340
+ This form generates a params[:post] array that can be used directly in a save action:
342
341
 
343
342
  class WeblogController < ActionController::Base
344
- def save
343
+ def create
345
344
  post = Post.create(params[:post])
346
345
  redirect_to :action => "display", :id => post.id
347
346
  end
@@ -350,10 +349,10 @@ A short rundown of the major features:
350
349
  {Learn more}[link:classes/ActionView/Helpers/ActiveRecordHelper.html]
351
350
 
352
351
 
353
- * Runs on top of WEBrick, CGI, FCGI, and mod_ruby
352
+ * Runs on top of WEBrick, Mongrel, CGI, FCGI, and mod_ruby
354
353
 
355
354
 
356
- == Simple example
355
+ == Simple example (from outside of Rails)
357
356
 
358
357
  This example will implement a simple weblog system using inline templates and
359
358
  an Active Record model. So let's build that WeblogController with just a few
@@ -366,11 +365,11 @@ methods:
366
365
  layout "weblog/layout"
367
366
 
368
367
  def index
369
- @posts = Post.find_all
368
+ @posts = Post.find(:all)
370
369
  end
371
370
 
372
371
  def display
373
- @post = Post.find(:params[:id])
372
+ @post = Post.find(params[:id])
374
373
  end
375
374
 
376
375
  def new
@@ -394,7 +393,7 @@ And the templates look like this:
394
393
 
395
394
  weblog/layout.rhtml:
396
395
  <html><body>
397
- <%= @content_for_layout %>
396
+ <%= yield %>
398
397
  </body></html>
399
398
 
400
399
  weblog/index.rhtml:
@@ -431,6 +430,8 @@ template casing from content.
431
430
  Please note that you might need to change the "shebang" line to
432
431
  #!/usr/local/env ruby, if your Ruby is not placed in /usr/local/bin/ruby
433
432
 
433
+ Also note that these examples are all for demonstrating using Action Pack on
434
+ its own. Not for when it's used inside of Rails.
434
435
 
435
436
  == Download
436
437
 
@@ -440,7 +441,7 @@ The latest version of Action Pack can be found at
440
441
 
441
442
  Documentation can be found at
442
443
 
443
- * http://ap.rubyonrails.com
444
+ * http://api.rubyonrails.com
444
445
 
445
446
 
446
447
  == Installation
@@ -459,13 +460,10 @@ Action Pack is released under the MIT license.
459
460
 
460
461
  == Support
461
462
 
462
- The Action Pack homepage is http://www.rubyonrails.com. You can find
463
+ The Action Pack homepage is http://www.rubyonrails.org. You can find
463
464
  the Action Pack RubyForge page at http://rubyforge.org/projects/actionpack.
464
465
  And as Jim from Rake says:
465
466
 
466
467
  Feel free to submit commits or feature requests. If you send a patch,
467
468
  remember to update the corresponding unit tests. If fact, I prefer
468
- new feature to be submitted in the form of new unit tests.
469
-
470
- For other information, feel free to ask on the ruby-talk mailing list (which
471
- is mirrored to comp.lang.ruby) or contact mailto:david@loudthinking.com.
469
+ new feature to be submitted in the form of new unit tests.
data/Rakefile CHANGED
@@ -22,11 +22,14 @@ task :default => [ :test ]
22
22
 
23
23
  # Run the unit tests
24
24
 
25
- Rake::TestTask.new { |t|
25
+ desc "Run all unit tests"
26
+ task :test => [:test_action_pack, :test_active_record_integration]
27
+
28
+ Rake::TestTask.new(:test_action_pack) { |t|
26
29
  t.libs << "test"
27
30
  # make sure we include the controller tests (c*) first as on some systems
28
31
  # this will not happen automatically and the tests (as a whole) will error
29
- t.test_files=Dir.glob( "test/c*/*_test.rb" ) + Dir.glob( "test/[ft]*/*_test.rb" )
32
+ t.test_files=Dir.glob( "test/c*/**/*_test.rb" ) + Dir.glob( "test/[ft]*/*_test.rb" )
30
33
  # t.pattern = 'test/*/*_test.rb'
31
34
  t.verbose = true
32
35
  }
@@ -72,12 +75,12 @@ spec = Gem::Specification.new do |s|
72
75
  s.has_rdoc = true
73
76
  s.requirements << 'none'
74
77
 
75
- s.add_dependency('activesupport', '= 1.3.1' + PKG_BUILD)
78
+ s.add_dependency('activesupport', '= 1.4.0' + PKG_BUILD)
76
79
 
77
80
  s.require_path = 'lib'
78
81
  s.autorequire = 'action_controller'
79
82
 
80
- s.files = [ "Rakefile", "install.rb", "filler.txt", "README", "RUNNING_UNIT_TESTS", "CHANGELOG", "MIT-LICENSE", "examples/.htaccess" ]
83
+ s.files = [ "Rakefile", "install.rb", "README", "RUNNING_UNIT_TESTS", "CHANGELOG", "MIT-LICENSE", "examples/.htaccess" ]
81
84
  dist_dirs.each do |dir|
82
85
  s.files = s.files + Dir.glob( "#{dir}/**/*" ).delete_if { |item| item.include?( "\.svn" ) }
83
86
  end
@@ -28,11 +28,11 @@ class AddressBookController < ActionController::Base
28
28
  end
29
29
 
30
30
  def person
31
- @person = @address_book.find_person(@params["id"])
31
+ @person = @address_book.find_person(params[:id])
32
32
  end
33
33
 
34
34
  def create_person
35
- @address_book.create_person(@params["person"])
35
+ @address_book.create_person(params[:person])
36
36
  redirect_to :action => "index"
37
37
  end
38
38
 
@@ -49,4 +49,4 @@ begin
49
49
  AddressBookController.process_cgi(CGI.new) if $0 == __FILE__
50
50
  rescue => e
51
51
  CGI.new.out { "#{e.class}: #{e.message}" }
52
- end
52
+ end
@@ -14,7 +14,7 @@ class BlogController < ActionController::Base
14
14
 
15
15
  render_template <<-"EOF"
16
16
  <html><body>
17
- <%= @flash["alert"] %>
17
+ <%= flash["alert"] %>
18
18
  <h1>Posts</h1>
19
19
  <% @posts.each do |post| %>
20
20
  <p><b><%= post.title %></b><br /><%= post.body %></p>
@@ -32,7 +32,7 @@ class BlogController < ActionController::Base
32
32
  end
33
33
 
34
34
  def create
35
- @session["posts"].unshift(Post.new(@params["post"]["title"], @params["post"]["body"]))
35
+ @session["posts"].unshift(Post.new(params[:post][:title], params[:post][:body]))
36
36
  flash["alert"] = "New post added!"
37
37
  redirect_to :action => "index"
38
38
  end
@@ -50,4 +50,4 @@ begin
50
50
  BlogController.process_cgi(CGI.new) if $0 == __FILE__
51
51
  rescue => e
52
52
  CGI.new.out { "#{e.class}: #{e.message}" }
53
- end
53
+ end
@@ -25,19 +25,19 @@ class DebateController < ActionController::Base
25
25
  end
26
26
 
27
27
  def topic
28
- @topic = @debate.find_topic(@params["id"])
28
+ @topic = @debate.find_topic(params[:id])
29
29
  end
30
30
 
31
31
  # def new_topic() end <-- This is not needed as the template doesn't require any assigns
32
32
 
33
33
  def create_topic
34
- @debate.create_topic(@params["topic"])
34
+ @debate.create_topic(params[:topic])
35
35
  redirect_to :action => "index"
36
36
  end
37
37
 
38
38
  def create_reply
39
- @debate.create_reply(@params["reply"])
40
- redirect_to :action => "topic", :path_params => { "id" => @params["reply"]["topic_id"] }
39
+ @debate.create_reply(params[:reply])
40
+ redirect_to :action => "topic", :path_params => { "id" => params[:reply][:topic_id] }
41
41
  end
42
42
 
43
43
  private
@@ -54,4 +54,4 @@ begin
54
54
  DebateController.process_cgi(CGI.new) if $0 == __FILE__
55
55
  rescue => e
56
56
  CGI.new.out { "#{e.class}: #{e.message}" }
57
- end
57
+ end
@@ -1,5 +1,5 @@
1
1
  #--
2
- # Copyright (c) 2004 David Heinemeier Hansson
2
+ # Copyright (c) 2004-2006 David Heinemeier Hansson
3
3
  #
4
4
  # Permission is hereby granted, free of charge, to any person obtaining
5
5
  # a copy of this software and associated documentation files (the
@@ -43,7 +43,7 @@ require 'action_controller/benchmarking'
43
43
  require 'action_controller/flash'
44
44
  require 'action_controller/filters'
45
45
  require 'action_controller/layout'
46
- require 'action_controller/dependencies'
46
+ require 'action_controller/deprecated_dependencies'
47
47
  require 'action_controller/mime_responds'
48
48
  require 'action_controller/pagination'
49
49
  require 'action_controller/scaffolding'
@@ -1,320 +1,82 @@
1
1
  require 'test/unit'
2
2
  require 'test/unit/assertions'
3
- require 'rexml/document'
4
- require File.dirname(__FILE__) + "/vendor/html-scanner/html/document"
5
3
 
6
- module Test #:nodoc:
7
- module Unit #:nodoc:
8
- # In addition to these specific assertions, you also have easy access to various collections that the regular test/unit assertions
9
- # can be used against. These collections are:
10
- #
11
- # * assigns: Instance variables assigned in the action that are available for the view.
12
- # * session: Objects being saved in the session.
13
- # * flash: The flash objects currently in the session.
14
- # * cookies: Cookies being sent to the user on this request.
15
- #
16
- # These collections can be used just like any other hash:
17
- #
18
- # assert_not_nil assigns(:person) # makes sure that a @person instance variable was set
19
- # assert_equal "Dave", cookies[:name] # makes sure that a cookie called :name was set as "Dave"
20
- # assert flash.empty? # makes sure that there's nothing in the flash
21
- #
22
- # For historic reasons, the assigns hash uses string-based keys. So assigns[:person] won't work, but assigns["person"] will. To
23
- # appease our yearning for symbols, though, an alternative accessor has been deviced using a method call instead of index referencing.
24
- # So assigns(:person) will work just like assigns["person"], but again, assigns[:person] will not work.
25
- #
26
- # On top of the collections, you have the complete url that a given action redirected to available in redirect_to_url.
27
- #
28
- # For redirects within the same controller, you can even call follow_redirect and the redirect will be followed, triggering another
29
- # action call which can then be asserted against.
30
- #
31
- # == Manipulating the request collections
32
- #
33
- # The collections described above link to the response, so you can test if what the actions were expected to do happened. But
34
- # sometimes you also want to manipulate these collections in the incoming request. This is really only relevant for sessions
35
- # and cookies, though. For sessions, you just do:
36
- #
37
- # @request.session[:key] = "value"
38
- #
39
- # For cookies, you need to manually create the cookie, like this:
40
- #
41
- # @request.cookies["key"] = CGI::Cookie.new("key", "value")
42
- #
43
- # == Testing named routes
44
- #
45
- # If you're using named routes, they can be easily tested using the original named routes methods straight in the test case.
46
- # Example:
47
- #
48
- # assert_redirected_to page_url(:title => 'foo')
49
- module Assertions
50
- # Asserts that the response is one of the following types:
51
- #
52
- # * <tt>:success</tt>: Status code was 200
53
- # * <tt>:redirect</tt>: Status code was in the 300-399 range
54
- # * <tt>:missing</tt>: Status code was 404
55
- # * <tt>:error</tt>: Status code was in the 500-599 range
56
- #
57
- # You can also pass an explicit status code number as the type, like assert_response(501)
58
- def assert_response(type, message = nil)
59
- clean_backtrace do
60
- if [ :success, :missing, :redirect, :error ].include?(type) && @response.send("#{type}?")
61
- assert_block("") { true } # to count the assertion
62
- elsif type.is_a?(Fixnum) && @response.response_code == type
63
- assert_block("") { true } # to count the assertion
64
- else
65
- assert_block(build_message(message, "Expected response to be a <?>, but was <?>", type, @response.response_code)) { false }
66
- end
67
- end
68
- end
69
-
70
- # Assert that the redirection options passed in match those of the redirect called in the latest action. This match can be partial,
71
- # such that assert_redirected_to(:controller => "weblog") will also match the redirection of
72
- # redirect_to(:controller => "weblog", :action => "show") and so on.
73
- def assert_redirected_to(options = {}, message=nil)
74
- clean_backtrace do
75
- assert_response(:redirect, message)
76
-
77
- if options.is_a?(String)
78
- msg = build_message(message, "expected a redirect to <?>, found one to <?>", options, @response.redirect_url)
79
- url_regexp = %r{^(\w+://.*?(/|$|\?))(.*)$}
80
- eurl, epath, url, path = [options, @response.redirect_url].collect do |url|
81
- u, p = (url_regexp =~ url) ? [$1, $3] : [nil, url]
82
- [u, (p[0..0] == '/') ? p : '/' + p]
83
- end.flatten
84
-
85
- assert_equal(eurl, url, msg) if eurl && url
86
- assert_equal(epath, path, msg) if epath && path
87
- else
88
- @response_diff = options.diff(@response.redirected_to) if options.is_a?(Hash) && @response.redirected_to.is_a?(Hash)
89
- msg = build_message(message, "response is not a redirection to all of the options supplied (redirection is <?>)#{', difference: <?>' if @response_diff}",
90
- @response.redirected_to || @response.redirect_url, @response_diff)
91
-
92
- assert_block(msg) do
93
- if options.is_a?(Symbol)
94
- @response.redirected_to == options
95
- else
96
- options.keys.all? do |k|
97
- if k == :controller then options[k] == ActionController::Routing.controller_relative_to(@response.redirected_to[k], @controller.class.controller_path)
98
- else options[k] == (@response.redirected_to[k].respond_to?(:to_param) ? @response.redirected_to[k].to_param : @response.redirected_to[k] unless @response.redirected_to[k].nil?)
99
- end
100
- end
101
- end
102
- end
103
- end
104
- end
105
- end
106
-
107
- # Asserts that the request was rendered with the appropriate template file.
108
- def assert_template(expected = nil, message=nil)
109
- clean_backtrace do
110
- rendered = expected ? @response.rendered_file(!expected.include?('/')) : @response.rendered_file
111
- msg = build_message(message, "expecting <?> but rendering with <?>", expected, rendered)
112
- assert_block(msg) do
113
- if expected.nil?
114
- !@response.rendered_with_file?
115
- else
116
- expected == rendered
117
- end
118
- end
119
- end
120
- end
121
-
122
- # Asserts that the routing of the given path was handled correctly and that the parsed options match.
123
- def assert_recognizes(expected_options, path, extras={}, message=nil)
124
- clean_backtrace do
125
- path = "/#{path}" unless path[0..0] == '/'
126
- # Load routes.rb if it hasn't been loaded.
127
- ActionController::Routing::Routes.reload if ActionController::Routing::Routes.empty?
128
-
129
- # Assume given controller
130
- request = ActionController::TestRequest.new({}, {}, nil)
131
- request.path = path
132
- ActionController::Routing::Routes.recognize!(request)
133
-
134
- expected_options = expected_options.clone
135
- extras.each_key { |key| expected_options.delete key } unless extras.nil?
136
-
137
- expected_options.stringify_keys!
138
- msg = build_message(message, "The recognized options <?> did not match <?>",
139
- request.path_parameters, expected_options)
140
- assert_block(msg) { request.path_parameters == expected_options }
141
- end
142
- end
143
-
144
- # Asserts that the provided options can be used to generate the provided path.
145
- def assert_generates(expected_path, options, defaults={}, extras = {}, message=nil)
146
- clean_backtrace do
147
- expected_path = "/#{expected_path}" unless expected_path[0] == ?/
148
- # Load routes.rb if it hasn't been loaded.
149
- ActionController::Routing::Routes.reload if ActionController::Routing::Routes.empty?
150
-
151
- generated_path, extra_keys = ActionController::Routing::Routes.generate(options, extras)
152
- found_extras = options.reject {|k, v| ! extra_keys.include? k}
153
-
154
- msg = build_message(message, "found extras <?>, not <?>", found_extras, extras)
155
- assert_block(msg) { found_extras == extras }
156
-
157
- msg = build_message(message, "The generated path <?> did not match <?>", generated_path,
158
- expected_path)
159
- assert_block(msg) { expected_path == generated_path }
160
- end
161
- end
162
-
163
- # Asserts that path and options match both ways; in other words, the URL generated from
164
- # options is the same as path, and also that the options recognized from path are the same as options
165
- def assert_routing(path, options, defaults={}, extras={}, message=nil)
166
- assert_recognizes(options, path, extras, message)
167
-
168
- controller, default_controller = options[:controller], defaults[:controller]
169
- if controller && controller.include?(?/) && default_controller && default_controller.include?(?/)
170
- options[:controller] = "/#{controller}"
171
- end
172
-
173
- assert_generates(path, options, defaults, extras, message)
4
+ module ActionController #:nodoc:
5
+ # In addition to these specific assertions, you also have easy access to various collections that the regular test/unit assertions
6
+ # can be used against. These collections are:
7
+ #
8
+ # * assigns: Instance variables assigned in the action that are available for the view.
9
+ # * session: Objects being saved in the session.
10
+ # * flash: The flash objects currently in the session.
11
+ # * cookies: Cookies being sent to the user on this request.
12
+ #
13
+ # These collections can be used just like any other hash:
14
+ #
15
+ # assert_not_nil assigns(:person) # makes sure that a @person instance variable was set
16
+ # assert_equal "Dave", cookies[:name] # makes sure that a cookie called :name was set as "Dave"
17
+ # assert flash.empty? # makes sure that there's nothing in the flash
18
+ #
19
+ # For historic reasons, the assigns hash uses string-based keys. So assigns[:person] won't work, but assigns["person"] will. To
20
+ # appease our yearning for symbols, though, an alternative accessor has been deviced using a method call instead of index referencing.
21
+ # So assigns(:person) will work just like assigns["person"], but again, assigns[:person] will not work.
22
+ #
23
+ # On top of the collections, you have the complete url that a given action redirected to available in redirect_to_url.
24
+ #
25
+ # For redirects within the same controller, you can even call follow_redirect and the redirect will be followed, triggering another
26
+ # action call which can then be asserted against.
27
+ #
28
+ # == Manipulating the request collections
29
+ #
30
+ # The collections described above link to the response, so you can test if what the actions were expected to do happened. But
31
+ # sometimes you also want to manipulate these collections in the incoming request. This is really only relevant for sessions
32
+ # and cookies, though. For sessions, you just do:
33
+ #
34
+ # @request.session[:key] = "value"
35
+ #
36
+ # For cookies, you need to manually create the cookie, like this:
37
+ #
38
+ # @request.cookies["key"] = CGI::Cookie.new("key", "value")
39
+ #
40
+ # == Testing named routes
41
+ #
42
+ # If you're using named routes, they can be easily tested using the original named routes methods straight in the test case.
43
+ # Example:
44
+ #
45
+ # assert_redirected_to page_url(:title => 'foo')
46
+ module Assertions
47
+ def self.included(klass)
48
+ klass.class_eval do
49
+ include ActionController::Assertions::ResponseAssertions
50
+ include ActionController::Assertions::SelectorAssertions
51
+ include ActionController::Assertions::RoutingAssertions
52
+ include ActionController::Assertions::TagAssertions
53
+ include ActionController::Assertions::DomAssertions
54
+ include ActionController::Assertions::ModelAssertions
55
+ include ActionController::Assertions::DeprecatedAssertions
174
56
  end
57
+ end
175
58
 
176
- # Asserts that there is a tag/node/element in the body of the response
177
- # that meets all of the given conditions. The +conditions+ parameter must
178
- # be a hash of any of the following keys (all are optional):
179
- #
180
- # * <tt>:tag</tt>: the node type must match the corresponding value
181
- # * <tt>:attributes</tt>: a hash. The node's attributes must match the
182
- # corresponding values in the hash.
183
- # * <tt>:parent</tt>: a hash. The node's parent must match the
184
- # corresponding hash.
185
- # * <tt>:child</tt>: a hash. At least one of the node's immediate children
186
- # must meet the criteria described by the hash.
187
- # * <tt>:ancestor</tt>: a hash. At least one of the node's ancestors must
188
- # meet the criteria described by the hash.
189
- # * <tt>:descendant</tt>: a hash. At least one of the node's descendants
190
- # must meet the criteria described by the hash.
191
- # * <tt>:sibling</tt>: a hash. At least one of the node's siblings must
192
- # meet the criteria described by the hash.
193
- # * <tt>:after</tt>: a hash. The node must be after any sibling meeting
194
- # the criteria described by the hash, and at least one sibling must match.
195
- # * <tt>:before</tt>: a hash. The node must be before any sibling meeting
196
- # the criteria described by the hash, and at least one sibling must match.
197
- # * <tt>:children</tt>: a hash, for counting children of a node. Accepts
198
- # the keys:
199
- # * <tt>:count</tt>: either a number or a range which must equal (or
200
- # include) the number of children that match.
201
- # * <tt>:less_than</tt>: the number of matching children must be less
202
- # than this number.
203
- # * <tt>:greater_than</tt>: the number of matching children must be
204
- # greater than this number.
205
- # * <tt>:only</tt>: another hash consisting of the keys to use
206
- # to match on the children, and only matching children will be
207
- # counted.
208
- # * <tt>:content</tt>: the textual content of the node must match the
209
- # given value. This will not match HTML tags in the body of a
210
- # tag--only text.
211
- #
212
- # Conditions are matched using the following algorithm:
213
- #
214
- # * if the condition is a string, it must be a substring of the value.
215
- # * if the condition is a regexp, it must match the value.
216
- # * if the condition is a number, the value must match number.to_s.
217
- # * if the condition is +true+, the value must not be +nil+.
218
- # * if the condition is +false+ or +nil+, the value must be +nil+.
219
- #
220
- # Usage:
221
- #
222
- # # assert that there is a "span" tag
223
- # assert_tag :tag => "span"
224
- #
225
- # # assert that there is a "span" tag with id="x"
226
- # assert_tag :tag => "span", :attributes => { :id => "x" }
227
- #
228
- # # assert that there is a "span" tag using the short-hand
229
- # assert_tag :span
230
- #
231
- # # assert that there is a "span" tag with id="x" using the short-hand
232
- # assert_tag :span, :attributes => { :id => "x" }
233
- #
234
- # # assert that there is a "span" inside of a "div"
235
- # assert_tag :tag => "span", :parent => { :tag => "div" }
236
- #
237
- # # assert that there is a "span" somewhere inside a table
238
- # assert_tag :tag => "span", :ancestor => { :tag => "table" }
239
- #
240
- # # assert that there is a "span" with at least one "em" child
241
- # assert_tag :tag => "span", :child => { :tag => "em" }
242
- #
243
- # # assert that there is a "span" containing a (possibly nested)
244
- # # "strong" tag.
245
- # assert_tag :tag => "span", :descendant => { :tag => "strong" }
246
- #
247
- # # assert that there is a "span" containing between 2 and 4 "em" tags
248
- # # as immediate children
249
- # assert_tag :tag => "span",
250
- # :children => { :count => 2..4, :only => { :tag => "em" } }
251
- #
252
- # # get funky: assert that there is a "div", with an "ul" ancestor
253
- # # and an "li" parent (with "class" = "enum"), and containing a
254
- # # "span" descendant that contains text matching /hello world/
255
- # assert_tag :tag => "div",
256
- # :ancestor => { :tag => "ul" },
257
- # :parent => { :tag => "li",
258
- # :attributes => { :class => "enum" } },
259
- # :descendant => { :tag => "span",
260
- # :child => /hello world/ }
261
- #
262
- # <strong>Please note</strong: #assert_tag and #assert_no_tag only work
263
- # with well-formed XHTML. They recognize a few tags as implicitly self-closing
264
- # (like br and hr and such) but will not work correctly with tags
265
- # that allow optional closing tags (p, li, td). <em>You must explicitly
266
- # close all of your tags to use these assertions.</em>
267
- def assert_tag(*opts)
268
- clean_backtrace do
269
- opts = opts.size > 1 ? opts.last.merge({ :tag => opts.first.to_s }) : opts.first
270
- tag = find_tag(opts)
271
- assert tag, "expected tag, but no tag found matching #{opts.inspect} in:\n#{@response.body.inspect}"
272
- end
273
- end
274
-
275
- # Identical to #assert_tag, but asserts that a matching tag does _not_
276
- # exist. (See #assert_tag for a full discussion of the syntax.)
277
- def assert_no_tag(*opts)
278
- clean_backtrace do
279
- opts = opts.size > 1 ? opts.last.merge({ :tag => opts.first.to_s }) : opts.first
280
- tag = find_tag(opts)
281
- assert !tag, "expected no tag, but found tag matching #{opts.inspect} in:\n#{@response.body.inspect}"
282
- end
283
- end
59
+ def clean_backtrace(&block)
60
+ yield
61
+ rescue Test::Unit::AssertionFailedError => e
62
+ path = File.expand_path(__FILE__)
63
+ raise Test::Unit::AssertionFailedError, e.message, e.backtrace.reject { |line| File.expand_path(line) =~ /#{path}/ }
64
+ end
65
+ end
66
+ end
284
67
 
285
- # test 2 html strings to be equivalent, i.e. identical up to reordering of attributes
286
- def assert_dom_equal(expected, actual, message="")
287
- clean_backtrace do
288
- expected_dom = HTML::Document.new(expected).root
289
- actual_dom = HTML::Document.new(actual).root
290
- full_message = build_message(message, "<?> expected to be == to\n<?>.", expected_dom.to_s, actual_dom.to_s)
291
- assert_block(full_message) { expected_dom == actual_dom }
292
- end
293
- end
294
-
295
- # negated form of +assert_dom_equivalent+
296
- def assert_dom_not_equal(expected, actual, message="")
297
- clean_backtrace do
298
- expected_dom = HTML::Document.new(expected).root
299
- actual_dom = HTML::Document.new(actual).root
300
- full_message = build_message(message, "<?> expected to be != to\n<?>.", expected_dom.to_s, actual_dom.to_s)
301
- assert_block(full_message) { expected_dom != actual_dom }
302
- end
303
- end
68
+ require File.dirname(__FILE__) + '/assertions/response_assertions'
69
+ require File.dirname(__FILE__) + '/assertions/selector_assertions'
70
+ require File.dirname(__FILE__) + '/assertions/tag_assertions'
71
+ require File.dirname(__FILE__) + '/assertions/dom_assertions'
72
+ require File.dirname(__FILE__) + '/assertions/routing_assertions'
73
+ require File.dirname(__FILE__) + '/assertions/model_assertions'
74
+ require File.dirname(__FILE__) + '/assertions/deprecated_assertions'
304
75
 
305
- # ensures that the passed record is valid by active record standards. returns the error messages if not
306
- def assert_valid(record)
307
- clean_backtrace do
308
- assert record.valid?, record.errors.full_messages.join("\n")
309
- end
310
- end
311
-
312
- def clean_backtrace(&block)
313
- yield
314
- rescue AssertionFailedError => e
315
- path = File.expand_path(__FILE__)
316
- raise AssertionFailedError, e.message, e.backtrace.reject { |line| File.expand_path(line) =~ /#{path}/ }
317
- end
76
+ module Test #:nodoc:
77
+ module Unit #:nodoc:
78
+ class TestCase #:nodoc:
79
+ include ActionController::Assertions
318
80
  end
319
81
  end
320
- end
82
+ end