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.
- data/CHANGELOG +517 -15
- data/MIT-LICENSE +1 -1
- data/README +18 -20
- data/Rakefile +7 -4
- data/examples/address_book_controller.rb +3 -3
- data/examples/blog_controller.cgi +3 -3
- data/examples/debate_controller.cgi +5 -5
- data/lib/action_controller.rb +2 -2
- data/lib/action_controller/assertions.rb +73 -311
- data/lib/action_controller/{deprecated_assertions.rb → assertions/deprecated_assertions.rb} +32 -8
- data/lib/action_controller/assertions/dom_assertions.rb +25 -0
- data/lib/action_controller/assertions/model_assertions.rb +12 -0
- data/lib/action_controller/assertions/response_assertions.rb +140 -0
- data/lib/action_controller/assertions/routing_assertions.rb +82 -0
- data/lib/action_controller/assertions/selector_assertions.rb +571 -0
- data/lib/action_controller/assertions/tag_assertions.rb +117 -0
- data/lib/action_controller/base.rb +334 -163
- data/lib/action_controller/benchmarking.rb +3 -6
- data/lib/action_controller/caching.rb +83 -22
- data/lib/action_controller/cgi_ext/cgi_ext.rb +0 -7
- data/lib/action_controller/cgi_ext/cgi_methods.rb +167 -173
- data/lib/action_controller/cgi_ext/raw_post_data_fix.rb +43 -22
- data/lib/action_controller/cgi_process.rb +50 -27
- data/lib/action_controller/components.rb +21 -25
- data/lib/action_controller/cookies.rb +10 -9
- data/lib/action_controller/{dependencies.rb → deprecated_dependencies.rb} +9 -27
- data/lib/action_controller/filters.rb +448 -225
- data/lib/action_controller/flash.rb +24 -20
- data/lib/action_controller/helpers.rb +2 -5
- data/lib/action_controller/integration.rb +40 -16
- data/lib/action_controller/layout.rb +11 -8
- data/lib/action_controller/macros/auto_complete.rb +3 -2
- data/lib/action_controller/macros/in_place_editing.rb +3 -2
- data/lib/action_controller/mime_responds.rb +41 -29
- data/lib/action_controller/mime_type.rb +68 -10
- data/lib/action_controller/pagination.rb +4 -3
- data/lib/action_controller/request.rb +22 -14
- data/lib/action_controller/rescue.rb +25 -22
- data/lib/action_controller/resources.rb +302 -0
- data/lib/action_controller/response.rb +20 -2
- data/lib/action_controller/response.rb.rej +17 -0
- data/lib/action_controller/routing.rb +1165 -567
- data/lib/action_controller/scaffolding.rb +30 -31
- data/lib/action_controller/session/active_record_store.rb +2 -0
- data/lib/action_controller/session/drb_store.rb +4 -0
- data/lib/action_controller/session/mem_cache_store.rb +4 -0
- data/lib/action_controller/session_management.rb +6 -9
- data/lib/action_controller/status_codes.rb +89 -0
- data/lib/action_controller/streaming.rb +6 -15
- data/lib/action_controller/templates/rescues/_request_and_response.rhtml +5 -5
- data/lib/action_controller/templates/rescues/diagnostics.rhtml +2 -2
- data/lib/action_controller/templates/rescues/routing_error.rhtml +4 -4
- data/lib/action_controller/templates/rescues/template_error.rhtml +1 -1
- data/lib/action_controller/templates/scaffolds/list.rhtml +1 -1
- data/lib/action_controller/test_process.rb +52 -30
- data/lib/action_controller/url_rewriter.rb +63 -29
- data/lib/action_controller/vendor/html-scanner/html/document.rb +1 -0
- data/lib/action_controller/vendor/html-scanner/html/node.rb +3 -4
- data/lib/action_controller/vendor/html-scanner/html/selector.rb +822 -0
- data/lib/action_controller/verification.rb +22 -11
- data/lib/action_pack.rb +1 -1
- data/lib/action_pack/version.rb +2 -2
- data/lib/action_view.rb +1 -1
- data/lib/action_view/base.rb +46 -43
- data/lib/action_view/compiled_templates.rb +1 -1
- data/lib/action_view/helpers/active_record_helper.rb +54 -17
- data/lib/action_view/helpers/asset_tag_helper.rb +97 -46
- data/lib/action_view/helpers/capture_helper.rb +1 -1
- data/lib/action_view/helpers/date_helper.rb +258 -136
- data/lib/action_view/helpers/debug_helper.rb +1 -1
- data/lib/action_view/helpers/deprecated_helper.rb +34 -0
- data/lib/action_view/helpers/form_helper.rb +75 -35
- data/lib/action_view/helpers/form_options_helper.rb +7 -5
- data/lib/action_view/helpers/form_tag_helper.rb +44 -6
- data/lib/action_view/helpers/java_script_macros_helper.rb +59 -46
- data/lib/action_view/helpers/javascript_helper.rb +71 -10
- data/lib/action_view/helpers/javascripts/controls.js +41 -23
- data/lib/action_view/helpers/javascripts/dragdrop.js +105 -76
- data/lib/action_view/helpers/javascripts/effects.js +293 -163
- data/lib/action_view/helpers/javascripts/prototype.js +897 -389
- data/lib/action_view/helpers/javascripts/prototype.js.rej +561 -0
- data/lib/action_view/helpers/number_helper.rb +111 -65
- data/lib/action_view/helpers/prototype_helper.rb +84 -109
- data/lib/action_view/helpers/scriptaculous_helper.rb +5 -0
- data/lib/action_view/helpers/tag_helper.rb +69 -16
- data/lib/action_view/helpers/text_helper.rb +149 -112
- data/lib/action_view/helpers/url_helper.rb +200 -107
- data/lib/action_view/template_error.rb +66 -42
- data/test/abstract_unit.rb +4 -2
- data/test/active_record_unit.rb +84 -56
- data/test/activerecord/active_record_assertions_test.rb +26 -18
- data/test/activerecord/active_record_store_test.rb +4 -36
- data/test/activerecord/pagination_test.rb +1 -6
- data/test/controller/action_pack_assertions_test.rb +230 -113
- data/test/controller/addresses_render_test.rb +2 -6
- data/test/controller/assert_select_test.rb +576 -0
- data/test/controller/base_test.rb +73 -3
- data/test/controller/caching_test.rb +228 -0
- data/test/controller/capture_test.rb +12 -10
- data/test/controller/cgi_test.rb +89 -12
- data/test/controller/components_test.rb +24 -2
- data/test/controller/content_type_test.rb +139 -0
- data/test/controller/controller_fixtures/app/controllers/admin/user_controller.rb +0 -0
- data/test/controller/controller_fixtures/app/controllers/user_controller.rb +0 -0
- data/test/controller/controller_fixtures/vendor/plugins/bad_plugin/lib/plugin_controller.rb +0 -0
- data/test/controller/cookie_test.rb +33 -25
- data/test/controller/deprecated_instance_variables_test.rb +48 -0
- data/test/controller/deprecation/deprecated_base_methods_test.rb +60 -0
- data/test/controller/fake_controllers.rb +0 -1
- data/test/controller/filters_test.rb +301 -16
- data/test/controller/flash_test.rb +19 -2
- data/test/controller/helper_test.rb +2 -2
- data/test/controller/integration_test.rb +154 -0
- data/test/controller/layout_test.rb +115 -1
- data/test/controller/mime_responds_test.rb +94 -0
- data/test/controller/mime_type_test.rb +9 -0
- data/test/controller/new_render_test.rb +161 -11
- data/test/controller/raw_post_test.rb +52 -15
- data/test/controller/redirect_test.rb +27 -14
- data/test/controller/render_test.rb +76 -29
- data/test/controller/request_test.rb +55 -4
- data/test/controller/resources_test.rb +274 -0
- data/test/controller/routing_test.rb +1533 -824
- data/test/controller/selector_test.rb +628 -0
- data/test/controller/send_file_test.rb +9 -1
- data/test/controller/session_management_test.rb +51 -0
- data/test/controller/test_test.rb +113 -29
- data/test/controller/url_rewriter_test.rb +86 -17
- data/test/controller/verification_test.rb +19 -17
- data/test/controller/webservice_test.rb +0 -7
- data/test/fixtures/content_type/render_default_content_types_for_respond_to.rhtml +1 -0
- data/test/fixtures/content_type/render_default_for_rhtml.rhtml +1 -0
- data/test/fixtures/content_type/render_default_for_rjs.rjs +1 -0
- data/test/fixtures/content_type/render_default_for_rxml.rxml +1 -0
- data/test/fixtures/deprecated_instance_variables/_cookies_ivar.rhtml +1 -0
- data/test/fixtures/deprecated_instance_variables/_cookies_method.rhtml +1 -0
- data/test/fixtures/deprecated_instance_variables/_flash_ivar.rhtml +1 -0
- data/test/fixtures/deprecated_instance_variables/_flash_method.rhtml +1 -0
- data/test/fixtures/deprecated_instance_variables/_headers_ivar.rhtml +1 -0
- data/test/fixtures/deprecated_instance_variables/_headers_method.rhtml +1 -0
- data/test/fixtures/deprecated_instance_variables/_params_ivar.rhtml +1 -0
- data/test/fixtures/deprecated_instance_variables/_params_method.rhtml +1 -0
- data/test/fixtures/deprecated_instance_variables/_request_ivar.rhtml +1 -0
- data/test/fixtures/deprecated_instance_variables/_request_method.rhtml +1 -0
- data/test/fixtures/deprecated_instance_variables/_response_ivar.rhtml +1 -0
- data/test/fixtures/deprecated_instance_variables/_response_method.rhtml +1 -0
- data/test/fixtures/deprecated_instance_variables/_session_ivar.rhtml +1 -0
- data/test/fixtures/deprecated_instance_variables/_session_method.rhtml +1 -0
- data/test/fixtures/multipart/binary_file +0 -0
- data/test/fixtures/public/javascripts/application.js +1 -0
- data/test/fixtures/test/_hello.rxml +1 -0
- data/test/fixtures/test/hello_world_container.rxml +3 -0
- data/test/fixtures/topic.rb +2 -2
- data/test/template/active_record_helper_test.rb +83 -12
- data/test/template/asset_tag_helper_test.rb +75 -95
- data/test/template/compiled_templates_test.rb +1 -0
- data/test/template/date_helper_test.rb +873 -181
- data/test/template/deprecated_helper_test.rb +36 -0
- data/test/template/deprecated_instance_variables_test.rb +43 -0
- data/test/template/form_helper_test.rb +77 -1
- data/test/template/form_options_helper_test.rb +4 -0
- data/test/template/form_tag_helper_test.rb +66 -2
- data/test/template/java_script_macros_helper_test.rb +4 -1
- data/test/template/javascript_helper_test.rb +29 -0
- data/test/template/number_helper_test.rb +63 -27
- data/test/template/prototype_helper_test.rb +77 -34
- data/test/template/tag_helper_test.rb +34 -6
- data/test/template/text_helper_test.rb +69 -34
- data/test/template/url_helper_test.rb +168 -16
- data/test/testing_sandbox.rb +7 -22
- metadata +66 -20
- data/filler.txt +0 -50
- data/lib/action_controller/code_generation.rb +0 -235
- data/lib/action_controller/vendor/xml_simple.rb +0 -1019
- data/test/controller/caching_filestore.rb +0 -74
- data/test/fixtures/application_root/app/controllers/a_class_that_contains_a_controller/poorly_placed_controller.rb +0 -7
- data/test/fixtures/application_root/app/controllers/module_that_holds_controllers/nested_controller.rb +0 -3
- data/test/fixtures/application_root/app/models/a_class_that_contains_a_controller.rb +0 -7
- data/test/fixtures/dont_load.rb +0 -3
data/MIT-LICENSE
CHANGED
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
|
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
|
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><%=
|
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
|
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
|
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
|
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
|
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.
|
368
|
+
@posts = Post.find(:all)
|
370
369
|
end
|
371
370
|
|
372
371
|
def display
|
373
|
-
@post = Post.find(
|
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
|
-
<%=
|
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://
|
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.
|
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
|
-
|
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
|
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.
|
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", "
|
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(
|
31
|
+
@person = @address_book.find_person(params[:id])
|
32
32
|
end
|
33
33
|
|
34
34
|
def create_person
|
35
|
-
@address_book.create_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
|
-
<%=
|
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(
|
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(
|
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(
|
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(
|
40
|
-
redirect_to :action => "topic", :path_params => { "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
|
data/lib/action_controller.rb
CHANGED
@@ -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/
|
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
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
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
|
-
|
177
|
-
|
178
|
-
|
179
|
-
|
180
|
-
|
181
|
-
|
182
|
-
|
183
|
-
|
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
|
-
|
286
|
-
|
287
|
-
|
288
|
-
|
289
|
-
|
290
|
-
|
291
|
-
|
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
|
-
|
306
|
-
|
307
|
-
|
308
|
-
|
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
|