diff options
Diffstat (limited to 'vendor/rails-2.0.2/actionpack/test/controller')
56 files changed, 15008 insertions, 0 deletions
diff --git a/vendor/rails-2.0.2/actionpack/test/controller/action_pack_assertions_test.rb b/vendor/rails-2.0.2/actionpack/test/controller/action_pack_assertions_test.rb new file mode 100644 index 000000000..1eb9610d0 --- /dev/null +++ b/vendor/rails-2.0.2/actionpack/test/controller/action_pack_assertions_test.rb @@ -0,0 +1,492 @@ +require File.dirname(__FILE__) + '/../abstract_unit' + +# a controller class to facilitate the tests +class ActionPackAssertionsController < ActionController::Base + + # this does absolutely nothing + def nothing() head :ok end + + # a standard template + def hello_world() render :template => "test/hello_world"; end + + # a standard template + def hello_xml_world() render :template => "test/hello_xml_world"; end + + # a redirect to an internal location + def redirect_internal() redirect_to "/nothing"; end + + def redirect_to_action() redirect_to :action => "flash_me", :id => 1, :params => { "panda" => "fun" }; end + + def redirect_to_controller() redirect_to :controller => "elsewhere", :action => "flash_me"; end + + def redirect_to_controller_with_symbol() redirect_to :controller => :elsewhere, :action => :flash_me; end + + def redirect_to_path() redirect_to '/some/path' end + + def redirect_to_named_route() redirect_to route_one_url end + + # a redirect to an external location + def redirect_external() redirect_to "http://www.rubyonrails.org"; end + + # a 404 + def response404() head '404 AWOL' end + + # a 500 + def response500() head '500 Sorry' end + + # a fictional 599 + def response599() head '599 Whoah!' end + + # putting stuff in the flash + def flash_me + flash['hello'] = 'my name is inigo montoya...' + render :text => "Inconceivable!" + end + + # we have a flash, but nothing is in it + def flash_me_naked + flash.clear + render :text => "wow!" + end + + # assign some template instance variables + def assign_this + @howdy = "ho" + render :inline => "Mr. Henke" + end + + def render_based_on_parameters + render :text => "Mr. #{params[:name]}" + end + + def render_url + render :text => "<div>#{url_for(:action => 'flash_me', :only_path => true)}</div>" + end + + def render_text_with_custom_content_type + render :text => "Hello!", :content_type => Mime::RSS + end + + # puts something in the session + def session_stuffing + session['xmas'] = 'turkey' + render :text => "ho ho ho" + end + + # raises exception on get requests + def raise_on_get + raise "get" if request.get? + render :text => "request method: #{request.env['REQUEST_METHOD']}" + end + + # raises exception on post requests + def raise_on_post + raise "post" if request.post? + render :text => "request method: #{request.env['REQUEST_METHOD']}" + end + + def get_valid_record + @record = Class.new do + def valid? + true + end + + def errors + Class.new do + def full_messages; []; end + end.new + end + + end.new + + render :nothing => true + end + + + def get_invalid_record + @record = Class.new do + + def valid? + false + end + + def errors + Class.new do + def full_messages; ['...stuff...']; end + end.new + end + end.new + + render :nothing => true + end + + # 911 + def rescue_action(e) raise; end +end + +module Admin + class InnerModuleController < ActionController::Base + def index + render :nothing => true + end + + def redirect_to_index + redirect_to admin_inner_module_path + end + + def redirect_to_absolute_controller + redirect_to :controller => '/content' + end + + def redirect_to_fellow_controller + redirect_to :controller => 'user' + end + + def redirect_to_top_level_named_route + redirect_to top_level_url(:id => "foo") + end + end +end + +# --------------------------------------------------------------------------- + + +# tell the controller where to find its templates but start from parent +# directory of test_request_response to simulate the behaviour of a +# production environment +ActionPackAssertionsController.view_paths = [ File.dirname(__FILE__) + "/../fixtures/" ] + +# a test case to exercise the new capabilities TestRequest & TestResponse +class ActionPackAssertionsControllerTest < Test::Unit::TestCase + # let's get this party started + def setup + ActionController::Routing::Routes.reload + ActionController::Routing.use_controllers!(%w(action_pack_assertions admin/inner_module content admin/user)) + @controller = ActionPackAssertionsController.new + @request, @response = ActionController::TestRequest.new, ActionController::TestResponse.new + end + + def teardown + ActionController::Routing::Routes.reload + end + + # -- assertion-based testing ------------------------------------------------ + + def test_assert_tag_and_url_for + get :render_url + assert_tag :content => "/action_pack_assertions/flash_me" + end + + # test the get method, make sure the request really was a get + def test_get + assert_raise(RuntimeError) { get :raise_on_get } + get :raise_on_post + assert_equal @response.body, 'request method: GET' + end + + # test the get method, make sure the request really was a get + def test_post + assert_raise(RuntimeError) { post :raise_on_post } + post :raise_on_get + assert_equal @response.body, 'request method: POST' + end + +# the following test fails because the request_method is now cached on the request instance +# test the get/post switch within one test action +# def test_get_post_switch +# post :raise_on_get +# assert_equal @response.body, 'request method: POST' +# get :raise_on_post +# assert_equal @response.body, 'request method: GET' +# post :raise_on_get +# assert_equal @response.body, 'request method: POST' +# get :raise_on_post +# assert_equal @response.body, 'request method: GET' +# end + + # test the redirection to a named route + def test_assert_redirect_to_named_route + with_routing do |set| + set.draw do |map| + map.route_one 'route_one', :controller => 'action_pack_assertions', :action => 'nothing' + map.connect ':controller/:action/:id' + end + set.install_helpers + + process :redirect_to_named_route + assert_redirected_to 'http://test.host/route_one' + assert_redirected_to route_one_url + assert_redirected_to :route_one_url + end + end + + def test_assert_redirect_to_named_route_failure + with_routing do |set| + set.draw do |map| + map.route_one 'route_one', :controller => 'action_pack_assertions', :action => 'nothing', :id => 'one' + map.route_two 'route_two', :controller => 'action_pack_assertions', :action => 'nothing', :id => 'two' + map.connect ':controller/:action/:id' + end + process :redirect_to_named_route + assert_raise(Test::Unit::AssertionFailedError) do + assert_redirected_to 'http://test.host/route_two' + end + assert_raise(Test::Unit::AssertionFailedError) do + assert_redirected_to :controller => 'action_pack_assertions', :action => 'nothing', :id => 'two' + end + assert_raise(Test::Unit::AssertionFailedError) do + assert_redirected_to route_two_url + end + assert_raise(Test::Unit::AssertionFailedError) do + assert_redirected_to :route_two_url + end + end + end + + def test_assert_redirect_to_nested_named_route + with_routing do |set| + set.draw do |map| + map.admin_inner_module 'admin/inner_module', :controller => 'admin/inner_module', :action => 'index' + map.connect ':controller/:action/:id' + end + @controller = Admin::InnerModuleController.new + process :redirect_to_index + # redirection is <{"action"=>"index", "controller"=>"admin/admin/inner_module"}> + assert_redirected_to admin_inner_module_path + end + end + + def test_assert_redirected_to_top_level_named_route_from_nested_controller + with_routing do |set| + set.draw do |map| + map.top_level '/action_pack_assertions/:id', :controller => 'action_pack_assertions', :action => 'index' + map.connect ':controller/:action/:id' + end + @controller = Admin::InnerModuleController.new + process :redirect_to_top_level_named_route + # passes -> assert_redirected_to "http://test.host/action_pack_assertions/foo" + assert_redirected_to "/action_pack_assertions/foo" + end + end + + # -- standard request/response object testing -------------------------------- + + # make sure that the template objects exist + def test_template_objects_alive + process :assign_this + assert !@response.has_template_object?('hi') + assert @response.has_template_object?('howdy') + end + + # make sure we don't have template objects when we shouldn't + def test_template_object_missing + process :nothing + assert_nil @response.template_objects['howdy'] + end + + # check the empty flashing + def test_flash_me_naked + process :flash_me_naked + assert !@response.has_flash? + assert !@response.has_flash_with_contents? + end + + # check if we have flash objects + def test_flash_haves + process :flash_me + assert @response.has_flash? + assert @response.has_flash_with_contents? + assert @response.has_flash_object?('hello') + end + + # ensure we don't have flash objects + def test_flash_have_nots + process :nothing + assert !@response.has_flash? + assert !@response.has_flash_with_contents? + assert_nil @response.flash['hello'] + end + + # check if we were rendered by a file-based template? + def test_rendered_action + process :nothing + assert !@response.rendered_with_file? + + process :hello_world + assert @response.rendered_with_file? + assert 'hello_world', @response.rendered_file + end + + # check the redirection location + def test_redirection_location + process :redirect_internal + assert_equal 'http://test.host/nothing', @response.redirect_url + + process :redirect_external + assert_equal 'http://www.rubyonrails.org', @response.redirect_url + end + + def test_no_redirect_url + process :nothing + assert_nil @response.redirect_url + end + + + # check server errors + def test_server_error_response_code + process :response500 + assert @response.server_error? + + process :response599 + assert @response.server_error? + + process :response404 + assert !@response.server_error? + end + + # check a 404 response code + def test_missing_response_code + process :response404 + assert @response.missing? + end + + # check to see if our redirection matches a pattern + def test_redirect_url_match + process :redirect_external + assert @response.redirect? + assert @response.redirect_url_match?("rubyonrails") + assert @response.redirect_url_match?(/rubyonrails/) + assert !@response.redirect_url_match?("phpoffrails") + assert !@response.redirect_url_match?(/perloffrails/) + end + + # check for a redirection + def test_redirection + process :redirect_internal + assert @response.redirect? + + process :redirect_external + assert @response.redirect? + + process :nothing + assert !@response.redirect? + end + + # check a successful response code + def test_successful_response_code + process :nothing + assert @response.success? + end + + # a basic check to make sure we have a TestResponse object + def test_has_response + process :nothing + assert_kind_of ActionController::TestResponse, @response + end + + def test_render_based_on_parameters + process :render_based_on_parameters, "name" => "David" + assert_equal "Mr. David", @response.body + end + + def test_follow_redirect + process :redirect_to_action + assert_redirected_to :action => "flash_me" + + follow_redirect + assert_equal 1, @request.parameters["id"].to_i + + assert "Inconceivable!", @response.body + end + + def test_follow_redirect_outside_current_action + process :redirect_to_controller + assert_redirected_to :controller => "elsewhere", :action => "flash_me" + + assert_raises(RuntimeError, "Can't follow redirects outside of current controller (elsewhere)") { follow_redirect } + end + + def test_assert_redirection_fails_with_incorrect_controller + process :redirect_to_controller + assert_raise(Test::Unit::AssertionFailedError) do + assert_redirected_to :controller => "action_pack_assertions", :action => "flash_me" + end + end + + def test_assert_redirection_with_extra_controller_option + get :redirect_to_action + assert_redirected_to :controller => 'action_pack_assertions', :action => "flash_me", :id => 1, :params => { :panda => 'fun' } + end + + def test_redirected_to_url_leadling_slash + process :redirect_to_path + assert_redirected_to '/some/path' + end + def test_redirected_to_url_no_leadling_slash + process :redirect_to_path + assert_redirected_to 'some/path' + end + def test_redirected_to_url_full_url + process :redirect_to_path + assert_redirected_to 'http://test.host/some/path' + end + + def test_assert_redirection_with_symbol + process :redirect_to_controller_with_symbol + assert_nothing_raised { + assert_redirected_to :controller => "elsewhere", :action => "flash_me" + } + process :redirect_to_controller_with_symbol + assert_nothing_raised { + assert_redirected_to :controller => :elsewhere, :action => :flash_me + } + end + + def test_redirected_to_with_nested_controller + @controller = Admin::InnerModuleController.new + get :redirect_to_absolute_controller + assert_redirected_to :controller => 'content' + + get :redirect_to_fellow_controller + assert_redirected_to :controller => 'admin/user' + end + + def test_assert_valid + get :get_valid_record + assert_valid assigns('record') + end + + def test_assert_valid_failing + get :get_invalid_record + + begin + assert_valid assigns('record') + assert false + rescue Test::Unit::AssertionFailedError => e + end + end +end + +class ActionPackHeaderTest < Test::Unit::TestCase + def setup + @controller = ActionPackAssertionsController.new + @request, @response = ActionController::TestRequest.new, ActionController::TestResponse.new + end + + def test_rendering_xml_sets_content_type + process :hello_xml_world + assert_equal('application/xml; charset=utf-8', @response.headers['type']) + end + + def test_rendering_xml_respects_content_type + @response.headers['type'] = 'application/pdf' + process :hello_xml_world + assert_equal('application/pdf; charset=utf-8', @response.headers['type']) + end + + + def test_render_text_with_custom_content_type + get :render_text_with_custom_content_type + assert_equal 'application/rss+xml; charset=utf-8', @response.headers['type'] + end +end diff --git a/vendor/rails-2.0.2/actionpack/test/controller/addresses_render_test.rb b/vendor/rails-2.0.2/actionpack/test/controller/addresses_render_test.rb new file mode 100644 index 000000000..d1e9122dc --- /dev/null +++ b/vendor/rails-2.0.2/actionpack/test/controller/addresses_render_test.rb @@ -0,0 +1,43 @@ +require File.dirname(__FILE__) + '/../abstract_unit' + +class Address + + def Address.count(conditions = nil, join = nil) + nil + end + + def Address.find_all(arg1, arg2, arg3, arg4) + [] + end + + def self.find(*args) + [] + end +end + +class AddressesTestController < ActionController::Base + def self.controller_name; "addresses"; end + def self.controller_path; "addresses"; end +end + +AddressesTestController.view_paths = [ File.dirname(__FILE__) + "/../fixtures/" ] + +class AddressesTest < Test::Unit::TestCase + def setup + @controller = AddressesTestController.new + + # enable a logger so that (e.g.) the benchmarking stuff runs, so we can get + # a more accurate simulation of what happens in "real life". + @controller.logger = Logger.new(nil) + + @request = ActionController::TestRequest.new + @response = ActionController::TestResponse.new + + @request.host = "www.nextangle.com" + end + + def test_list + get :list + assert_equal "We only need to get this far!", @response.body.chomp + end +end diff --git a/vendor/rails-2.0.2/actionpack/test/controller/assert_select_test.rb b/vendor/rails-2.0.2/actionpack/test/controller/assert_select_test.rb new file mode 100644 index 000000000..b0f3d6ced --- /dev/null +++ b/vendor/rails-2.0.2/actionpack/test/controller/assert_select_test.rb @@ -0,0 +1,682 @@ +#-- +# Copyright (c) 2006 Assaf Arkin (http://labnotes.org) +# Under MIT and/or CC By license. +#++ + +require "#{File.dirname(__FILE__)}/../abstract_unit" +require "#{File.dirname(__FILE__)}/fake_controllers" + + +unless defined?(ActionMailer) + begin + $:.unshift(File.dirname(__FILE__) + "/../../../actionmailer/lib") + require 'action_mailer' + rescue LoadError + require 'rubygems' + gem 'actionmailer' + end +end + +class AssertSelectTest < Test::Unit::TestCase + class AssertSelectController < ActionController::Base + def response_with=(content) + @content = content + end + + def response_with(&block) + @update = block + end + + def html() + render :text=>@content, :layout=>false, :content_type=>Mime::HTML + @content = nil + end + + def rjs() + render :update do |page| + @update.call page + end + @update = nil + end + + def xml() + render :text=>@content, :layout=>false, :content_type=>Mime::XML + @content = nil + end + + def rescue_action(e) + raise e + end + end + + class AssertSelectMailer < ActionMailer::Base + def test(html) + recipients "test <test@test.host>" + from "test@test.host" + subject "Test e-mail" + part :content_type=>"text/html", :body=>html + end + end + + AssertionFailedError = Test::Unit::AssertionFailedError + + def setup + @controller = AssertSelectController.new + @request = ActionController::TestRequest.new + @response = ActionController::TestResponse.new + ActionMailer::Base.delivery_method = :test + ActionMailer::Base.perform_deliveries = true + ActionMailer::Base.deliveries = [] + end + + + def teardown + ActionMailer::Base.deliveries.clear + end + + def assert_failure(message, &block) + e = assert_raises(AssertionFailedError, &block) + assert_match(message, e.message) if Regexp === message + assert_equal(message, e.message) if String === message + end + + # + # Test assert select. + # + + def test_assert_select + render_html %Q{<div id="1"></div><div id="2"></div>} + assert_select "div", 2 + assert_failure(/Expected at least 3 elements matching \"div\", found 2/) { assert_select "div", 3 } + assert_failure(/Expected at least 1 element matching \"p\", found 0/) { assert_select "p" } + end + + + def test_equality_true_false + render_html %Q{<div id="1"></div><div id="2"></div>} + assert_nothing_raised { assert_select "div" } + assert_raises(AssertionFailedError) { assert_select "p" } + assert_nothing_raised { assert_select "div", true } + assert_raises(AssertionFailedError) { assert_select "p", true } + assert_raises(AssertionFailedError) { assert_select "div", false } + assert_nothing_raised { assert_select "p", false } + end + + + def test_equality_string_and_regexp + render_html %Q{<div id="1">foo</div><div id="2">foo</div>} + assert_nothing_raised { assert_select "div", "foo" } + assert_raises(AssertionFailedError) { assert_select "div", "bar" } + assert_nothing_raised { assert_select "div", :text=>"foo" } + assert_raises(AssertionFailedError) { assert_select "div", :text=>"bar" } + assert_nothing_raised { assert_select "div", /(foo|bar)/ } + assert_raises(AssertionFailedError) { assert_select "div", /foobar/ } + assert_nothing_raised { assert_select "div", :text=>/(foo|bar)/ } + assert_raises(AssertionFailedError) { assert_select "div", :text=>/foobar/ } + assert_raises(AssertionFailedError) { assert_select "p", :text=>/foobar/ } + end + + + def test_equality_of_html + render_html %Q{<p>\n<em>"This is <strong>not</strong> a big problem,"</em> he said.\n</p>} + text = "\"This is not a big problem,\" he said." + html = "<em>\"This is <strong>not</strong> a big problem,\"</em> he said." + assert_nothing_raised { assert_select "p", text } + assert_raises(AssertionFailedError) { assert_select "p", html } + assert_nothing_raised { assert_select "p", :html=>html } + assert_raises(AssertionFailedError) { assert_select "p", :html=>text } + # No stripping for pre. + render_html %Q{<pre>\n<em>"This is <strong>not</strong> a big problem,"</em> he said.\n</pre>} + text = "\n\"This is not a big problem,\" he said.\n" + html = "\n<em>\"This is <strong>not</strong> a big problem,\"</em> he said.\n" + assert_nothing_raised { assert_select "pre", text } + assert_raises(AssertionFailedError) { assert_select "pre", html } + assert_nothing_raised { assert_select "pre", :html=>html } + assert_raises(AssertionFailedError) { assert_select "pre", :html=>text } + end + + + def test_counts + render_html %Q{<div id="1">foo</div><div id="2">foo</div>} + assert_nothing_raised { assert_select "div", 2 } + assert_failure(/Expected at least 3 elements matching \"div\", found 2/) do + assert_select "div", 3 + end + assert_nothing_raised { assert_select "div", 1..2 } + assert_failure(/Expected between 3 and 4 elements matching \"div\", found 2/) do + assert_select "div", 3..4 + end + assert_nothing_raised { assert_select "div", :count=>2 } + assert_failure(/Expected at least 3 elements matching \"div\", found 2/) do + assert_select "div", :count=>3 + end + assert_nothing_raised { assert_select "div", :minimum=>1 } + assert_nothing_raised { assert_select "div", :minimum=>2 } + assert_failure(/Expected at least 3 elements matching \"div\", found 2/) do + assert_select "div", :minimum=>3 + end + assert_nothing_raised { assert_select "div", :maximum=>2 } + assert_nothing_raised { assert_select "div", :maximum=>3 } + assert_failure(/Expected at most 1 element matching \"div\", found 2/) do + assert_select "div", :maximum=>1 + end + assert_nothing_raised { assert_select "div", :minimum=>1, :maximum=>2 } + assert_failure(/Expected between 3 and 4 elements matching \"div\", found 2/) do + assert_select "div", :minimum=>3, :maximum=>4 + end + end + + + def test_substitution_values + render_html %Q{<div id="1">foo</div><div id="2">foo</div>} + assert_select "div#?", /\d+/ do |elements| + assert_equal 2, elements.size + end + assert_select "div" do + assert_select "div#?", /\d+/ do |elements| + assert_equal 2, elements.size + assert_select "#1" + assert_select "#2" + end + end + end + + + def test_nested_assert_select + render_html %Q{<div id="1">foo</div><div id="2">foo</div>} + assert_select "div" do |elements| + assert_equal 2, elements.size + assert_select elements[0], "#1" + assert_select elements[1], "#2" + end + assert_select "div" do + assert_select "div" do |elements| + assert_equal 2, elements.size + # Testing in a group is one thing + assert_select "#1,#2" + # Testing individually is another. + assert_select "#1" + assert_select "#2" + assert_select "#3", false + end + end + + assert_failure(/Expected at least 1 element matching \"#4\", found 0\./) do + assert_select "div" do + assert_select "#4" + end + end + end + + + def test_assert_select_text_match + render_html %Q{<div id="1"><span>foo</span></div><div id="2"><span>bar</span></div>} + assert_select "div" do + assert_nothing_raised { assert_select "div", "foo" } + assert_nothing_raised { assert_select "div", "bar" } + assert_nothing_raised { assert_select "div", /\w*/ } + assert_nothing_raised { assert_select "div", /\w*/, :count=>2 } + assert_raises(AssertionFailedError) { assert_select "div", :text=>"foo", :count=>2 } + assert_nothing_raised { assert_select "div", :html=>"<span>bar</span>" } + assert_nothing_raised { assert_select "div", :html=>"<span>bar</span>" } + assert_nothing_raised { assert_select "div", :html=>/\w*/ } + assert_nothing_raised { assert_select "div", :html=>/\w*/, :count=>2 } + assert_raises(AssertionFailedError) { assert_select "div", :html=>"<span>foo</span>", :count=>2 } + end + end + + + # With single result. + def test_assert_select_from_rjs_with_single_result + render_rjs do |page| + page.replace_html "test", "<div id=\"1\">foo</div>\n<div id=\"2\">foo</div>" + end + assert_select "div" do |elements| + assert elements.size == 2 + assert_select "#1" + assert_select "#2" + end + assert_select "div#?", /\d+/ do |elements| + assert_select "#1" + assert_select "#2" + end + end + + # With multiple results. + def test_assert_select_from_rjs_with_multiple_results + render_rjs do |page| + page.replace_html "test", "<div id=\"1\">foo</div>" + page.replace_html "test2", "<div id=\"2\">foo</div>" + end + assert_select "div" do |elements| + assert elements.size == 2 + assert_select "#1" + assert_select "#2" + end + end + + + # + # Test css_select. + # + + + def test_css_select + render_html %Q{<div id="1"></div><div id="2"></div>} + assert 2, css_select("div").size + assert 0, css_select("p").size + end + + + def test_nested_css_select + render_html %Q{<div id="1">foo</div><div id="2">foo</div>} + assert_select "div#?", /\d+/ do |elements| + assert_equal 1, css_select(elements[0], "div").size + assert_equal 1, css_select(elements[1], "div").size + end + assert_select "div" do + assert_equal 2, css_select("div").size + css_select("div").each do |element| + # Testing as a group is one thing + assert !css_select("#1,#2").empty? + # Testing individually is another + assert !css_select("#1").empty? + assert !css_select("#2").empty? + end + end + end + + + # With one result. + def test_css_select_from_rjs_with_single_result + render_rjs do |page| + page.replace_html "test", "<div id=\"1\">foo</div>\n<div id=\"2\">foo</div>" + end + assert_equal 2, css_select("div").size + assert_equal 1, css_select("#1").size + assert_equal 1, css_select("#2").size + end + + # With multiple results. + def test_css_select_from_rjs_with_multiple_results + render_rjs do |page| + page.replace_html "test", "<div id=\"1\">foo</div>" + page.replace_html "test2", "<div id=\"2\">foo</div>" + end + + assert_equal 2, css_select("div").size + assert_equal 1, css_select("#1").size + assert_equal 1, css_select("#2").size + end + + + # + # Test assert_select_rjs. + # + + + # Test that we can pick up all statements in the result. + def test_assert_select_rjs_picks_up_all_statements + render_rjs do |page| + page.replace "test", "<div id=\"1\">foo</div>" + page.replace_html "test2", "<div id=\"2\">foo</div>" + page.insert_html :top, "test3", "<div id=\"3\">foo</div>" + end + + found = false + assert_select_rjs do + assert_select "#1" + assert_select "#2" + assert_select "#3" + found = true + end + assert found + end + + # Test that we fail if there is nothing to pick. + def test_assert_select_rjs_fails_if_nothing_to_pick + render_rjs { } + assert_raises(AssertionFailedError) { assert_select_rjs } + end + + def test_assert_select_rjs_with_unicode + # Test that non-ascii characters (which are converted into \uXXXX in RJS) are decoded correctly. + render_rjs do |page| + page.replace "test", "<div id=\"1\">\343\203\201\343\202\261\343\203\203\343\203\210</div>" + end + assert_select_rjs do + assert_select "#1", :text => "\343\203\201\343\202\261\343\203\203\343\203\210" + assert_select "#1", "\343\203\201\343\202\261\343\203\203\343\203\210" + assert_select "#1", Regexp.new("\343\203\201..\343\203\210",0,'U') + assert_raises(AssertionFailedError) { assert_select "#1", Regexp.new("\343\203\201.\343\203\210",0,'U') } + end + end + + def test_assert_select_rjs_with_id + # Test that we can pick up all statements in the result. + render_rjs do |page| + page.replace "test1", "<div id=\"1\">foo</div>" + page.replace_html "test2", "<div id=\"2\">foo</div>" + page.insert_html :top, "test3", "<div id=\"3\">foo</div>" + end + assert_select_rjs "test1" do + assert_select "div", 1 + assert_select "#1" + end + assert_select_rjs "test2" do + assert_select "div", 1 + assert_select "#2" + end + assert_select_rjs "test3" do + assert_select "div", 1 + assert_select "#3" + end + assert_raises(AssertionFailedError) { assert_select_rjs "test4" } + end + + + def test_assert_select_rjs_for_replace + render_rjs do |page| + page.replace "test1", "<div id=\"1\">foo</div>" + page.replace_html "test2", "<div id=\"2\">foo</div>" + page.insert_html :top, "test3", "<div id=\"3\">foo</div>" + end + # Replace. + assert_select_rjs :replace do + assert_select "div", 1 + assert_select "#1" + end + assert_select_rjs :replace, "test1" do + assert_select "div", 1 + assert_select "#1" + end + assert_raises(AssertionFailedError) { assert_select_rjs :replace, "test2" } + # Replace HTML. + assert_select_rjs :replace_html do + assert_select "div", 1 + assert_select "#2" + end + assert_select_rjs :replace_html, "test2" do + assert_select "div", 1 + assert_select "#2" + end + assert_raises(AssertionFailedError) { assert_select_rjs :replace_html, "test1" } + end + + def test_assert_select_rjs_for_chained_replace + render_rjs do |page| + page['test1'].replace "<div id=\"1\">foo</div>" + page['test2'].replace_html "<div id=\"2\">foo</div>" + page.insert_html :top, "test3", "<div id=\"3\">foo</div>" + end + # Replace. + assert_select_rjs :chained_replace do + assert_select "div", 1 + assert_select "#1" + end + assert_select_rjs :chained_replace, "test1" do + assert_select "div", 1 + assert_select "#1" + end + assert_raises(AssertionFailedError) { assert_select_rjs :chained_replace, "test2" } + # Replace HTML. + assert_select_rjs :chained_replace_html do + assert_select "div", 1 + assert_select "#2" + end + assert_select_rjs :chained_replace_html, "test2" do + assert_select "div", 1 + assert_select "#2" + end + assert_raises(AssertionFailedError) { assert_select_rjs :replace_html, "test1" } + end + + # Simple remove + def test_assert_select_rjs_for_remove + render_rjs do |page| + page.remove "test1" + end + + assert_select_rjs :remove, "test1" + end + + def test_assert_select_rjs_for_remove_ignores_block + render_rjs do |page| + page.remove "test1" + end + + assert_nothing_raised do + assert_select_rjs :remove, "test1" do + assert_select "p" + end + end + end + + # Simple show + def test_assert_select_rjs_for_show + render_rjs do |page| + page.show "test1" + end + + assert_select_rjs :show, "test1" + end + + def test_assert_select_rjs_for_show_ignores_block + render_rjs do |page| + page.show "test1" + end + + assert_nothing_raised do + assert_select_rjs :show, "test1" do + assert_select "p" + end + end + end + + # Simple hide + def test_assert_select_rjs_for_hide + render_rjs do |page| + page.hide "test1" + end + + assert_select_rjs :hide, "test1" + end + + def test_assert_select_rjs_for_hide_ignores_block + render_rjs do |page| + page.hide "test1" + end + + assert_nothing_raised do + assert_select_rjs :hide, "test1" do + assert_select "p" + end + end + end + + # Simple toggle + def test_assert_select_rjs_for_toggle + render_rjs do |page| + page.toggle "test1" + end + + assert_select_rjs :toggle, "test1" + end + + def test_assert_select_rjs_for_toggle_ignores_block + render_rjs do |page| + page.toggle "test1" + end + + assert_nothing_raised do + assert_select_rjs :toggle, "test1" do + assert_select "p" + end + end + end + + # Non-positioned insert. + def test_assert_select_rjs_for_nonpositioned_insert + render_rjs do |page| + page.replace "test1", "<div id=\"1\">foo</div>" + page.replace_html "test2", "<div id=\"2\">foo</div>" + page.insert_html :top, "test3", "<div id=\"3\">foo</div>" + end + assert_select_rjs :insert_html do + assert_select "div", 1 + assert_select "#3" + end + assert_select_rjs :insert_html, "test3" do + assert_select "div", 1 + assert_select "#3" + end + assert_raises(AssertionFailedError) { assert_select_rjs :insert_html, "test1" } + end + + # Positioned insert. + def test_assert_select_rjs_for_positioned_insert + render_rjs do |page| + page.insert_html :top, "test1", "<div id=\"1\">foo</div>" + page.insert_html :bottom, "test2", "<div id=\"2\">foo</div>" + page.insert_html :before, "test3", "<div id=\"3\">foo</div>" + page.insert_html :after, "test4", "<div id=\"4\">foo</div>" + end + assert_select_rjs :insert, :top do + assert_select "div", 1 + assert_select "#1" + end + assert_select_rjs :insert, :bottom do + assert_select "div", 1 + assert_select "#2" + end + assert_select_rjs :insert, :before do + assert_select "div", 1 + assert_select "#3" + end + assert_select_rjs :insert, :after do + assert_select "div", 1 + assert_select "#4" + end + assert_select_rjs :insert_html do + assert_select "div", 4 + end + end + + # Simple selection from a single result. + def test_nested_assert_select_rjs_with_single_result + render_rjs do |page| + page.replace_html "test", "<div id=\"1\">foo</div>\n<div id=\"2\">foo</div>" + end + + assert_select_rjs "test" do |elements| + assert_equal 2, elements.size + assert_select "#1" + assert_select "#2" + end + end + + # Deal with two results. + def test_nested_assert_select_rjs_with_two_results + render_rjs do |page| + page.replace_html "test", "<div id=\"1\">foo</div>" + page.replace_html "test2", "<div id=\"2\">foo</div>" + end + + assert_select_rjs "test" do |elements| + assert_equal 1, elements.size + assert_select "#1" + end + + assert_select_rjs "test2" do |elements| + assert_equal 1, elements.size + assert_select "#2" + end + end + + + def test_feed_item_encoded + render_xml <<-EOF +<rss version="2.0"> + <channel> + <item> + <description> + <![CDATA[ + <p>Test 1</p> + ]]> + </description> + </item> + <item> + <description> + <![CDATA[ + <p>Test 2</p> + ]]> + </description> + </item> + </channel> +</rss> +EOF + assert_select "channel item description" do + # Test element regardless of wrapper. + assert_select_encoded do + assert_select "p", :count=>2, :text=>/Test/ + end + # Test through encoded wrapper. + assert_select_encoded do + assert_select "encoded p", :count=>2, :text=>/Test/ + end + # Use :root instead (recommended) + assert_select_encoded do + assert_select ":root p", :count=>2, :text=>/Test/ + end + # Test individually. + assert_select "description" do |elements| + assert_select_encoded elements[0] do + assert_select "p", "Test 1" + end + assert_select_encoded elements[1] do + assert_select "p", "Test 2" + end + end + end + + # Test that we only un-encode element itself. + assert_select "channel item" do + assert_select_encoded do + assert_select "p", 0 + end + end + end + + + # + # Test assert_select_email + # + + def test_assert_select_email + assert_raises(AssertionFailedError) { assert_select_email {} } + AssertSelectMailer.deliver_test "<div><p>foo</p><p>bar</p></div>" + assert_select_email do + assert_select "div:root" do + assert_select "p:first-child", "foo" + assert_select "p:last-child", "bar" + end + end + end + + + protected + def render_html(html) + @controller.response_with = html + get :html + end + + def render_rjs(&block) + @controller.response_with &block + get :rjs + end + + def render_xml(xml) + @controller.response_with = xml + get :xml + end +end diff --git a/vendor/rails-2.0.2/actionpack/test/controller/base_test.rb b/vendor/rails-2.0.2/actionpack/test/controller/base_test.rb new file mode 100644 index 000000000..60e61b628 --- /dev/null +++ b/vendor/rails-2.0.2/actionpack/test/controller/base_test.rb @@ -0,0 +1,134 @@ +require File.dirname(__FILE__) + '/../abstract_unit' +require 'test/unit' +require 'pp' # require 'pp' early to prevent hidden_methods from not picking up the pretty-print methods until too late + +# Provide some controller to run the tests on. +module Submodule + class ContainedEmptyController < ActionController::Base + end + class ContainedNonEmptyController < ActionController::Base + def public_action + end + + hide_action :hidden_action + def hidden_action + raise "Noooo!" + end + + def another_hidden_action + end + hide_action :another_hidden_action + end + class SubclassedController < ContainedNonEmptyController + hide_action :public_action # Hiding it here should not affect the superclass. + end +end +class EmptyController < ActionController::Base +end +class NonEmptyController < ActionController::Base + def public_action + end + + hide_action :hidden_action + def hidden_action + end +end + +class MethodMissingController < ActionController::Base + + hide_action :shouldnt_be_called + def shouldnt_be_called + raise "NO WAY!" + end + +protected + + def method_missing(selector) + render :text => selector.to_s + end + +end + +class ControllerClassTests < Test::Unit::TestCase + def test_controller_path + assert_equal 'empty', EmptyController.controller_path + assert_equal EmptyController.controller_path, EmptyController.new.controller_path + assert_equal 'submodule/contained_empty', Submodule::ContainedEmptyController.controller_path + assert_equal Submodule::ContainedEmptyController.controller_path, Submodule::ContainedEmptyController.new.controller_path + end + def test_controller_name + assert_equal 'empty', EmptyController.controller_name + assert_equal 'contained_empty', Submodule::ContainedEmptyController.controller_name + end +end + +class ControllerInstanceTests < Test::Unit::TestCase + def setup + @empty = EmptyController.new + @contained = Submodule::ContainedEmptyController.new + @empty_controllers = [@empty, @contained, Submodule::SubclassedController.new] + + @non_empty_controllers = [NonEmptyController.new, + Submodule::ContainedNonEmptyController.new] + end + + def test_action_methods + @empty_controllers.each do |c| + hide_mocha_methods_from_controller(c) + assert_equal Set.new, c.send!(:action_methods), "#{c.controller_path} should be empty!" + end + @non_empty_controllers.each do |c| + hide_mocha_methods_from_controller(c) + assert_equal Set.new(%w(public_action)), c.send!(:action_methods), "#{c.controller_path} should not be empty!" + end + end + + protected + # Mocha adds some public instance methods to Object that would be + # considered actions, so explicitly hide_action them. + def hide_mocha_methods_from_controller(controller) + mocha_methods = [:expects, :metaclass, :mocha, :mocha_inspect, :reset_mocha, :stubba_object, :stubba_method, :stubs, :verify, :__metaclass__, :__is_a__] + controller.class.send!(:hide_action, *mocha_methods) + end +end + + +class PerformActionTest < Test::Unit::TestCase + def use_controller(controller_class) + @controller = controller_class.new + + # enable a logger so that (e.g.) the benchmarking stuff runs, so we can get + # a more accurate simulation of what happens in "real life". + @controller.logger = Logger.new(nil) + + @request = ActionController::TestRequest.new + @response = ActionController::TestResponse.new + + @request.host = "www.nextangle.com" + end + + def test_get_on_priv_should_show_selector + use_controller MethodMissingController + get :shouldnt_be_called + assert_response :success + assert_equal 'shouldnt_be_called', @response.body + end + + def test_method_missing_is_not_an_action_name + use_controller MethodMissingController + assert ! @controller.send!(:action_methods).include?('method_missing') + + get :method_missing + assert_response :success + assert_equal 'method_missing', @response.body + end + + def test_get_on_hidden_should_fail + use_controller NonEmptyController + get :hidden_action + assert_response 404 + + get :another_hidden_action + assert_response 404 + end +end diff --git a/vendor/rails-2.0.2/actionpack/test/controller/benchmark_test.rb b/vendor/rails-2.0.2/actionpack/test/controller/benchmark_test.rb new file mode 100644 index 000000000..f346e575e --- /dev/null +++ b/vendor/rails-2.0.2/actionpack/test/controller/benchmark_test.rb @@ -0,0 +1,33 @@ +require File.dirname(__FILE__) + '/../abstract_unit' +require 'test/unit' + +# Provide some static controllers. +class BenchmarkedController < ActionController::Base + def public_action + render :nothing => true + end + + def rescue_action(e) + raise e + end +end + +class BenchmarkTest < Test::Unit::TestCase + class MockLogger + def method_missing(*args) + end + end + + def setup + @controller = BenchmarkedController.new + # benchmark doesn't do anything unless a logger is set + @controller.logger = MockLogger.new + @request, @response = ActionController::TestRequest.new, ActionController::TestResponse.new + @request.host = "test.actioncontroller.i" + end + + def test_with_http_1_0_request + @request.host = nil + assert_nothing_raised { get :public_action } + end +end diff --git a/vendor/rails-2.0.2/actionpack/test/controller/caching_test.rb b/vendor/rails-2.0.2/actionpack/test/controller/caching_test.rb new file mode 100644 index 000000000..d6982fbc8 --- /dev/null +++ b/vendor/rails-2.0.2/actionpack/test/controller/caching_test.rb @@ -0,0 +1,349 @@ +require 'fileutils' +require File.dirname(__FILE__) + '/../abstract_unit' + +CACHE_DIR = 'test_cache' +# Don't change '/../temp/' cavalierly or you might hose something you don't want hosed +FILE_STORE_PATH = File.join(File.dirname(__FILE__), '/../temp/', CACHE_DIR) +ActionController::Base.page_cache_directory = FILE_STORE_PATH +ActionController::Base.fragment_cache_store = :file_store, FILE_STORE_PATH + +class PageCachingTestController < ActionController::Base + caches_page :ok, :no_content, :found, :not_found + + def ok + head :ok + end + + def no_content + head :no_content + end + + def found + redirect_to :action => 'ok' + end + + def not_found + head :not_found + end + + def custom_path + render :text => "Super soaker" + cache_page("Super soaker", "/index.html") + end + + def expire_custom_path + expire_page("/index.html") + head :ok + end + + def trailing_slash + render :text => "Sneak attack" + end +end + +class PageCachingTest < Test::Unit::TestCase + def setup + ActionController::Base.perform_caching = true + + ActionController::Routing::Routes.draw do |map| + map.main '', :controller => 'posts' + map.resources :posts + map.connect ':controller/:action/:id' + end + + @request = ActionController::TestRequest.new + @request.host = 'hostname.com' + + @response = ActionController::TestResponse.new + @controller = PageCachingTestController.new + + @params = {:controller => 'posts', :action => 'index', :only_path => true, :skip_relative_url_root => true} + @rewriter = ActionController::UrlRewriter.new(@request, @params) + + FileUtils.rm_rf(File.dirname(FILE_STORE_PATH)) + FileUtils.mkdir_p(FILE_STORE_PATH) + end + + def teardown + FileUtils.rm_rf(File.dirname(FILE_STORE_PATH)) + + ActionController::Base.perform_caching = false + end + + def test_page_caching_resources_saves_to_correct_path_with_extension_even_if_default_route + @params[:format] = 'rss' + assert_equal '/posts.rss', @rewriter.rewrite(@params) + @params[:format] = nil + assert_equal '/', @rewriter.rewrite(@params) + end + + def test_should_cache_get_with_ok_status + get :ok + assert_response :ok + assert_page_cached :ok, "get with ok status should have been cached" + end + + def test_should_cache_with_custom_path + get :custom_path + assert File.exist?("#{FILE_STORE_PATH}/index.html") + end + + def test_should_expire_cache_with_custom_path + get :custom_path + assert File.exist?("#{FILE_STORE_PATH}/index.html") + + get :expire_custom_path + assert !File.exist?("#{FILE_STORE_PATH}/index.html") + end + + def test_should_cache_without_trailing_slash_on_url + @controller.class.cache_page 'cached content', '/page_caching_test/trailing_slash' + assert File.exist?("#{FILE_STORE_PATH}/page_caching_test/trailing_slash.html") + end + + def test_should_cache_with_trailing_slash_on_url + @controller.class.cache_page 'cached content', '/page_caching_test/trailing_slash/' + assert File.exist?("#{FILE_STORE_PATH}/page_caching_test/trailing_slash.html") + end + + uses_mocha("should_cache_ok_at_custom_path") do + def test_should_cache_ok_at_custom_path + @request.expects(:path).returns("/index.html") + get :ok + assert_response :ok + assert File.exist?("#{FILE_STORE_PATH}/index.html") + end + end + + [:ok, :no_content, :found, :not_found].each do |status| + [:get, :post, :put, :delete].each do |method| + unless method == :get and status == :ok + define_method "test_shouldnt_cache_#{method}_with_#{status}_status" do + @request.env['REQUEST_METHOD'] = method.to_s.upcase + process status + assert_response status + assert_page_not_cached status, "#{method} with #{status} status shouldn't have been cached" + end + end + end + end + + private + def assert_page_cached(action, message = "#{action} should have been cached") + assert page_cached?(action), message + end + + def assert_page_not_cached(action, message = "#{action} shouldn't have been cached") + assert !page_cached?(action), message + end + + def page_cached?(action) + File.exist? "#{FILE_STORE_PATH}/page_caching_test/#{action}.html" + end +end + + +class ActionCachingTestController < ActionController::Base + caches_action :index, :redirected, :forbidden + caches_action :show, :cache_path => 'http://test.host/custom/show' + caches_action :edit, :cache_path => Proc.new { |c| c.params[:id] ? "http://test.host/#{c.params[:id]};edit" : "http://test.host/edit" } + + def index + @cache_this = Time.now.to_f.to_s + render :text => @cache_this + end + + def redirected + redirect_to :action => 'index' + end + + def forbidden + render :text => "Forbidden" + headers["Status"] = "403 Forbidden" + end + + alias_method :show, :index + alias_method :edit, :index + + def expire + expire_action :controller => 'action_caching_test', :action => 'index' + render :nothing => true + end + +end + +class ActionCachingMockController + attr_accessor :mock_url_for + attr_accessor :mock_path + + def initialize + yield self if block_given? + end + + def url_for(*args) + @mock_url_for + end + + def request + mocked_path = @mock_path + Object.new.instance_eval(<<-EVAL) + def path; '#{@mock_path}' end + self + EVAL + end +end + +class ActionCacheTest < Test::Unit::TestCase + def setup + reset! + FileUtils.mkdir_p(FILE_STORE_PATH) + @path_class = ActionController::Caching::Actions::ActionCachePath + @mock_controller = ActionCachingMockController.new + end + + def teardown + FileUtils.rm_rf(File.dirname(FILE_STORE_PATH)) + end + + def test_simple_action_cache + get :index + cached_time = content_to_cache + assert_equal cached_time, @response.body + assert_cache_exists 'hostname.com/action_caching_test' + reset! + + get :index + assert_equal cached_time, @response.body + end + + def test_action_cache_with_custom_cache_path + get :show + cached_time = content_to_cache + assert_equal cached_time, @response.body + assert_cache_exists 'test.host/custom/show' + reset! + + get :show + assert_equal cached_time, @response.body + end + + def test_action_cache_with_custom_cache_path_in_block + get :edit + assert_cache_exists 'test.host/edit' + reset! + + get :edit, :id => 1 + assert_cache_exists 'test.host/1;edit' + end + + def test_cache_expiration + get :index + cached_time = content_to_cache + reset! + + get :index + assert_equal cached_time, @response.body + reset! + + get :expire + reset! + + get :index + new_cached_time = content_to_cache + assert_not_equal cached_time, @response.body + reset! + + get :index + assert_response :success + assert_equal new_cached_time, @response.body + end + + def test_cache_is_scoped_by_subdomain + @request.host = 'jamis.hostname.com' + get :index + jamis_cache = content_to_cache + + reset! + + @request.host = 'david.hostname.com' + get :index + david_cache = content_to_cache + assert_not_equal jamis_cache, @response.body + + reset! + + @request.host = 'jamis.hostname.com' + get :index + assert_equal jamis_cache, @response.body + + reset! + + @request.host = 'david.hostname.com' + get :index + assert_equal david_cache, @response.body + end + + def test_redirect_is_not_cached + get :redirected + assert_response :redirect + reset! + + get :redirected + assert_response :redirect + end + + def test_forbidden_is_not_cached + get :forbidden + assert_response :forbidden + reset! + + get :forbidden + assert_response :forbidden + end + + def test_xml_version_of_resource_is_treated_as_different_cache + @mock_controller.mock_url_for = 'http://example.org/posts/' + @mock_controller.mock_path = '/posts/index.xml' + path_object = @path_class.new(@mock_controller, {}) + assert_equal 'xml', path_object.extension + assert_equal 'example.org/posts/index.xml', path_object.path + end + + def test_correct_content_type_is_returned_for_cache_hit + # run it twice to cache it the first time + get :index, :id => 'content-type.xml' + get :index, :id => 'content-type.xml' + assert_equal 'application/xml', @response.content_type + end + + def test_empty_path_is_normalized + @mock_controller.mock_url_for = 'http://example.org/' + @mock_controller.mock_path = '/' + + assert_equal 'example.org/index', @path_class.path_for(@mock_controller, {}) + end + + def test_file_extensions + get :index, :id => 'kitten.jpg' + get :index, :id => 'kitten.jpg' + + assert_response :success + end + + private + def content_to_cache + assigns(:cache_this) + end + + def reset! + @request = ActionController::TestRequest.new + @response = ActionController::TestResponse.new + @controller = ActionCachingTestController.new + @request.host = 'hostname.com' + end + + def assert_cache_exists(path) + full_path = File.join(FILE_STORE_PATH, path + '.cache') + assert File.exist?(full_path), "#{full_path.inspect} does not exist." + end +end diff --git a/vendor/rails-2.0.2/actionpack/test/controller/capture_test.rb b/vendor/rails-2.0.2/actionpack/test/controller/capture_test.rb new file mode 100644 index 000000000..7ec5f32a3 --- /dev/null +++ b/vendor/rails-2.0.2/actionpack/test/controller/capture_test.rb @@ -0,0 +1,89 @@ +require File.dirname(__FILE__) + '/../abstract_unit' + +class CaptureController < ActionController::Base + def self.controller_name; "test"; end + def self.controller_path; "test"; end + + def content_for + render :layout => "talk_from_action" + end + + def content_for_with_parameter + render :layout => "talk_from_action" + end + + def content_for_concatenated + render :layout => "talk_from_action" + end + + def erb_content_for + render :layout => "talk_from_action" + end + + def block_content_for + render :layout => "talk_from_action" + end + + def non_erb_block_content_for + render :layout => "talk_from_action" + end + + def rescue_action(e) raise end +end + +CaptureController.view_paths = [ File.dirname(__FILE__) + "/../fixtures/" ] + +class CaptureTest < Test::Unit::TestCase + def setup + @controller = CaptureController.new + + # enable a logger so that (e.g.) the benchmarking stuff runs, so we can get + # a more accurate simulation of what happens in "real life". + @controller.logger = Logger.new(nil) + + @request = ActionController::TestRequest.new + @response = ActionController::TestResponse.new + + @request.host = "www.nextangle.com" + end + + def test_simple_capture + get :capturing + assert_equal "Dreamy days", @response.body.strip + end + + def test_content_for + get :content_for + assert_equal expected_content_for_output, @response.body + end + + def test_should_concatentate_content_for + get :content_for_concatenated + assert_equal expected_content_for_output, @response.body + end + + def test_erb_content_for + get :erb_content_for + assert_equal expected_content_for_output, @response.body + end + + def test_should_set_content_for_with_parameter + get :content_for_with_parameter + assert_equal expected_content_for_output, @response.body + end + + def test_block_content_for + get :block_content_for + assert_equal expected_content_for_output, @response.body + end + + def test_non_erb_block_content_for + get :non_erb_block_content_for + assert_equal expected_content_for_output, @response.body + end + + private + def expected_content_for_output + "<title>Putting stuff in the title!</title>\n\nGreat stuff!" + end +end diff --git a/vendor/rails-2.0.2/actionpack/test/controller/cgi_test.rb b/vendor/rails-2.0.2/actionpack/test/controller/cgi_test.rb new file mode 100755 index 000000000..021781df9 --- /dev/null +++ b/vendor/rails-2.0.2/actionpack/test/controller/cgi_test.rb @@ -0,0 +1,115 @@ +require File.dirname(__FILE__) + '/../abstract_unit' +require 'action_controller/cgi_process' + +class BaseCgiTest < Test::Unit::TestCase + def setup + @request_hash = {"HTTP_MAX_FORWARDS"=>"10", "SERVER_NAME"=>"glu.ttono.us:8007", "FCGI_ROLE"=>"RESPONDER", "HTTP_X_FORWARDED_HOST"=>"glu.ttono.us", "HTTP_ACCEPT_ENCODING"=>"gzip, deflate", "HTTP_USER_AGENT"=>"Mozilla/5.0 (Macintosh; U; PPC Mac OS X; en) AppleWebKit/312.5.1 (KHTML, like Gecko) Safari/312.3.1", "PATH_INFO"=>"", "HTTP_ACCEPT_LANGUAGE"=>"en", "HTTP_HOST"=>"glu.ttono.us:8007", "SERVER_PROTOCOL"=>"HTTP/1.1", "REDIRECT_URI"=>"/dispatch.fcgi", "SCRIPT_NAME"=>"/dispatch.fcgi", "SERVER_ADDR"=>"207.7.108.53", "REMOTE_ADDR"=>"207.7.108.53", "SERVER_SOFTWARE"=>"lighttpd/1.4.5", "HTTP_COOKIE"=>"_session_id=c84ace84796670c052c6ceb2451fb0f2; is_admin=yes", "HTTP_X_FORWARDED_SERVER"=>"glu.ttono.us", "REQUEST_URI"=>"/admin", "DOCUMENT_ROOT"=>"/home/kevinc/sites/typo/public", "SERVER_PORT"=>"8007", "QUERY_STRING"=>"", "REMOTE_PORT"=>"63137", "GATEWAY_INTERFACE"=>"CGI/1.1", "HTTP_X_FORWARDED_FOR"=>"65.88.180.234", "HTTP_ACCEPT"=>"*/*", "SCRIPT_FILENAME"=>"/home/kevinc/sites/typo/public/dispatch.fcgi", "REDIRECT_STATUS"=>"200", "REQUEST_METHOD"=>"GET"} + # cookie as returned by some Nokia phone browsers (no space after semicolon separator) + @alt_cookie_fmt_request_hash = {"HTTP_COOKIE"=>"_session_id=c84ace84796670c052c6ceb2451fb0f2;is_admin=yes"} + @fake_cgi = Struct.new(:env_table).new(@request_hash) + @request = ActionController::CgiRequest.new(@fake_cgi) + end + + def default_test; end +end + + +class CgiRequestTest < BaseCgiTest + def test_proxy_request + assert_equal 'glu.ttono.us', @request.host_with_port + end + + def test_http_host + @request_hash.delete "HTTP_X_FORWARDED_HOST" + @request_hash['HTTP_HOST'] = "rubyonrails.org:8080" + assert_equal "rubyonrails.org:8080", @request.host_with_port + + @request_hash['HTTP_X_FORWARDED_HOST'] = "www.firsthost.org, www.secondhost.org" + assert_equal "www.secondhost.org", @request.host + end + + def test_http_host_with_default_port_overrides_server_port + @request_hash.delete "HTTP_X_FORWARDED_HOST" + @request_hash['HTTP_HOST'] = "rubyonrails.org" + assert_equal "rubyonrails.org", @request.host_with_port + end + + def test_host_with_port_defaults_to_server_name_if_no_host_headers + @request_hash.delete "HTTP_X_FORWARDED_HOST" + @request_hash.delete "HTTP_HOST" + assert_equal "glu.ttono.us:8007", @request.host_with_port + end + + def test_host_with_port_falls_back_to_server_addr_if_necessary + @request_hash.delete "HTTP_X_FORWARDED_HOST" + @request_hash.delete "HTTP_HOST" + @request_hash.delete "SERVER_NAME" + assert_equal "207.7.108.53:8007", @request.host_with_port + end + + def test_host_with_port_if_http_standard_port_is_specified + @request_hash['HTTP_X_FORWARDED_HOST'] = "glu.ttono.us:80" + assert_equal "glu.ttono.us", @request.host_with_port + end + + def test_host_with_port_if_https_standard_port_is_specified + @request_hash['HTTP_X_FORWARDED_PROTO'] = "https" + @request_hash['HTTP_X_FORWARDED_HOST'] = "glu.ttono.us:443" + assert_equal "glu.ttono.us", @request.host_with_port + end + + def test_host_if_ipv6_reference + @request_hash.delete "HTTP_X_FORWARDED_HOST" + @request_hash['HTTP_HOST'] = "[2001:1234:5678:9abc:def0::dead:beef]" + assert_equal "[2001:1234:5678:9abc:def0::dead:beef]", @request.host + end + + def test_host_if_ipv6_reference_with_port + @request_hash.delete "HTTP_X_FORWARDED_HOST" + @request_hash['HTTP_HOST'] = "[2001:1234:5678:9abc:def0::dead:beef]:8008" + assert_equal "[2001:1234:5678:9abc:def0::dead:beef]", @request.host + end + + def test_cookie_syntax_resilience + cookies = CGI::Cookie::parse(@request_hash["HTTP_COOKIE"]); + assert_equal ["c84ace84796670c052c6ceb2451fb0f2"], cookies["_session_id"], cookies.inspect + assert_equal ["yes"], cookies["is_admin"], cookies.inspect + + alt_cookies = CGI::Cookie::parse(@alt_cookie_fmt_request_hash["HTTP_COOKIE"]); + assert_equal ["c84ace84796670c052c6ceb2451fb0f2"], alt_cookies["_session_id"], alt_cookies.inspect + assert_equal ["yes"], alt_cookies["is_admin"], alt_cookies.inspect + end +end + + +class CgiRequestParamsParsingTest < BaseCgiTest + def test_doesnt_break_when_content_type_has_charset + data = 'flamenco=love' + @request.env['CONTENT_LENGTH'] = data.length + @request.env['CONTENT_TYPE'] = 'application/x-www-form-urlencoded; charset=utf-8' + @request.env['RAW_POST_DATA'] = data + assert_equal({"flamenco"=> "love"}, @request.request_parameters) + end + + def test_doesnt_interpret_request_uri_as_query_string_when_missing + @request.env['REQUEST_URI'] = 'foo' + assert_equal({}, @request.query_parameters) + end +end + + +class CgiRequestNeedsRewoundTest < BaseCgiTest + def test_body_should_be_rewound + data = 'foo' + fake_cgi = Struct.new(:env_table, :query_string, :stdinput).new(@request_hash, '', StringIO.new(data)) + fake_cgi.env_table['CONTENT_LENGTH'] = data.length + fake_cgi.env_table['CONTENT_TYPE'] = 'application/x-www-form-urlencoded; charset=utf-8' + + # Read the request body by parsing params. + request = ActionController::CgiRequest.new(fake_cgi) + request.request_parameters + + # Should have rewound the body. + assert_equal 0, request.body.pos + end +end diff --git a/vendor/rails-2.0.2/actionpack/test/controller/components_test.rb b/vendor/rails-2.0.2/actionpack/test/controller/components_test.rb new file mode 100644 index 000000000..debd8a274 --- /dev/null +++ b/vendor/rails-2.0.2/actionpack/test/controller/components_test.rb @@ -0,0 +1,140 @@ +require File.dirname(__FILE__) + '/../abstract_unit' + +class CallerController < ActionController::Base + def calling_from_controller + render_component(:controller => "callee", :action => "being_called") + end + + def calling_from_controller_with_params + render_component(:controller => "callee", :action => "being_called", :params => { "name" => "David" }) + end + + def calling_from_controller_with_different_status_code + render_component(:controller => "callee", :action => "blowing_up") + end + + def calling_from_template + render :inline => "Ring, ring: <%= render_component(:controller => 'callee', :action => 'being_called') %>" + end + + def internal_caller + render :inline => "Are you there? <%= render_component(:action => 'internal_callee') %>" + end + + def internal_callee + render :text => "Yes, ma'am" + end + + def set_flash + render_component(:controller => "callee", :action => "set_flash") + end + + def use_flash + render_component(:controller => "callee", :action => "use_flash") + end + + def calling_redirected + render_component(:controller => "callee", :action => "redirected") + end + + def calling_redirected_as_string + render :inline => "<%= render_component(:controller => 'callee', :action => 'redirected') %>" + end + + def rescue_action(e) raise end +end + +class CalleeController < ActionController::Base + def being_called + render :text => "#{params[:name] || "Lady"} of the House, speaking" + end + + def blowing_up + render :text => "It's game over, man, just game over, man!", :status => 500 + end + + def set_flash + flash[:notice] = 'My stoney baby' + render :text => 'flash is set' + end + + def use_flash + render :text => flash[:notice] || 'no flash' + end + + def redirected + redirect_to :controller => "callee", :action => "being_called" + end + + def rescue_action(e) raise end +end + +class ComponentsTest < Test::Unit::TestCase + def setup + @controller = CallerController.new + @request = ActionController::TestRequest.new + @response = ActionController::TestResponse.new + end + + def test_calling_from_controller + get :calling_from_controller + assert_equal "Lady of the House, speaking", @response.body + end + + def test_calling_from_controller_with_params + get :calling_from_controller_with_params + assert_equal "David of the House, speaking", @response.body + end + + def test_calling_from_controller_with_different_status_code + get :calling_from_controller_with_different_status_code + assert_equal 500, @response.response_code + end + + def test_calling_from_template + get :calling_from_template + assert_equal "Ring, ring: Lady of the House, speaking", @response.body + end + + def test_etag_is_set_for_parent_template_when_calling_from_template + get :calling_from_template + expected_etag = etag_for("Ring, ring: Lady of the House, speaking") + assert_equal expected_etag, @response.headers['ETag'] + end + + def test_internal_calling + get :internal_caller + assert_equal "Are you there? Yes, ma'am", @response.body + end + + def test_flash + get :set_flash + assert_equal 'My stoney baby', flash[:notice] + get :use_flash + assert_equal 'My stoney baby', @response.body + get :use_flash + assert_equal 'no flash', @response.body + end + + def test_component_redirect_redirects + get :calling_redirected + + assert_redirected_to :action => "being_called" + end + + def test_component_multiple_redirect_redirects + test_component_redirect_redirects + test_internal_calling + end + + def test_component_as_string_redirect_renders_redirected_action + get :calling_redirected_as_string + + assert_equal "Lady of the House, speaking", @response.body + end + + protected + def etag_for(text) + %("#{Digest::MD5.hexdigest(text)}") + end +end diff --git a/vendor/rails-2.0.2/actionpack/test/controller/content_type_test.rb b/vendor/rails-2.0.2/actionpack/test/controller/content_type_test.rb new file mode 100644 index 000000000..1841d37c0 --- /dev/null +++ b/vendor/rails-2.0.2/actionpack/test/controller/content_type_test.rb @@ -0,0 +1,139 @@ +require File.dirname(__FILE__) + '/../abstract_unit' + +class ContentTypeController < ActionController::Base + def render_content_type_from_body + response.content_type = Mime::RSS + render :text => "hello world!" + end + + def render_defaults + render :text => "hello world!" + end + + def render_content_type_from_render + render :text => "hello world!", :content_type => Mime::RSS + end + + def render_charset_from_body + response.charset = "utf-16" + render :text => "hello world!" + end + + def render_default_for_rhtml + end + + def render_default_for_rxml + end + + def render_default_for_rjs + end + + def render_change_for_rxml + response.content_type = Mime::HTML + render :action => "render_default_for_rxml" + end + + def render_default_content_types_for_respond_to + respond_to do |format| + format.html { render :text => "hello world!" } + format.xml { render :action => "render_default_content_types_for_respond_to.rhtml" } + format.js { render :text => "hello world!" } + format.rss { render :text => "hello world!", :content_type => Mime::XML } + end + end + + def rescue_action(e) raise end +end + +ContentTypeController.view_paths = [ File.dirname(__FILE__) + "/../fixtures/" ] + +class ContentTypeTest < Test::Unit::TestCase + def setup + @controller = ContentTypeController.new + + # enable a logger so that (e.g.) the benchmarking stuff runs, so we can get + # a more accurate simulation of what happens in "real life". + @controller.logger = Logger.new(nil) + + @request = ActionController::TestRequest.new + @response = ActionController::TestResponse.new + end + + def test_render_defaults + get :render_defaults + assert_equal "utf-8", @response.charset + assert_equal Mime::HTML, @response.content_type + end + + def test_render_changed_charset_default + ContentTypeController.default_charset = "utf-16" + get :render_defaults + assert_equal "utf-16", @response.charset + assert_equal Mime::HTML, @response.content_type + ContentTypeController.default_charset = "utf-8" + end + + def test_content_type_from_body + get :render_content_type_from_body + assert_equal "application/rss+xml", @response.content_type + assert_equal "utf-8", @response.charset + end + + def test_content_type_from_render + get :render_content_type_from_render + assert_equal "application/rss+xml", @response.content_type + assert_equal "utf-8", @response.charset + end + + def test_charset_from_body + get :render_charset_from_body + assert_equal "utf-16", @response.charset + assert_equal Mime::HTML, @response.content_type + end + + def test_default_for_rhtml + get :render_default_for_rhtml + assert_equal Mime::HTML, @response.content_type + assert_equal "utf-8", @response.charset + end + + def test_default_for_rxml + get :render_default_for_rxml + assert_equal Mime::XML, @response.content_type + assert_equal "utf-8", @response.charset + end + + def test_default_for_rjs + xhr :post, :render_default_for_rjs + assert_equal Mime::JS, @response.content_type + assert_equal "utf-8", @response.charset + end + + def test_change_for_rxml + get :render_change_for_rxml + assert_equal Mime::HTML, @response.content_type + assert_equal "utf-8", @response.charset + end + + def test_render_default_content_types_for_respond_to + @request.env["HTTP_ACCEPT"] = Mime::HTML.to_s + get :render_default_content_types_for_respond_to + assert_equal Mime::HTML, @response.content_type + + @request.env["HTTP_ACCEPT"] = Mime::JS.to_s + get :render_default_content_types_for_respond_to + assert_equal Mime::JS, @response.content_type + end + + def test_render_default_content_types_for_respond_to_with_template + @request.env["HTTP_ACCEPT"] = Mime::XML.to_s + get :render_default_content_types_for_respond_to + assert_equal Mime::XML, @response.content_type + end + + def test_render_default_content_types_for_respond_to_with_overwrite + @request.env["HTTP_ACCEPT"] = Mime::RSS.to_s + get :render_default_content_types_for_respond_to + assert_equal Mime::XML, @response.content_type + end +end
\ No newline at end of file diff --git a/vendor/rails-2.0.2/actionpack/test/controller/controller_fixtures/app/controllers/admin/user_controller.rb b/vendor/rails-2.0.2/actionpack/test/controller/controller_fixtures/app/controllers/admin/user_controller.rb new file mode 100644 index 000000000..e69de29bb --- /dev/null +++ b/vendor/rails-2.0.2/actionpack/test/controller/controller_fixtures/app/controllers/admin/user_controller.rb diff --git a/vendor/rails-2.0.2/actionpack/test/controller/controller_fixtures/app/controllers/user_controller.rb b/vendor/rails-2.0.2/actionpack/test/controller/controller_fixtures/app/controllers/user_controller.rb new file mode 100644 index 000000000..e69de29bb --- /dev/null +++ b/vendor/rails-2.0.2/actionpack/test/controller/controller_fixtures/app/controllers/user_controller.rb diff --git a/vendor/rails-2.0.2/actionpack/test/controller/controller_fixtures/vendor/plugins/bad_plugin/lib/plugin_controller.rb b/vendor/rails-2.0.2/actionpack/test/controller/controller_fixtures/vendor/plugins/bad_plugin/lib/plugin_controller.rb new file mode 100644 index 000000000..e69de29bb --- /dev/null +++ b/vendor/rails-2.0.2/actionpack/test/controller/controller_fixtures/vendor/plugins/bad_plugin/lib/plugin_controller.rb diff --git a/vendor/rails-2.0.2/actionpack/test/controller/cookie_test.rb b/vendor/rails-2.0.2/actionpack/test/controller/cookie_test.rb new file mode 100644 index 000000000..6a833fee3 --- /dev/null +++ b/vendor/rails-2.0.2/actionpack/test/controller/cookie_test.rb @@ -0,0 +1,135 @@ +require File.dirname(__FILE__) + '/../abstract_unit' + +class CookieTest < Test::Unit::TestCase + class TestController < ActionController::Base + def authenticate + cookies["user_name"] = "david" + end + + def authenticate_for_fourteen_days + cookies["user_name"] = { "value" => "david", "expires" => Time.local(2005, 10, 10) } + end + + def authenticate_for_fourteen_days_with_symbols + cookies[:user_name] = { :value => "david", :expires => Time.local(2005, 10, 10) } + end + + def set_multiple_cookies + cookies["user_name"] = { "value" => "david", "expires" => Time.local(2005, 10, 10) } + cookies["login"] = "XJ-122" + end + + def access_frozen_cookies + cookies["will"] = "work" + end + + def logout + cookies.delete("user_name") + end + + def delete_cookie_with_path + cookies.delete("user_name", :path => '/beaten') + render :text => "hello world" + end + + def authenticate_with_http_only + cookies["user_name"] = { :value => "david", :http_only => true } + end + + def rescue_action(e) + raise unless ActionController::MissingTemplate # No templates here, and we don't care about the output + end + end + + def setup + @request = ActionController::TestRequest.new + @response = ActionController::TestResponse.new + + @controller = TestController.new + @request.host = "www.nextangle.com" + end + + def test_setting_cookie + get :authenticate + assert_equal [ CGI::Cookie::new("name" => "user_name", "value" => "david") ], @response.headers["cookie"] + end + + def test_setting_cookie_for_fourteen_days + get :authenticate_for_fourteen_days + assert_equal [ CGI::Cookie::new("name" => "user_name", "value" => "david", "expires" => Time.local(2005, 10, 10)) ], @response.headers["cookie"] + end + + def test_setting_cookie_for_fourteen_days_with_symbols + get :authenticate_for_fourteen_days + assert_equal [ CGI::Cookie::new("name" => "user_name", "value" => "david", "expires" => Time.local(2005, 10, 10)) ], @response.headers["cookie"] + end + + def test_setting_cookie_with_http_only + get :authenticate_with_http_only + assert_equal [ CGI::Cookie::new("name" => "user_name", "value" => "david", "http_only" => true) ], @response.headers["cookie"] + assert_equal CGI::Cookie::new("name" => "user_name", "value" => "david", "path" => "/", "http_only" => true).to_s, @response.headers["cookie"][0].to_s + end + + def test_multiple_cookies + get :set_multiple_cookies + assert_equal 2, @response.cookies.size + end + + def test_setting_test_cookie + assert_nothing_raised { get :access_frozen_cookies } + end + + def test_expiring_cookie + get :logout + assert_equal [ CGI::Cookie::new("name" => "user_name", "value" => "", "expires" => Time.at(0)) ], @response.headers["cookie"] + end + + def test_cookiejar_accessor + @request.cookies["user_name"] = CGI::Cookie.new("name" => "user_name", "value" => "david", "expires" => Time.local(2025, 10, 10)) + @controller.request = @request + jar = ActionController::CookieJar.new(@controller) + assert_equal "david", jar["user_name"] + assert_equal nil, jar["something_else"] + end + + def test_cookiejar_accessor_with_array_value + a = %w{1 2 3} + @request.cookies["pages"] = CGI::Cookie.new("name" => "pages", "value" => a, "expires" => Time.local(2025, 10, 10)) + @controller.request = @request + jar = ActionController::CookieJar.new(@controller) + assert_equal a, jar["pages"] + end + + def test_delete_cookie_with_path + get :delete_cookie_with_path + assert_equal "/beaten", @response.headers["cookie"].first.path + assert_not_equal "/", @response.headers["cookie"].first.path + end + + def test_cookie_to_s_simple_values + assert_equal 'myname=myvalue; path=', CGI::Cookie.new('myname', 'myvalue').to_s + end + + def test_cookie_to_s_hash + cookie_str = CGI::Cookie.new( + 'name' => 'myname', + 'value' => 'myvalue', + 'domain' => 'mydomain', + 'path' => 'mypath', + 'expires' => Time.utc(2007, 10, 20), + 'secure' => true, + 'http_only' => true).to_s + assert_equal 'myname=myvalue; domain=mydomain; path=mypath; expires=Sat, 20 Oct 2007 00:00:00 GMT; secure; HttpOnly', cookie_str + end + + def test_cookie_to_s_hash_default_not_secure_not_http_only + cookie_str = CGI::Cookie.new( + 'name' => 'myname', + 'value' => 'myvalue', + 'domain' => 'mydomain', + 'path' => 'mypath', + 'expires' => Time.utc(2007, 10, 20)) + assert cookie_str !~ /secure/ + assert cookie_str !~ /HttpOnly/ + end +end diff --git a/vendor/rails-2.0.2/actionpack/test/controller/custom_handler_test.rb b/vendor/rails-2.0.2/actionpack/test/controller/custom_handler_test.rb new file mode 100644 index 000000000..2747a0f3c --- /dev/null +++ b/vendor/rails-2.0.2/actionpack/test/controller/custom_handler_test.rb @@ -0,0 +1,41 @@ +require File.dirname(__FILE__) + '/../abstract_unit' + +class CustomHandler + def initialize( view ) + @view = view + end + + def render( template, local_assigns ) + [ template, + local_assigns, + @view ] + end +end + +class CustomHandlerTest < Test::Unit::TestCase + def setup + ActionView::Base.register_template_handler "foo", CustomHandler + ActionView::Base.register_template_handler :foo2, CustomHandler + @view = ActionView::Base.new + end + + def test_custom_render + result = @view.render_template( "foo", "hello <%= one %>", nil, :one => "two" ) + assert_equal( + [ "hello <%= one %>", { :one => "two" }, @view ], + result ) + end + + def test_custom_render2 + result = @view.render_template( "foo2", "hello <%= one %>", nil, :one => "two" ) + assert_equal( + [ "hello <%= one %>", { :one => "two" }, @view ], + result ) + end + + def test_unhandled_extension + # uses the ERb handler by default if the extension isn't recognized + result = @view.render_template( "bar", "hello <%= one %>", nil, :one => "two" ) + assert_equal "hello two", result + end +end diff --git a/vendor/rails-2.0.2/actionpack/test/controller/deprecation/deprecated_base_methods_test.rb b/vendor/rails-2.0.2/actionpack/test/controller/deprecation/deprecated_base_methods_test.rb new file mode 100644 index 000000000..6d7157e1a --- /dev/null +++ b/vendor/rails-2.0.2/actionpack/test/controller/deprecation/deprecated_base_methods_test.rb @@ -0,0 +1,37 @@ +require File.dirname(__FILE__) + '/../../abstract_unit' + +class DeprecatedBaseMethodsTest < Test::Unit::TestCase + class Target < ActionController::Base + + def home_url(greeting) + "http://example.com/#{greeting}" + end + + def raises_name_error + this_method_doesnt_exist + end + + def rescue_action(e) raise e end + end + + Target.view_paths = [ File.dirname(__FILE__) + "/../../fixtures" ] + + def setup + @request = ActionController::TestRequest.new + @response = ActionController::TestResponse.new + @controller = Target.new + end + + def test_log_error_silences_deprecation_warnings + get :raises_name_error + rescue => e + assert_not_deprecated { @controller.send :log_error, e } + end + + def test_assertion_failed_error_silences_deprecation_warnings + get :raises_name_error + rescue => e + error = Test::Unit::Error.new('testing ur doodz', e) + assert_not_deprecated { error.message } + end +end diff --git a/vendor/rails-2.0.2/actionpack/test/controller/dispatcher_test.rb b/vendor/rails-2.0.2/actionpack/test/controller/dispatcher_test.rb new file mode 100644 index 000000000..ec937ebfd --- /dev/null +++ b/vendor/rails-2.0.2/actionpack/test/controller/dispatcher_test.rb @@ -0,0 +1,123 @@ +require "#{File.dirname(__FILE__)}/../abstract_unit" + +uses_mocha 'dispatcher tests' do + +require 'action_controller/dispatcher' + +class DispatcherTest < Test::Unit::TestCase + Dispatcher = ActionController::Dispatcher + + def setup + @output = StringIO.new + ENV['REQUEST_METHOD'] = 'GET' + + Dispatcher.callbacks[:prepare].clear + @dispatcher = Dispatcher.new(@output) + end + + def teardown + ENV['REQUEST_METHOD'] = nil + end + + def test_clears_dependencies_after_dispatch_if_in_loading_mode + Dependencies.stubs(:load?).returns(true) + + ActionController::Routing::Routes.expects(:reload).once + Dependencies.expects(:clear).once + + dispatch + end + + def test_leaves_dependencies_after_dispatch_if_not_in_loading_mode + Dependencies.stubs(:load?).returns(false) + + ActionController::Routing::Routes.expects(:reload).never + Dependencies.expects(:clear).never + + dispatch + end + + def test_failsafe_response + CGI.expects(:new).raises('some multipart parsing failure') + + ActionController::Routing::Routes.stubs(:reload) + Dispatcher.stubs(:log_failsafe_exception) + + assert_nothing_raised { dispatch } + + assert_equal "Status: 400 Bad Request\r\nContent-Type: text/html\r\n\r\n<html><body><h1>400 Bad Request</h1></body></html>", @output.string + end + + def test_reload_application_sets_unprepared_if_loading_dependencies + Dependencies.stubs(:load?).returns(false) + ActionController::Routing::Routes.expects(:reload).never + @dispatcher.unprepared = false + @dispatcher.send!(:reload_application) + assert !@dispatcher.unprepared + + Dependencies.stubs(:load?).returns(true) + ActionController::Routing::Routes.expects(:reload).once + @dispatcher.send!(:reload_application) + assert @dispatcher.unprepared + end + + def test_prepare_application_runs_callbacks_if_unprepared + a = b = c = nil + Dispatcher.to_prepare { a = b = c = 1 } + Dispatcher.to_prepare { b = c = 2 } + Dispatcher.to_prepare { c = 3 } + + # Skip the callbacks when already prepared. + @dispatcher.unprepared = false + @dispatcher.send! :prepare_application + assert_nil a || b || c + + # Perform the callbacks when unprepared. + @dispatcher.unprepared = true + @dispatcher.send! :prepare_application + assert_equal 1, a + assert_equal 2, b + assert_equal 3, c + + # But when not :load, make sure they are only run once + a = b = c = nil + @dispatcher.send! :prepare_application + assert_nil a || b || c + end + + def test_to_prepare_with_identifier_replaces + a = b = nil + Dispatcher.to_prepare(:unique_id) { a = b = 1 } + Dispatcher.to_prepare(:unique_id) { a = 2 } + + @dispatcher.unprepared = true + @dispatcher.send! :prepare_application + assert_equal 2, a + assert_equal nil, b + end + + def test_to_prepare_only_runs_once_if_not_loading_dependencies + Dependencies.stubs(:load?).returns(false) + called = 0 + Dispatcher.to_prepare(:unprepared_test) { called += 1 } + 2.times { dispatch } + assert_equal 1, called + end + + private + def dispatch(output = @output) + controller = mock + controller.stubs(:process).returns(controller) + controller.stubs(:out).with(output).returns('response') + + ActionController::Routing::Routes.stubs(:recognize).returns(controller) + + Dispatcher.dispatch(nil, {}, output) + end + + def assert_subclasses(howmany, klass, message = klass.subclasses.inspect) + assert_equal howmany, klass.subclasses.size, message + end +end + +end diff --git a/vendor/rails-2.0.2/actionpack/test/controller/fake_controllers.rb b/vendor/rails-2.0.2/actionpack/test/controller/fake_controllers.rb new file mode 100644 index 000000000..5f958b284 --- /dev/null +++ b/vendor/rails-2.0.2/actionpack/test/controller/fake_controllers.rb @@ -0,0 +1,16 @@ +class << Object; alias_method :const_available?, :const_defined?; end + +class ContentController < Class.new(ActionController::Base) +end +class NotAController +end +module Admin + class << self; alias_method :const_available?, :const_defined?; end + class UserController < Class.new(ActionController::Base); end + class NewsFeedController < Class.new(ActionController::Base); end +end + +ActionController::Routing::Routes.draw do |map| + map.route_one 'route_one', :controller => 'elsewhere', :action => 'flash_me' + map.connect ':controller/:action/:id' +end diff --git a/vendor/rails-2.0.2/actionpack/test/controller/fake_models.rb b/vendor/rails-2.0.2/actionpack/test/controller/fake_models.rb new file mode 100644 index 000000000..2761b09f2 --- /dev/null +++ b/vendor/rails-2.0.2/actionpack/test/controller/fake_models.rb @@ -0,0 +1,5 @@ +class Customer < Struct.new(:name, :id) + def to_param + id.to_s + end +end diff --git a/vendor/rails-2.0.2/actionpack/test/controller/filter_params_test.rb b/vendor/rails-2.0.2/actionpack/test/controller/filter_params_test.rb new file mode 100644 index 000000000..7b810b162 --- /dev/null +++ b/vendor/rails-2.0.2/actionpack/test/controller/filter_params_test.rb @@ -0,0 +1,43 @@ +require File.dirname(__FILE__) + '/../abstract_unit' + +class FilterParamController < ActionController::Base +end + +class FilterParamTest < Test::Unit::TestCase + def setup + @controller = FilterParamController.new + end + + def test_filter_parameters + assert FilterParamController.respond_to?(:filter_parameter_logging) + assert !@controller.respond_to?(:filter_parameters) + + FilterParamController.filter_parameter_logging + assert @controller.respond_to?(:filter_parameters) + + test_hashes = [[{},{},[]], + [{'foo'=>nil},{'foo'=>nil},[]], + [{'foo'=>'bar'},{'foo'=>'bar'},[]], + [{'foo'=>'bar'},{'foo'=>'bar'},%w'food'], + [{'foo'=>'bar'},{'foo'=>'[FILTERED]'},%w'foo'], + [{'foo'=>'bar', 'bar'=>'foo'},{'foo'=>'[FILTERED]', 'bar'=>'foo'},%w'foo baz'], + [{'foo'=>'bar', 'baz'=>'foo'},{'foo'=>'[FILTERED]', 'baz'=>'[FILTERED]'},%w'foo baz'], + [{'bar'=>{'foo'=>'bar','bar'=>'foo'}},{'bar'=>{'foo'=>'[FILTERED]','bar'=>'foo'}},%w'fo'], + [{'foo'=>{'foo'=>'bar','bar'=>'foo'}},{'foo'=>'[FILTERED]'},%w'f banana']] + + test_hashes.each do |before_filter, after_filter, filter_words| + FilterParamController.filter_parameter_logging(*filter_words) + assert_equal after_filter, @controller.filter_parameters(before_filter) + + filter_words.push('blah') + FilterParamController.filter_parameter_logging(*filter_words) do |key, value| + value.reverse! if key =~ /bargain/ + end + + before_filter['barg'] = {'bargain'=>'gain', 'blah'=>'bar', 'bar'=>{'bargain'=>{'blah'=>'foo'}}} + after_filter['barg'] = {'bargain'=>'niag', 'blah'=>'[FILTERED]', 'bar'=>{'bargain'=>{'blah'=>'[FILTERED]'}}} + + assert_equal after_filter, @controller.filter_parameters(before_filter) + end + end +end diff --git a/vendor/rails-2.0.2/actionpack/test/controller/filters_test.rb b/vendor/rails-2.0.2/actionpack/test/controller/filters_test.rb new file mode 100644 index 000000000..188e75afd --- /dev/null +++ b/vendor/rails-2.0.2/actionpack/test/controller/filters_test.rb @@ -0,0 +1,856 @@ +require File.dirname(__FILE__) + '/../abstract_unit' + +# FIXME: crashes Ruby 1.9 +class FilterTest < Test::Unit::TestCase + class TestController < ActionController::Base + before_filter :ensure_login + after_filter :clean_up + + def show + render :inline => "ran action" + end + + private + def ensure_login + @ran_filter ||= [] + @ran_filter << "ensure_login" + end + + def clean_up + @ran_after_filter ||= [] + @ran_after_filter << "clean_up" + end + end + + class ChangingTheRequirementsController < TestController + before_filter :ensure_login, :except => [:go_wild] + + def go_wild + render :text => "gobble" + end + end + + class TestMultipleFiltersController < ActionController::Base + before_filter :try_1 + before_filter :try_2 + before_filter :try_3 + + (1..3).each do |i| + define_method "fail_#{i}" do + render :text => i.to_s + end + end + + protected + (1..3).each do |i| + define_method "try_#{i}" do + instance_variable_set :@try, i + if action_name == "fail_#{i}" + head(404) + end + end + end + end + + class RenderingController < ActionController::Base + before_filter :render_something_else + + def show + @ran_action = true + render :inline => "ran action" + end + + private + def render_something_else + render :inline => "something else" + end + end + + class ConditionalFilterController < ActionController::Base + def show + render :inline => "ran action" + end + + def another_action + render :inline => "ran action" + end + + def show_without_filter + render :inline => "ran action without filter" + end + + private + def ensure_login + @ran_filter ||= [] + @ran_filter << "ensure_login" + end + + def clean_up_tmp + @ran_filter ||= [] + @ran_filter << "clean_up_tmp" + end + + def rescue_action(e) raise(e) end + end + + class ConditionalCollectionFilterController < ConditionalFilterController + before_filter :ensure_login, :except => [ :show_without_filter, :another_action ] + end + + class OnlyConditionSymController < ConditionalFilterController + before_filter :ensure_login, :only => :show + end + + class ExceptConditionSymController < ConditionalFilterController + before_filter :ensure_login, :except => :show_without_filter + end + + class BeforeAndAfterConditionController < ConditionalFilterController + before_filter :ensure_login, :only => :show + after_filter :clean_up_tmp, :only => :show + end + + class OnlyConditionProcController < ConditionalFilterController + before_filter(:only => :show) {|c| c.assigns["ran_proc_filter"] = true } + end + + class ExceptConditionProcController < ConditionalFilterController + before_filter(:except => :show_without_filter) {|c| c.assigns["ran_proc_filter"] = true } + end + + class ConditionalClassFilter + def self.filter(controller) controller.assigns["ran_class_filter"] = true end + end + + class OnlyConditionClassController < ConditionalFilterController + before_filter ConditionalClassFilter, :only => :show + end + + class ExceptConditionClassController < ConditionalFilterController + before_filter ConditionalClassFilter, :except => :show_without_filter + end + + class AnomolousYetValidConditionController < ConditionalFilterController + before_filter(ConditionalClassFilter, :ensure_login, Proc.new {|c| c.assigns["ran_proc_filter1"] = true }, :except => :show_without_filter) { |c| c.assigns["ran_proc_filter2"] = true} + end + + class EmptyFilterChainController < TestController + self.filter_chain.clear + def show + @action_executed = true + render :text => "yawp!" + end + end + + class PrependingController < TestController + prepend_before_filter :wonderful_life + # skip_before_filter :fire_flash + + private + def wonderful_life + @ran_filter ||= [] + @ran_filter << "wonderful_life" + end + end + + class ConditionalSkippingController < TestController + skip_before_filter :ensure_login, :only => [ :login ] + skip_after_filter :clean_up, :only => [ :login ] + + before_filter :find_user, :only => [ :change_password ] + + def login + render :inline => "ran action" + end + + def change_password + render :inline => "ran action" + end + + protected + def find_user + @ran_filter ||= [] + @ran_filter << "find_user" + end + end + + class ConditionalParentOfConditionalSkippingController < ConditionalFilterController + before_filter :conditional_in_parent, :only => [:show, :another_action] + after_filter :conditional_in_parent, :only => [:show, :another_action] + + private + + def conditional_in_parent + @ran_filter ||= [] + @ran_filter << 'conditional_in_parent' + end + end + + class ChildOfConditionalParentController < ConditionalParentOfConditionalSkippingController + skip_before_filter :conditional_in_parent, :only => :another_action + skip_after_filter :conditional_in_parent, :only => :another_action + end + + class AnotherChildOfConditionalParentController < ConditionalParentOfConditionalSkippingController + skip_before_filter :conditional_in_parent, :only => :show + end + + class ProcController < PrependingController + before_filter(proc { |c| c.assigns["ran_proc_filter"] = true }) + end + + class ImplicitProcController < PrependingController + before_filter { |c| c.assigns["ran_proc_filter"] = true } + end + + class AuditFilter + def self.filter(controller) + controller.assigns["was_audited"] = true + end + end + + class AroundFilter + def before(controller) + @execution_log = "before" + controller.class.execution_log << " before aroundfilter " if controller.respond_to? :execution_log + controller.assigns["before_ran"] = true + end + + def after(controller) + controller.assigns["execution_log"] = @execution_log + " and after" + controller.assigns["after_ran"] = true + controller.class.execution_log << " after aroundfilter " if controller.respond_to? :execution_log + end + end + + class AppendedAroundFilter + def before(controller) + controller.class.execution_log << " before appended aroundfilter " + end + + def after(controller) + controller.class.execution_log << " after appended aroundfilter " + end + end + + class AuditController < ActionController::Base + before_filter(AuditFilter) + + def show + render :text => "hello" + end + end + + class AroundFilterController < PrependingController + around_filter AroundFilter.new + end + + class BeforeAfterClassFilterController < PrependingController + begin + filter = AroundFilter.new + before_filter filter + after_filter filter + end + end + + class MixedFilterController < PrependingController + cattr_accessor :execution_log + + def initialize + @@execution_log = "" + end + + before_filter { |c| c.class.execution_log << " before procfilter " } + prepend_around_filter AroundFilter.new + + after_filter { |c| c.class.execution_log << " after procfilter " } + append_around_filter AppendedAroundFilter.new + end + + class MixedSpecializationController < ActionController::Base + class OutOfOrder < StandardError; end + + before_filter :first + before_filter :second, :only => :foo + + def foo + render :text => 'foo' + end + + def bar + render :text => 'bar' + end + + protected + def first + @first = true + end + + def second + raise OutOfOrder unless @first + end + end + + class DynamicDispatchController < ActionController::Base + before_filter :choose + + %w(foo bar baz).each do |action| + define_method(action) { render :text => action } + end + + private + def choose + self.action_name = params[:choose] + end + end + + class PrependingBeforeAndAfterController < ActionController::Base + prepend_before_filter :before_all + prepend_after_filter :after_all + before_filter :between_before_all_and_after_all + + def before_all + @ran_filter ||= [] + @ran_filter << 'before_all' + end + + def after_all + @ran_filter ||= [] + @ran_filter << 'after_all' + end + + def between_before_all_and_after_all + @ran_filter ||= [] + @ran_filter << 'between_before_all_and_after_all' + end + def show + render :text => 'hello' + end + end + + class ErrorToRescue < Exception; end + + class RescuingAroundFilterWithBlock + def filter(controller) + begin + yield + rescue ErrorToRescue => ex + controller.send! :render, :text => "I rescued this: #{ex.inspect}" + end + end + end + + class RescuedController < ActionController::Base + around_filter RescuingAroundFilterWithBlock.new + + def show + raise ErrorToRescue.new("Something made the bad noise.") + end + + private + def rescue_action(exception) + raise exception + end + end + + class NonYieldingAroundFilterController < ActionController::Base + + before_filter :filter_one + around_filter :non_yielding_filter + before_filter :filter_two + after_filter :filter_three + + def index + render :inline => "index" + end + + #make sure the controller complains + def rescue_action(e); raise e; end + + private + + def filter_one + @filters ||= [] + @filters << "filter_one" + end + + def filter_two + @filters << "filter_two" + end + + def non_yielding_filter + @filters << "zomg it didn't yield" + @filter_return_value + end + + def filter_three + @filters << "filter_three" + end + + end + + def test_non_yielding_around_filters_not_returning_false_do_not_raise + controller = NonYieldingAroundFilterController.new + controller.instance_variable_set "@filter_return_value", true + assert_nothing_raised do + test_process(controller, "index") + end + end + + def test_non_yielding_around_filters_returning_false_do_not_raise + controller = NonYieldingAroundFilterController.new + controller.instance_variable_set "@filter_return_value", false + assert_nothing_raised do + test_process(controller, "index") + end + end + + def test_after_filters_are_not_run_if_around_filter_returns_false + controller = NonYieldingAroundFilterController.new + controller.instance_variable_set "@filter_return_value", false + test_process(controller, "index") + assert_equal ["filter_one", "zomg it didn't yield"], controller.assigns['filters'] + end + + def test_after_filters_are_not_run_if_around_filter_does_not_yield + controller = NonYieldingAroundFilterController.new + controller.instance_variable_set "@filter_return_value", true + test_process(controller, "index") + assert_equal ["filter_one", "zomg it didn't yield"], controller.assigns['filters'] + end + + def test_empty_filter_chain + assert_equal 0, EmptyFilterChainController.filter_chain.size + assert test_process(EmptyFilterChainController).template.assigns['action_executed'] + end + + def test_added_filter_to_inheritance_graph + assert_equal [ :ensure_login ], TestController.before_filters + end + + def test_base_class_in_isolation + assert_equal [ ], ActionController::Base.before_filters + end + + def test_prepending_filter + assert_equal [ :wonderful_life, :ensure_login ], PrependingController.before_filters + end + + def test_running_filters + assert_equal %w( wonderful_life ensure_login ), test_process(PrependingController).template.assigns["ran_filter"] + end + + def test_running_filters_with_proc + assert test_process(ProcController).template.assigns["ran_proc_filter"] + end + + def test_running_filters_with_implicit_proc + assert test_process(ImplicitProcController).template.assigns["ran_proc_filter"] + end + + def test_running_filters_with_class + assert test_process(AuditController).template.assigns["was_audited"] + end + + def test_running_anomolous_yet_valid_condition_filters + response = test_process(AnomolousYetValidConditionController) + assert_equal %w( ensure_login ), response.template.assigns["ran_filter"] + assert response.template.assigns["ran_class_filter"] + assert response.template.assigns["ran_proc_filter1"] + assert response.template.assigns["ran_proc_filter2"] + + response = test_process(AnomolousYetValidConditionController, "show_without_filter") + assert_equal nil, response.template.assigns["ran_filter"] + assert !response.template.assigns["ran_class_filter"] + assert !response.template.assigns["ran_proc_filter1"] + assert !response.template.assigns["ran_proc_filter2"] + end + + def test_running_collection_condition_filters + assert_equal %w( ensure_login ), test_process(ConditionalCollectionFilterController).template.assigns["ran_filter"] + assert_equal nil, test_process(ConditionalCollectionFilterController, "show_without_filter").template.assigns["ran_filter"] + assert_equal nil, test_process(ConditionalCollectionFilterController, "another_action").template.assigns["ran_filter"] + end + + def test_running_only_condition_filters + assert_equal %w( ensure_login ), test_process(OnlyConditionSymController).template.assigns["ran_filter"] + assert_equal nil, test_process(OnlyConditionSymController, "show_without_filter").template.assigns["ran_filter"] + + assert test_process(OnlyConditionProcController).template.assigns["ran_proc_filter"] + assert !test_process(OnlyConditionProcController, "show_without_filter").template.assigns["ran_proc_filter"] + + assert test_process(OnlyConditionClassController).template.assigns["ran_class_filter"] + assert !test_process(OnlyConditionClassController, "show_without_filter").template.assigns["ran_class_filter"] + end + + def test_running_except_condition_filters + assert_equal %w( ensure_login ), test_process(ExceptConditionSymController).template.assigns["ran_filter"] + assert_equal nil, test_process(ExceptConditionSymController, "show_without_filter").template.assigns["ran_filter"] + + assert test_process(ExceptConditionProcController).template.assigns["ran_proc_filter"] + assert !test_process(ExceptConditionProcController, "show_without_filter").template.assigns["ran_proc_filter"] + + assert test_process(ExceptConditionClassController).template.assigns["ran_class_filter"] + assert !test_process(ExceptConditionClassController, "show_without_filter").template.assigns["ran_class_filter"] + end + + def test_running_before_and_after_condition_filters + assert_equal %w( ensure_login clean_up_tmp), test_process(BeforeAndAfterConditionController).template.assigns["ran_filter"] + assert_equal nil, test_process(BeforeAndAfterConditionController, "show_without_filter").template.assigns["ran_filter"] + end + + def test_bad_filter + bad_filter_controller = Class.new(ActionController::Base) + assert_raises(ActionController::ActionControllerError) do + bad_filter_controller.before_filter 2 + end + end + + def test_around_filter + controller = test_process(AroundFilterController) + assert controller.template.assigns["before_ran"] + assert controller.template.assigns["after_ran"] + end + + def test_before_after_class_filter + controller = test_process(BeforeAfterClassFilterController) + assert controller.template.assigns["before_ran"] + assert controller.template.assigns["after_ran"] + end + + def test_having_properties_in_around_filter + controller = test_process(AroundFilterController) + assert_equal "before and after", controller.template.assigns["execution_log"] + end + + def test_prepending_and_appending_around_filter + controller = test_process(MixedFilterController) + assert_equal " before aroundfilter before procfilter before appended aroundfilter " + + " after appended aroundfilter after aroundfilter after procfilter ", + MixedFilterController.execution_log + end + + def test_rendering_breaks_filtering_chain + response = test_process(RenderingController) + assert_equal "something else", response.body + assert !response.template.assigns["ran_action"] + end + + def test_filters_with_mixed_specialization_run_in_order + assert_nothing_raised do + response = test_process(MixedSpecializationController, 'bar') + assert_equal 'bar', response.body + end + + assert_nothing_raised do + response = test_process(MixedSpecializationController, 'foo') + assert_equal 'foo', response.body + end + end + + def test_dynamic_dispatch + %w(foo bar baz).each do |action| + request = ActionController::TestRequest.new + request.query_parameters[:choose] = action + response = DynamicDispatchController.process(request, ActionController::TestResponse.new) + assert_equal action, response.body + end + end + + def test_running_prepended_before_and_after_filter + assert_equal 3, PrependingBeforeAndAfterController.filter_chain.length + response = test_process(PrependingBeforeAndAfterController) + assert_equal %w( before_all between_before_all_and_after_all after_all ), response.template.assigns["ran_filter"] + end + + def test_conditional_skipping_of_filters + assert_nil test_process(ConditionalSkippingController, "login").template.assigns["ran_filter"] + assert_equal %w( ensure_login find_user ), test_process(ConditionalSkippingController, "change_password").template.assigns["ran_filter"] + + assert_nil test_process(ConditionalSkippingController, "login").template.controller.instance_variable_get("@ran_after_filter") + assert_equal %w( clean_up ), test_process(ConditionalSkippingController, "change_password").template.controller.instance_variable_get("@ran_after_filter") + end + + def test_conditional_skipping_of_filters_when_parent_filter_is_also_conditional + assert_equal %w( conditional_in_parent conditional_in_parent ), test_process(ChildOfConditionalParentController).template.assigns['ran_filter'] + assert_nil test_process(ChildOfConditionalParentController, 'another_action').template.assigns['ran_filter'] + end + + def test_condition_skipping_of_filters_when_siblings_also_have_conditions + assert_equal %w( conditional_in_parent conditional_in_parent ), test_process(ChildOfConditionalParentController).template.assigns['ran_filter'], "1" + assert_equal nil, test_process(AnotherChildOfConditionalParentController).template.assigns['ran_filter'] + assert_equal %w( conditional_in_parent conditional_in_parent ), test_process(ChildOfConditionalParentController).template.assigns['ran_filter'] + end + + def test_changing_the_requirements + assert_equal nil, test_process(ChangingTheRequirementsController, "go_wild").template.assigns['ran_filter'] + end + + def test_a_rescuing_around_filter + response = nil + assert_nothing_raised do + response = test_process(RescuedController) + end + + assert response.success? + assert_equal("I rescued this: #<FilterTest::ErrorToRescue: Something made the bad noise.>", response.body) + end + + private + def test_process(controller, action = "show") + request = ActionController::TestRequest.new + request.action = action + controller.process(request, ActionController::TestResponse.new) + end +end + + + +class PostsController < ActionController::Base + def rescue_action(e); raise e; end + + module AroundExceptions + class Error < StandardError ; end + class Before < Error ; end + class After < Error ; end + end + include AroundExceptions + + class DefaultFilter + include AroundExceptions + end + + module_eval %w(raises_before raises_after raises_both no_raise no_filter).map { |action| "def #{action}; default_action end" }.join("\n") + + private + def default_action + render :inline => "#{action_name} called" + end +end + +class ControllerWithSymbolAsFilter < PostsController + around_filter :raise_before, :only => :raises_before + around_filter :raise_after, :only => :raises_after + around_filter :without_exception, :only => :no_raise + + private + def raise_before + raise Before + yield + end + + def raise_after + yield + raise After + end + + def without_exception + # Do stuff... + 1 + 1 + + yield + + # Do stuff... + 1 + 1 + end +end + +class ControllerWithFilterClass < PostsController + class YieldingFilter < DefaultFilter + def self.filter(controller) + yield + raise After + end + end + + around_filter YieldingFilter, :only => :raises_after +end + +class ControllerWithFilterInstance < PostsController + class YieldingFilter < DefaultFilter + def filter(controller) + yield + raise After + end + end + + around_filter YieldingFilter.new, :only => :raises_after +end + +class ControllerWithFilterMethod < PostsController + class YieldingFilter < DefaultFilter + def filter(controller) + yield + raise After + end + end + + around_filter YieldingFilter.new.method(:filter), :only => :raises_after +end + +class ControllerWithProcFilter < PostsController + around_filter(:only => :no_raise) do |c,b| + c.assigns['before'] = true + b.call + c.assigns['after'] = true + end +end + +class ControllerWithWrongFilterType < PostsController + around_filter lambda { yield }, :only => :no_raise +end + +class ControllerWithNestedFilters < ControllerWithSymbolAsFilter + around_filter :raise_before, :raise_after, :without_exception, :only => :raises_both +end + +class ControllerWithAllTypesOfFilters < PostsController + before_filter :before + around_filter :around + after_filter :after + around_filter :around_again + + private + def before + @ran_filter ||= [] + @ran_filter << 'before' + end + + def around + @ran_filter << 'around (before yield)' + yield + @ran_filter << 'around (after yield)' + end + + def after + @ran_filter << 'after' + end + + def around_again + @ran_filter << 'around_again (before yield)' + yield + @ran_filter << 'around_again (after yield)' + end +end + +class ControllerWithTwoLessFilters < ControllerWithAllTypesOfFilters + skip_filter :around_again + skip_filter :after +end + +class YieldingAroundFiltersTest < Test::Unit::TestCase + include PostsController::AroundExceptions + + def test_filters_registering + assert_equal 1, ControllerWithFilterMethod.filter_chain.size + assert_equal 1, ControllerWithFilterClass.filter_chain.size + assert_equal 1, ControllerWithFilterInstance.filter_chain.size + assert_equal 3, ControllerWithSymbolAsFilter.filter_chain.size + assert_equal 1, ControllerWithWrongFilterType.filter_chain.size + assert_equal 6, ControllerWithNestedFilters.filter_chain.size + assert_equal 4, ControllerWithAllTypesOfFilters.filter_chain.size + end + + def test_wrong_filter_type + assert_raise(ActionController::ActionControllerError) do + test_process(ControllerWithWrongFilterType,'no_raise') + end + end + + def test_base + controller = PostsController + assert_nothing_raised { test_process(controller,'no_raise') } + assert_nothing_raised { test_process(controller,'raises_before') } + assert_nothing_raised { test_process(controller,'raises_after') } + assert_nothing_raised { test_process(controller,'no_filter') } + end + + def test_with_symbol + controller = ControllerWithSymbolAsFilter + assert_nothing_raised { test_process(controller,'no_raise') } + assert_raise(Before) { test_process(controller,'raises_before') } + assert_raise(After) { test_process(controller,'raises_after') } + assert_nothing_raised { test_process(controller,'no_raise') } + end + + def test_with_class + controller = ControllerWithFilterClass + assert_nothing_raised { test_process(controller,'no_raise') } + assert_raise(After) { test_process(controller,'raises_after') } + end + + def test_with_instance + controller = ControllerWithFilterInstance + assert_nothing_raised { test_process(controller,'no_raise') } + assert_raise(After) { test_process(controller,'raises_after') } + end + + def test_with_method + controller = ControllerWithFilterMethod + assert_nothing_raised { test_process(controller,'no_raise') } + assert_raise(After) { test_process(controller,'raises_after') } + end + + def test_with_proc + controller = test_process(ControllerWithProcFilter,'no_raise') + assert controller.template.assigns['before'] + assert controller.template.assigns['after'] + end + + def test_nested_filters + controller = ControllerWithNestedFilters + assert_nothing_raised do + begin + test_process(controller,'raises_both') + rescue Before, After + end + end + assert_raise Before do + begin + test_process(controller,'raises_both') + rescue After + end + end + end + + def test_filter_order_with_all_filter_types + controller = test_process(ControllerWithAllTypesOfFilters,'no_raise') + assert_equal 'before around (before yield) around_again (before yield) around_again (after yield) around (after yield) after',controller.template.assigns['ran_filter'].join(' ') + end + + def test_filter_order_with_skip_filter_method + controller = test_process(ControllerWithTwoLessFilters,'no_raise') + assert_equal 'before around (before yield) around (after yield)',controller.template.assigns['ran_filter'].join(' ') + end + + def test_first_filter_in_multiple_before_filter_chain_halts + controller = ::FilterTest::TestMultipleFiltersController.new + response = test_process(controller, 'fail_1') + assert_equal ' ', response.body + assert_equal 1, controller.instance_variable_get(:@try) + assert controller.instance_variable_get(:@before_filter_chain_aborted) + end + + def test_second_filter_in_multiple_before_filter_chain_halts + controller = ::FilterTest::TestMultipleFiltersController.new + response = test_process(controller, 'fail_2') + assert_equal ' ', response.body + assert_equal 2, controller.instance_variable_get(:@try) + assert controller.instance_variable_get(:@before_filter_chain_aborted) + end + + def test_last_filter_in_multiple_before_filter_chain_halts + controller = ::FilterTest::TestMultipleFiltersController.new + response = test_process(controller, 'fail_3') + assert_equal ' ', response.body + assert_equal 3, controller.instance_variable_get(:@try) + assert controller.instance_variable_get(:@before_filter_chain_aborted) + end + + protected + def test_process(controller, action = "show") + request = ActionController::TestRequest.new + request.action = action + controller.process(request, ActionController::TestResponse.new) + end +end diff --git a/vendor/rails-2.0.2/actionpack/test/controller/flash_test.rb b/vendor/rails-2.0.2/actionpack/test/controller/flash_test.rb new file mode 100644 index 000000000..4a6f3c9e0 --- /dev/null +++ b/vendor/rails-2.0.2/actionpack/test/controller/flash_test.rb @@ -0,0 +1,146 @@ +require File.dirname(__FILE__) + '/../abstract_unit' + +class FlashTest < Test::Unit::TestCase + class TestController < ActionController::Base + def set_flash + flash["that"] = "hello" + render :inline => "hello" + end + + def set_flash_now + flash.now["that"] = "hello" + flash.now["foo"] ||= "bar" + flash.now["foo"] ||= "err" + @flashy = flash.now["that"] + @flash_copy = {}.update flash + render :inline => "hello" + end + + def attempt_to_use_flash_now + @flash_copy = {}.update flash + @flashy = flash["that"] + render :inline => "hello" + end + + def use_flash + @flash_copy = {}.update flash + @flashy = flash["that"] + render :inline => "hello" + end + + def use_flash_and_keep_it + @flash_copy = {}.update flash + @flashy = flash["that"] + flash.keep + render :inline => "hello" + end + + def use_flash_and_update_it + flash.update("this" => "hello again") + @flash_copy = {}.update flash + render :inline => "hello" + end + + def use_flash_after_reset_session + flash["that"] = "hello" + @flashy_that = flash["that"] + reset_session + @flashy_that_reset = flash["that"] + flash["this"] = "good-bye" + @flashy_this = flash["this"] + render :inline => "hello" + end + + def rescue_action(e) + raise unless ActionController::MissingTemplate === e + end + + # methods for test_sweep_after_halted_filter_chain + before_filter :halt_and_redir, :only => "filter_halting_action" + + def std_action + @flash_copy = {}.update(flash) + end + + def filter_halting_action + @flash_copy = {}.update(flash) + end + + def halt_and_redir + flash["foo"] = "bar" + redirect_to :action => "std_action" + @flash_copy = {}.update(flash) + end + end + + def setup + @request = ActionController::TestRequest.new + @response = ActionController::TestResponse.new + @controller = TestController.new + end + + def test_flash + get :set_flash + + get :use_flash + assert_equal "hello", @response.template.assigns["flash_copy"]["that"] + assert_equal "hello", @response.template.assigns["flashy"] + + get :use_flash + assert_nil @response.template.assigns["flash_copy"]["that"], "On second flash" + end + + def test_keep_flash + get :set_flash + + get :use_flash_and_keep_it + assert_equal "hello", @response.template.assigns["flash_copy"]["that"] + assert_equal "hello", @response.template.assigns["flashy"] + + get :use_flash + assert_equal "hello", @response.template.assigns["flash_copy"]["that"], "On second flash" + + get :use_flash + assert_nil @response.template.assigns["flash_copy"]["that"], "On third flash" + end + + def test_flash_now + get :set_flash_now + assert_equal "hello", @response.template.assigns["flash_copy"]["that"] + assert_equal "bar" , @response.template.assigns["flash_copy"]["foo"] + assert_equal "hello", @response.template.assigns["flashy"] + + get :attempt_to_use_flash_now + assert_nil @response.template.assigns["flash_copy"]["that"] + assert_nil @response.template.assigns["flash_copy"]["foo"] + assert_nil @response.template.assigns["flashy"] + end + + def test_update_flash + get :set_flash + get :use_flash_and_update_it + assert_equal "hello", @response.template.assigns["flash_copy"]["that"] + assert_equal "hello again", @response.template.assigns["flash_copy"]["this"] + get :use_flash + assert_nil @response.template.assigns["flash_copy"]["that"], "On second flash" + assert_equal "hello again", @response.template.assigns["flash_copy"]["this"], "On second flash" + end + + def test_flash_after_reset_session + get :use_flash_after_reset_session + assert_equal "hello", @response.template.assigns["flashy_that"] + assert_equal "good-bye", @response.template.assigns["flashy_this"] + assert_nil @response.template.assigns["flashy_that_reset"] + end + + def test_sweep_after_halted_filter_chain + get :std_action + assert_nil @response.template.assigns["flash_copy"]["foo"] + get :filter_halting_action + assert_equal "bar", @response.template.assigns["flash_copy"]["foo"] + get :std_action # follow redirection + assert_equal "bar", @response.template.assigns["flash_copy"]["foo"] + get :std_action + assert_nil @response.template.assigns["flash_copy"]["foo"] + end +end diff --git a/vendor/rails-2.0.2/actionpack/test/controller/fragment_store_setting_test.rb b/vendor/rails-2.0.2/actionpack/test/controller/fragment_store_setting_test.rb new file mode 100644 index 000000000..3df6fd0be --- /dev/null +++ b/vendor/rails-2.0.2/actionpack/test/controller/fragment_store_setting_test.rb @@ -0,0 +1,47 @@ +require File.dirname(__FILE__) + '/../abstract_unit' + +MemCache = Struct.new(:MemCache, :address) unless Object.const_defined?(:MemCache) + +class FragmentCacheStoreSettingTest < Test::Unit::TestCase + def teardown + ActionController::Base.fragment_cache_store = ActionController::Caching::Fragments::MemoryStore.new + end + + def test_file_fragment_cache_store + ActionController::Base.fragment_cache_store = :file_store, "/path/to/cache/directory" + assert_kind_of( + ActionController::Caching::Fragments::FileStore, + ActionController::Base.fragment_cache_store + ) + assert_equal "/path/to/cache/directory", ActionController::Base.fragment_cache_store.cache_path + end + + def test_drb_fragment_cache_store + ActionController::Base.fragment_cache_store = :drb_store, "druby://localhost:9192" + assert_kind_of( + ActionController::Caching::Fragments::DRbStore, + ActionController::Base.fragment_cache_store + ) + assert_equal "druby://localhost:9192", ActionController::Base.fragment_cache_store.address + end + + if defined? CGI::Session::MemCacheStore + def test_mem_cache_fragment_cache_store + ActionController::Base.fragment_cache_store = :mem_cache_store, "localhost" + assert_kind_of( + ActionController::Caching::Fragments::MemCacheStore, + ActionController::Base.fragment_cache_store + ) + assert_equal %w(localhost), ActionController::Base.fragment_cache_store.addresses + end + end + + def test_object_assigned_fragment_cache_store + ActionController::Base.fragment_cache_store = ActionController::Caching::Fragments::FileStore.new("/path/to/cache/directory") + assert_kind_of( + ActionController::Caching::Fragments::FileStore, + ActionController::Base.fragment_cache_store + ) + assert_equal "/path/to/cache/directory", ActionController::Base.fragment_cache_store.cache_path + end +end diff --git a/vendor/rails-2.0.2/actionpack/test/controller/helper_test.rb b/vendor/rails-2.0.2/actionpack/test/controller/helper_test.rb new file mode 100644 index 000000000..117f73b76 --- /dev/null +++ b/vendor/rails-2.0.2/actionpack/test/controller/helper_test.rb @@ -0,0 +1,206 @@ +require File.dirname(__FILE__) + '/../abstract_unit' + +ActionController::Helpers::HELPERS_DIR.replace File.dirname(__FILE__) + '/../fixtures/helpers' + +class TestController < ActionController::Base + attr_accessor :delegate_attr + def delegate_method() end + def rescue_action(e) raise end +end + +module Fun + class GamesController < ActionController::Base + def render_hello_world + render :inline => "hello: <%= stratego %>" + end + + def rescue_action(e) raise end + end + + class PdfController < ActionController::Base + def test + render :inline => "test: <%= foobar %>" + end + + def rescue_action(e) raise end + end +end + +class ApplicationController < ActionController::Base + helper :all +end + +module LocalAbcHelper + def a() end + def b() end + def c() end +end + +class HelperTest < Test::Unit::TestCase + def setup + # Increment symbol counter. + @symbol = (@@counter ||= 'A0').succ!.dup + + # Generate new controller class. + controller_class_name = "Helper#{@symbol}Controller" + eval("class #{controller_class_name} < TestController; end") + @controller_class = self.class.const_get(controller_class_name) + + # Generate new template class and assign to controller. + template_class_name = "Test#{@symbol}View" + eval("class #{template_class_name} < ActionView::Base; end") + @template_class = self.class.const_get(template_class_name) + @controller_class.template_class = @template_class + + # Set default test helper. + self.test_helper = LocalAbcHelper + end + + def teardown + # Reset template class. + #ActionController::Base.template_class = ActionView::Base + end + + + def test_deprecated_helper + assert_equal expected_helper_methods, missing_methods + assert_nothing_raised { @controller_class.helper TestHelper } + assert_equal [], missing_methods + end + + def test_declare_helper + require 'abc_helper' + self.test_helper = AbcHelper + assert_equal expected_helper_methods, missing_methods + assert_nothing_raised { @controller_class.helper :abc } + assert_equal [], missing_methods + end + + def test_declare_missing_helper + assert_equal expected_helper_methods, missing_methods + assert_raise(MissingSourceFile) { @controller_class.helper :missing } + end + + def test_declare_missing_file_from_helper + require 'broken_helper' + rescue LoadError => e + assert_nil(/\bbroken_helper\b/.match(e.to_s)[1]) + end + + def test_helper_block + assert_nothing_raised { + @controller_class.helper { def block_helper_method; end } + } + assert master_helper_methods.include?('block_helper_method') + end + + def test_helper_block_include + assert_equal expected_helper_methods, missing_methods + assert_nothing_raised { + @controller_class.helper { include TestHelper } + } + assert [], missing_methods + end + + def test_helper_method + assert_nothing_raised { @controller_class.helper_method :delegate_method } + assert master_helper_methods.include?('delegate_method') + end + + def test_helper_attr + assert_nothing_raised { @controller_class.helper_attr :delegate_attr } + assert master_helper_methods.include?('delegate_attr') + assert master_helper_methods.include?('delegate_attr=') + end + + def test_helper_for_nested_controller + request = ActionController::TestRequest.new + response = ActionController::TestResponse.new + request.action = 'render_hello_world' + + assert_equal 'hello: Iz guuut!', Fun::GamesController.process(request, response).body + end + + def test_helper_for_acronym_controller + request = ActionController::TestRequest.new + response = ActionController::TestResponse.new + request.action = 'test' + + assert_equal 'test: baz', Fun::PdfController.process(request, response).body + end + + def test_all_helpers + methods = ApplicationController.master_helper_module.instance_methods.map(&:to_s) + + # abc_helper.rb + assert methods.include?('bare_a') + + # fun/games_helper.rb + assert methods.include?('stratego') + + # fun/pdf_helper.rb + assert methods.include?('foobar') + end + + private + def expected_helper_methods + TestHelper.instance_methods.map(&:to_s) + end + + def master_helper_methods + @controller_class.master_helper_module.instance_methods.map(&:to_s) + end + + def missing_methods + expected_helper_methods - master_helper_methods + end + + def test_helper=(helper_module) + silence_warnings { self.class.const_set('TestHelper', helper_module) } + end +end + + +class IsolatedHelpersTest < Test::Unit::TestCase + class A < ActionController::Base + def index + render :inline => '<%= shout %>' + end + + def rescue_action(e) raise end + end + + class B < A + helper { def shout; 'B' end } + + def index + render :inline => '<%= shout %>' + end + end + + class C < A + helper { def shout; 'C' end } + + def index + render :inline => '<%= shout %>' + end + end + + def setup + @request = ActionController::TestRequest.new + @response = ActionController::TestResponse.new + @request.action = 'index' + end + + def test_helper_in_a + assert_raise(NameError) { A.process(@request, @response) } + end + + def test_helper_in_b + assert_equal 'B', B.process(@request, @response).body + end + + def test_helper_in_c + assert_equal 'C', C.process(@request, @response).body + end +end diff --git a/vendor/rails-2.0.2/actionpack/test/controller/html-scanner/document_test.rb b/vendor/rails-2.0.2/actionpack/test/controller/html-scanner/document_test.rb new file mode 100644 index 000000000..0719883f3 --- /dev/null +++ b/vendor/rails-2.0.2/actionpack/test/controller/html-scanner/document_test.rb @@ -0,0 +1,124 @@ +require File.dirname(__FILE__) + '/../../abstract_unit' +require 'test/unit' + +class DocumentTest < Test::Unit::TestCase + def test_handle_doctype + doc = nil + assert_nothing_raised do + doc = HTML::Document.new <<-HTML.strip + <!DOCTYPE "blah" "blah" "blah"> + <html> + </html> + HTML + end + assert_equal 3, doc.root.children.length + assert_equal %{<!DOCTYPE "blah" "blah" "blah">}, doc.root.children[0].content + assert_match %r{\s+}m, doc.root.children[1].content + assert_equal "html", doc.root.children[2].name + end + + def test_find_img + doc = HTML::Document.new <<-HTML.strip + <html> + <body> + <p><img src="hello.gif"></p> + </body> + </html> + HTML + assert doc.find(:tag=>"img", :attributes=>{"src"=>"hello.gif"}) + end + + def test_find_all + doc = HTML::Document.new <<-HTML.strip + <html> + <body> + <p class="test"><img src="hello.gif"></p> + <div class="foo"> + <p class="test">something</p> + <p>here is <em class="test">more</em></p> + </div> + </body> + </html> + HTML + all = doc.find_all :attributes => { :class => "test" } + assert_equal 3, all.length + assert_equal [ "p", "p", "em" ], all.map { |n| n.name } + end + + def test_find_with_text + doc = HTML::Document.new <<-HTML.strip + <html> + <body> + <p>Some text</p> + </body> + </html> + HTML + assert doc.find(:content => "Some text") + assert doc.find(:tag => "p", :child => { :content => "Some text" }) + assert doc.find(:tag => "p", :child => "Some text") + assert doc.find(:tag => "p", :content => "Some text") + end + + def test_parse_xml + assert_nothing_raised { HTML::Document.new("<tags><tag/></tags>", true, true) } + assert_nothing_raised { HTML::Document.new("<outer><link>something</link></outer>", true, true) } + end + + def test_parse_document + doc = HTML::Document.new(<<-HTML) + <div> + <h2>blah</h2> + <table> + </table> + </div> + HTML + assert_not_nil doc.find(:tag => "div", :children => { :count => 1, :only => { :tag => "table" } }) + end + + def test_tag_nesting_nothing_to_s + doc = HTML::Document.new("<tag></tag>") + assert_equal "<tag></tag>", doc.root.to_s + end + + def test_tag_nesting_space_to_s + doc = HTML::Document.new("<tag> </tag>") + assert_equal "<tag> </tag>", doc.root.to_s + end + + def test_tag_nesting_text_to_s + doc = HTML::Document.new("<tag>text</tag>") + assert_equal "<tag>text</tag>", doc.root.to_s + end + + def test_tag_nesting_tag_to_s + doc = HTML::Document.new("<tag><nested /></tag>") + assert_equal "<tag><nested /></tag>", doc.root.to_s + end + + def test_parse_cdata + doc = HTML::Document.new(<<-HTML) +<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" + "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"> +<html xmlns="http://www.w3.org/1999/xhtml" lang="en" xml:lang="en"> + <head> + <title><![CDATA[<br>]]></title> + </head> + <body> + <p>this document has <br> for a title</p> + </body> +</html> +HTML + + assert_nil doc.find(:tag => "title", :descendant => { :tag => "br" }) + assert doc.find(:tag => "title", :child => "<br>") + end + + def test_find_empty_tag + doc = HTML::Document.new("<div id='map'></div>") + assert_nil doc.find(:tag => "div", :attributes => { :id => "map" }, :content => /./) + assert doc.find(:tag => "div", :attributes => { :id => "map" }, :content => /\A\Z/) + assert doc.find(:tag => "div", :attributes => { :id => "map" }, :content => /^$/) + assert doc.find(:tag => "div", :attributes => { :id => "map" }, :content => "") + assert doc.find(:tag => "div", :attributes => { :id => "map" }, :content => nil) + end +end diff --git a/vendor/rails-2.0.2/actionpack/test/controller/html-scanner/node_test.rb b/vendor/rails-2.0.2/actionpack/test/controller/html-scanner/node_test.rb new file mode 100644 index 000000000..1cf0a4bb6 --- /dev/null +++ b/vendor/rails-2.0.2/actionpack/test/controller/html-scanner/node_test.rb @@ -0,0 +1,69 @@ +require File.dirname(__FILE__) + '/../../abstract_unit' +require 'test/unit' + +class NodeTest < Test::Unit::TestCase + + class MockNode + def initialize(matched, value) + @matched = matched + @value = value + end + + def find(conditions) + @matched && self + end + + def to_s + @value.to_s + end + end + + def setup + @node = HTML::Node.new("parent") + @node.children.concat [MockNode.new(false,1), MockNode.new(true,"two"), MockNode.new(false,:three)] + end + + def test_match + assert !@node.match("foo") + end + + def test_tag + assert !@node.tag? + end + + def test_to_s + assert_equal "1twothree", @node.to_s + end + + def test_find + assert_equal "two", @node.find('blah').to_s + end + + def test_parse_strict + s = "<b foo='hello'' bar='baz'>" + assert_raise(RuntimeError) { HTML::Node.parse(nil,0,0,s) } + end + + def test_parse_relaxed + s = "<b foo='hello'' bar='baz'>" + node = nil + assert_nothing_raised { node = HTML::Node.parse(nil,0,0,s,false) } + assert node.attributes.has_key?("foo") + assert !node.attributes.has_key?("bar") + end + + def test_to_s_with_boolean_attrs + s = "<b foo bar>" + node = HTML::Node.parse(nil,0,0,s) + assert node.attributes.has_key?("foo") + assert node.attributes.has_key?("bar") + assert "<b foo bar>", node.to_s + end + + def test_parse_with_unclosed_tag + s = "<span onmouseover='bang'" + node = nil + assert_nothing_raised { node = HTML::Node.parse(nil,0,0,s,false) } + assert node.attributes.has_key?("onmouseover") + end +end diff --git a/vendor/rails-2.0.2/actionpack/test/controller/html-scanner/sanitizer_test.rb b/vendor/rails-2.0.2/actionpack/test/controller/html-scanner/sanitizer_test.rb new file mode 100644 index 000000000..8fe9bbc5e --- /dev/null +++ b/vendor/rails-2.0.2/actionpack/test/controller/html-scanner/sanitizer_test.rb @@ -0,0 +1,250 @@ +require File.dirname(__FILE__) + '/../../abstract_unit' +require 'test/unit' + +class SanitizerTest < Test::Unit::TestCase + def setup + @sanitizer = nil # used by assert_sanitizer + end + + def test_strip_tags + sanitizer = HTML::FullSanitizer.new + assert_equal("<<<bad html", sanitizer.sanitize("<<<bad html")) + assert_equal("<<", sanitizer.sanitize("<<<bad html>")) + assert_equal("Dont touch me", sanitizer.sanitize("Dont touch me")) + assert_equal("This is a test.", sanitizer.sanitize("<p>This <u>is<u> a <a href='test.html'><strong>test</strong></a>.</p>")) + assert_equal("Weirdos", sanitizer.sanitize("Wei<<a>a onclick='alert(document.cookie);'</a>/>rdos")) + assert_equal("This is a test.", sanitizer.sanitize("This is a test.")) + assert_equal( + %{This is a test.\n\n\nIt no longer contains any HTML.\n}, sanitizer.sanitize( + %{<title>This is <b>a <a href="" target="_blank">test</a></b>.</title>\n\n<!-- it has a comment -->\n\n<p>It no <b>longer <strong>contains <em>any <strike>HTML</strike></em>.</strong></b></p>\n})) + assert_equal "This has a here.", sanitizer.sanitize("This has a <!-- comment --> here.") + [nil, '', ' '].each { |blank| assert_equal blank, sanitizer.sanitize(blank) } + end + + def test_strip_links + sanitizer = HTML::LinkSanitizer.new + assert_equal "Dont touch me", sanitizer.sanitize("Dont touch me") + assert_equal "on my mind\nall day long", sanitizer.sanitize("<a href='almost'>on my mind</a>\n<A href='almost'>all day long</A>") + assert_equal "0wn3d", sanitizer.sanitize("<a href='http://www.rubyonrails.com/'><a href='http://www.rubyonrails.com/' onlclick='steal()'>0wn3d</a></a>") + assert_equal "Magic", sanitizer.sanitize("<a href='http://www.rubyonrails.com/'>Mag<a href='http://www.ruby-lang.org/'>ic") + assert_equal "FrrFox", sanitizer.sanitize("<href onlclick='steal()'>FrrFox</a></href>") + assert_equal "My mind\nall <b>day</b> long", sanitizer.sanitize("<a href='almost'>My mind</a>\n<A href='almost'>all <b>day</b> long</A>") + assert_equal "all <b>day</b> long", sanitizer.sanitize("<<a>a href='hello'>all <b>day</b> long<</A>/a>") + + assert_equal "<a<a", sanitizer.sanitize("<a<a") + end + + def test_sanitize_form + assert_sanitized "<form action=\"/foo/bar\" method=\"post\"><input></form>", '' + end + + def test_sanitize_plaintext + raw = "<plaintext><span>foo</span></plaintext>" + assert_sanitized raw, "<span>foo</span>" + end + + def test_sanitize_script + assert_sanitized "a b c<script language=\"Javascript\">blah blah blah</script>d e f", "a b cd e f" + end + + # fucked + def test_sanitize_js_handlers + raw = %{onthis="do that" <a href="#" onclick="hello" name="foo" onbogus="remove me">hello</a>} + assert_sanitized raw, %{onthis="do that" <a name="foo" href="#">hello</a>} + end + + def test_sanitize_javascript_href + raw = %{href="javascript:bang" <a href="javascript:bang" name="hello">foo</a>, <span href="javascript:bang">bar</span>} + assert_sanitized raw, %{href="javascript:bang" <a name="hello">foo</a>, <span>bar</span>} + end + + def test_sanitize_image_src + raw = %{src="javascript:bang" <img src="javascript:bang" width="5">foo</img>, <span src="javascript:bang">bar</span>} + assert_sanitized raw, %{src="javascript:bang" <img width="5">foo</img>, <span>bar</span>} + end + + HTML::WhiteListSanitizer.allowed_tags.each do |tag_name| + define_method "test_should_allow_#{tag_name}_tag" do + assert_sanitized "start <#{tag_name} title=\"1\" onclick=\"foo\">foo <bad>bar</bad> baz</#{tag_name}> end", %(start <#{tag_name} title="1">foo bar baz</#{tag_name}> end) + end + end + + def test_should_allow_anchors + assert_sanitized %(<a href="foo" onclick="bar"><script>baz</script></a>), %(<a href="foo"></a>) + end + + # RFC 3986, sec 4.2 + def test_allow_colons_in_path_component + assert_sanitized("<a href=\"./this:that\">foo</a>") + end + + %w(src width height alt).each do |img_attr| + define_method "test_should_allow_image_#{img_attr}_attribute" do + assert_sanitized %(<img #{img_attr}="foo" onclick="bar" />), %(<img #{img_attr}="foo" />) + end + end + + def test_should_handle_non_html + assert_sanitized 'abc' + end + + def test_should_handle_blank_text + assert_sanitized nil + assert_sanitized '' + end + + def test_should_allow_custom_tags + text = "<u>foo</u>" + sanitizer = HTML::WhiteListSanitizer.new + assert_equal(text, sanitizer.sanitize(text, :tags => %w(u))) + end + + def test_should_allow_only_custom_tags + text = "<u>foo</u> with <i>bar</i>" + sanitizer = HTML::WhiteListSanitizer.new + assert_equal("<u>foo</u> with bar", sanitizer.sanitize(text, :tags => %w(u))) + end + + def test_should_allow_custom_tags_with_attributes + text = %(<blockquote cite="http://example.com/">foo</blockquote>) + sanitizer = HTML::WhiteListSanitizer.new + assert_equal(text, sanitizer.sanitize(text)) + end + + def test_should_allow_custom_tags_with_custom_attributes + text = %(<blockquote foo="bar">Lorem ipsum</blockquote>) + sanitizer = HTML::WhiteListSanitizer.new + assert_equal(text, sanitizer.sanitize(text, :attributes => ['foo'])) + end + + [%w(img src), %w(a href)].each do |(tag, attr)| + define_method "test_should_strip_#{attr}_attribute_in_#{tag}_with_bad_protocols" do + assert_sanitized %(<#{tag} #{attr}="javascript:bang" title="1">boo</#{tag}>), %(<#{tag} title="1">boo</#{tag}>) + end + end + + def test_should_flag_bad_protocols + sanitizer = HTML::WhiteListSanitizer.new + %w(about chrome data disk hcp help javascript livescript lynxcgi lynxexec ms-help ms-its mhtml mocha opera res resource shell vbscript view-source vnd.ms.radio wysiwyg).each do |proto| + assert sanitizer.send(:contains_bad_protocols?, 'src', "#{proto}://bad") + end + end + + def test_should_accept_good_protocols + sanitizer = HTML::WhiteListSanitizer.new + HTML::WhiteListSanitizer.allowed_protocols.each do |proto| + assert !sanitizer.send(:contains_bad_protocols?, 'src', "#{proto}://good") + end + end + + def test_should_reject_hex_codes_in_protocol + assert_sanitized %(<a href="%6A%61%76%61%73%63%72%69%70%74%3A%61%6C%65%72%74%28%22%58%53%53%22%29">1</a>), "<a>1</a>" + assert @sanitizer.send(:contains_bad_protocols?, 'src', "%6A%61%76%61%73%63%72%69%70%74%3A%61%6C%65%72%74%28%22%58%53%53%22%29") + end + + def test_should_block_script_tag + assert_sanitized %(<SCRIPT\nSRC=http://ha.ckers.org/xss.js></SCRIPT>), "" + end + + [%(<IMG SRC="javascript:alert('XSS');">), + %(<IMG SRC=javascript:alert('XSS')>), + %(<IMG SRC=JaVaScRiPt:alert('XSS')>), + %(<IMG """><SCRIPT>alert("XSS")</SCRIPT>">), + %(<IMG SRC=javascript:alert("XSS")>), + %(<IMG SRC=javascript:alert(String.fromCharCode(88,83,83))>), + %(<IMG SRC=javascript:alert('XSS')>), + %(<IMG SRC=javascript:alert('XSS')>), + %(<IMG SRC=javascript:alert('XSS')>), + %(<IMG SRC="jav\tascript:alert('XSS');">), + %(<IMG SRC="jav	ascript:alert('XSS');">), + %(<IMG SRC="jav
ascript:alert('XSS');">), + %(<IMG SRC="jav
ascript:alert('XSS');">), + %(<IMG SRC="  javascript:alert('XSS');">), + %(<IMG SRC=`javascript:alert("RSnake says, 'XSS'")`>)].each_with_index do |img_hack, i| + define_method "test_should_not_fall_for_xss_image_hack_#{i+1}" do + assert_sanitized img_hack, "<img>" + end + end + + def test_should_sanitize_tag_broken_up_by_null + assert_sanitized %(<SCR\0IPT>alert(\"XSS\")</SCR\0IPT>), "alert(\"XSS\")" + end + + def test_should_sanitize_invalid_script_tag + assert_sanitized %(<SCRIPT/XSS SRC="http://ha.ckers.org/xss.js"></SCRIPT>), "" + end + + def test_should_sanitize_script_tag_with_multiple_open_brackets + assert_sanitized %(<<SCRIPT>alert("XSS");//<</SCRIPT>), "<" + assert_sanitized %(<iframe src=http://ha.ckers.org/scriptlet.html\n<a), %(<a) + end + + def test_should_sanitize_unclosed_script + assert_sanitized %(<SCRIPT SRC=http://ha.ckers.org/xss.js?<B>), "<b>" + end + + def test_should_sanitize_half_open_scripts + assert_sanitized %(<IMG SRC="javascript:alert('XSS')"), "<img>" + end + + def test_should_not_fall_for_ridiculous_hack + img_hack = %(<IMG\nSRC\n=\n"\nj\na\nv\na\ns\nc\nr\ni\np\nt\n:\na\nl\ne\nr\nt\n(\n'\nX\nS\nS\n'\n)\n"\n>) + assert_sanitized img_hack, "<img>" + end + + # fucked + def test_should_sanitize_attributes + assert_sanitized %(<SPAN title="'><script>alert()</script>">blah</SPAN>), %(<span title="'><script>alert()</script>">blah</span>) + end + + def test_should_sanitize_illegal_style_properties + raw = %(display:block; position:absolute; left:0; top:0; width:100%; height:100%; z-index:1; background-color:black; background-image:url(http://www.ragingplatypus.com/i/cam-full.jpg); background-x:center; background-y:center; background-repeat:repeat;) + expected = %(display: block; width: 100%; height: 100%; background-color: black; background-image: ; background-x: center; background-y: center;) + assert_equal expected, sanitize_css(raw) + end + + def test_should_sanitize_xul_style_attributes + raw = %(-moz-binding:url('http://ha.ckers.org/xssmoz.xml#xss')) + assert_equal '', sanitize_css(raw) + end + + def test_should_sanitize_invalid_tag_names + assert_sanitized(%(a b c<script/XSS src="http://ha.ckers.org/xss.js"></script>d e f), "a b cd e f") + end + + def test_should_sanitize_non_alpha_and_non_digit_characters_in_tags + assert_sanitized('<a onclick!#$%&()*~+-_.,:;?@[/|\]^`=alert("XSS")>foo</a>', "<a>foo</a>") + end + + def test_should_sanitize_invalid_tag_names_in_single_tags + assert_sanitized('<img/src="http://ha.ckers.org/xss.js"/>', "<img />") + end + + def test_should_sanitize_img_dynsrc_lowsrc + assert_sanitized(%(<img lowsrc="javascript:alert('XSS')" />), "<img />") + end + + def test_should_sanitize_div_background_image_unicode_encoded + raw = %(background-image:\0075\0072\006C\0028'\006a\0061\0076\0061\0073\0063\0072\0069\0070\0074\003a\0061\006c\0065\0072\0074\0028.1027\0058.1053\0053\0027\0029'\0029) + assert_equal '', sanitize_css(raw) + end + + def test_should_sanitize_div_style_expression + raw = %(width: expression(alert('XSS'));) + assert_equal '', sanitize_css(raw) + end + + def test_should_sanitize_img_vbscript + assert_sanitized %(<img src='vbscript:msgbox("XSS")' />), '<img />' + end + +protected + def assert_sanitized(input, expected = nil) + @sanitizer ||= HTML::WhiteListSanitizer.new + assert_equal expected || input, @sanitizer.sanitize(input) + end + + def sanitize_css(input) + (@sanitizer ||= HTML::WhiteListSanitizer.new).sanitize_css(input) + end +end
\ No newline at end of file diff --git a/vendor/rails-2.0.2/actionpack/test/controller/html-scanner/tag_node_test.rb b/vendor/rails-2.0.2/actionpack/test/controller/html-scanner/tag_node_test.rb new file mode 100644 index 000000000..daeada9b9 --- /dev/null +++ b/vendor/rails-2.0.2/actionpack/test/controller/html-scanner/tag_node_test.rb @@ -0,0 +1,239 @@ +require File.dirname(__FILE__) + '/../../abstract_unit' +require 'test/unit' + +class TagNodeTest < Test::Unit::TestCase + def test_open_without_attributes + node = tag("<tag>") + assert_equal "tag", node.name + assert_equal Hash.new, node.attributes + assert_nil node.closing + end + + def test_open_with_attributes + node = tag("<TAG1 foo=hey_ho x:bar=\"blah blah\" BAZ='blah blah blah' >") + assert_equal "tag1", node.name + assert_equal "hey_ho", node["foo"] + assert_equal "blah blah", node["x:bar"] + assert_equal "blah blah blah", node["baz"] + end + + def test_self_closing_without_attributes + node = tag("<tag/>") + assert_equal "tag", node.name + assert_equal Hash.new, node.attributes + assert_equal :self, node.closing + end + + def test_self_closing_with_attributes + node = tag("<tag a=b/>") + assert_equal "tag", node.name + assert_equal( { "a" => "b" }, node.attributes ) + assert_equal :self, node.closing + end + + def test_closing_without_attributes + node = tag("</tag>") + assert_equal "tag", node.name + assert_nil node.attributes + assert_equal :close, node.closing + end + + def test_bracket_op_when_no_attributes + node = tag("</tag>") + assert_nil node["foo"] + end + + def test_bracket_op_when_attributes + node = tag("<tag a=b/>") + assert_equal "b", node["a"] + end + + def test_attributes_with_escaped_quotes + node = tag("<tag a='b\\'c' b=\"bob \\\"float\\\"\">") + assert_equal "b\\'c", node["a"] + assert_equal "bob \\\"float\\\"", node["b"] + end + + def test_to_s + node = tag("<a b=c d='f' g=\"h 'i'\" />") + assert_equal %(<a b='c' d='f' g='h \\'i\\'' />), node.to_s + end + + def test_tag + assert tag("<tag>").tag? + end + + def test_match_tag_as_string + assert tag("<tag>").match(:tag => "tag") + assert !tag("<tag>").match(:tag => "b") + end + + def test_match_tag_as_regexp + assert tag("<tag>").match(:tag => /t.g/) + assert !tag("<tag>").match(:tag => /t[bqs]g/) + end + + def test_match_attributes_as_string + t = tag("<tag a=something b=else />") + assert t.match(:attributes => {"a" => "something"}) + assert t.match(:attributes => {"b" => "else"}) + end + + def test_match_attributes_as_regexp + t = tag("<tag a=something b=else />") + assert t.match(:attributes => {"a" => /^something$/}) + assert t.match(:attributes => {"b" => /e.*e/}) + assert t.match(:attributes => {"a" => /me..i/, "b" => /.ls.$/}) + end + + def test_match_attributes_as_number + t = tag("<tag a=15 b=3.1415 />") + assert t.match(:attributes => {"a" => 15}) + assert t.match(:attributes => {"b" => 3.1415}) + assert t.match(:attributes => {"a" => 15, "b" => 3.1415}) + end + + def test_match_attributes_exist + t = tag("<tag a=15 b=3.1415 />") + assert t.match(:attributes => {"a" => true}) + assert t.match(:attributes => {"b" => true}) + assert t.match(:attributes => {"a" => true, "b" => true}) + end + + def test_match_attributes_not_exist + t = tag("<tag a=15 b=3.1415 />") + assert t.match(:attributes => {"c" => false}) + assert t.match(:attributes => {"c" => nil}) + assert t.match(:attributes => {"a" => true, "c" => false}) + end + + def test_match_parent_success + t = tag("<tag a=15 b='hello'>", tag("<foo k='value'>")) + assert t.match(:parent => {:tag => "foo", :attributes => {"k" => /v.l/, "j" => false}}) + end + + def test_match_parent_fail + t = tag("<tag a=15 b='hello'>", tag("<foo k='value'>")) + assert !t.match(:parent => {:tag => /kafka/}) + end + + def test_match_child_success + t = tag("<tag x:k='something'>") + tag("<child v=john a=kelly>", t) + tag("<sib m=vaughn v=james>", t) + assert t.match(:child => { :tag => "sib", :attributes => {"v" => /j/}}) + assert t.match(:child => { :attributes => {"a" => "kelly"}}) + end + + def test_match_child_fail + t = tag("<tag x:k='something'>") + tag("<child v=john a=kelly>", t) + tag("<sib m=vaughn v=james>", t) + assert !t.match(:child => { :tag => "sib", :attributes => {"v" => /r/}}) + assert !t.match(:child => { :attributes => {"v" => false}}) + end + + def test_match_ancestor_success + t = tag("<tag x:k='something'>", tag("<parent v=john a=kelly>", tag("<grandparent m=vaughn v=james>"))) + assert t.match(:ancestor => {:tag => "parent", :attributes => {"a" => /ll/}}) + assert t.match(:ancestor => {:attributes => {"m" => "vaughn"}}) + end + + def test_match_ancestor_fail + t = tag("<tag x:k='something'>", tag("<parent v=john a=kelly>", tag("<grandparent m=vaughn v=james>"))) + assert !t.match(:ancestor => {:tag => /^parent/, :attributes => {"v" => /m/}}) + assert !t.match(:ancestor => {:attributes => {"v" => false}}) + end + + def test_match_descendant_success + tag("<grandchild m=vaughn v=james>", tag("<child v=john a=kelly>", t = tag("<tag x:k='something'>"))) + assert t.match(:descendant => {:tag => "child", :attributes => {"a" => /ll/}}) + assert t.match(:descendant => {:attributes => {"m" => "vaughn"}}) + end + + def test_match_descendant_fail + tag("<grandchild m=vaughn v=james>", tag("<child v=john a=kelly>", t = tag("<tag x:k='something'>"))) + assert !t.match(:descendant => {:tag => /^child/, :attributes => {"v" => /m/}}) + assert !t.match(:descendant => {:attributes => {"v" => false}}) + end + + def test_match_child_count + t = tag("<tag x:k='something'>") + tag("hello", t) + tag("<child v=john a=kelly>", t) + tag("<sib m=vaughn v=james>", t) + assert t.match(:children => { :count => 2 }) + assert t.match(:children => { :count => 2..4 }) + assert t.match(:children => { :less_than => 4 }) + assert t.match(:children => { :greater_than => 1 }) + assert !t.match(:children => { :count => 3 }) + end + + def test_conditions_as_strings + t = tag("<tag x:k='something'>") + assert t.match("tag" => "tag") + assert t.match("attributes" => { "x:k" => "something" }) + assert !t.match("tag" => "gat") + assert !t.match("attributes" => { "x:j" => "something" }) + end + + def test_attributes_as_symbols + t = tag("<child v=john a=kelly>") + assert t.match(:attributes => { :v => /oh/ }) + assert t.match(:attributes => { :a => /ll/ }) + end + + def test_match_sibling + t = tag("<tag x:k='something'>") + tag("hello", t) + tag("<span a=b>", t) + tag("world", t) + m = tag("<span k=r>", t) + tag("<span m=l>", t) + + assert m.match(:sibling => {:tag => "span", :attributes => {:a => true}}) + assert m.match(:sibling => {:tag => "span", :attributes => {:m => true}}) + assert !m.match(:sibling => {:tag => "span", :attributes => {:k => true}}) + end + + def test_match_sibling_before + t = tag("<tag x:k='something'>") + tag("hello", t) + tag("<span a=b>", t) + tag("world", t) + m = tag("<span k=r>", t) + tag("<span m=l>", t) + + assert m.match(:before => {:tag => "span", :attributes => {:m => true}}) + assert !m.match(:before => {:tag => "span", :attributes => {:a => true}}) + assert !m.match(:before => {:tag => "span", :attributes => {:k => true}}) + end + + def test_match_sibling_after + t = tag("<tag x:k='something'>") + tag("hello", t) + tag("<span a=b>", t) + tag("world", t) + m = tag("<span k=r>", t) + tag("<span m=l>", t) + + assert m.match(:after => {:tag => "span", :attributes => {:a => true}}) + assert !m.match(:after => {:tag => "span", :attributes => {:m => true}}) + assert !m.match(:after => {:tag => "span", :attributes => {:k => true}}) + end + + def test_to_s + t = tag("<b x='foo'>") + tag("hello", t) + tag("<hr />", t) + assert_equal %(<b x="foo">hello<hr /></b>), t.to_s + end + + private + + def tag(content, parent=nil) + node = HTML::Node.parse(parent,0,0,content) + parent.children << node if parent + node + end +end diff --git a/vendor/rails-2.0.2/actionpack/test/controller/html-scanner/text_node_test.rb b/vendor/rails-2.0.2/actionpack/test/controller/html-scanner/text_node_test.rb new file mode 100644 index 000000000..9853701fd --- /dev/null +++ b/vendor/rails-2.0.2/actionpack/test/controller/html-scanner/text_node_test.rb @@ -0,0 +1,51 @@ +require File.dirname(__FILE__) + '/../../abstract_unit' +require 'test/unit' + +class TextNodeTest < Test::Unit::TestCase + def setup + @node = HTML::Text.new(nil, 0, 0, "hello, howdy, aloha, annyeong") + end + + def test_to_s + assert_equal "hello, howdy, aloha, annyeong", @node.to_s + end + + def test_find_string + assert_equal @node, @node.find("hello, howdy, aloha, annyeong") + assert_equal false, @node.find("bogus") + end + + def test_find_regexp + assert_equal @node, @node.find(/an+y/) + assert_nil @node.find(/b/) + end + + def test_find_hash + assert_equal @node, @node.find(:content => /howdy/) + assert_nil @node.find(:content => /^howdy$/) + assert_equal false, @node.find(:content => "howdy") + end + + def test_find_other + assert_nil @node.find(:hello) + end + + def test_match_string + assert @node.match("hello, howdy, aloha, annyeong") + assert_equal false, @node.match("bogus") + end + + def test_match_regexp + assert_not_nil @node, @node.match(/an+y/) + assert_nil @node.match(/b/) + end + + def test_match_hash + assert_not_nil @node, @node.match(:content => "howdy") + assert_nil @node.match(:content => /^howdy$/) + end + + def test_match_other + assert_nil @node.match(:hello) + end +end
\ No newline at end of file diff --git a/vendor/rails-2.0.2/actionpack/test/controller/html-scanner/tokenizer_test.rb b/vendor/rails-2.0.2/actionpack/test/controller/html-scanner/tokenizer_test.rb new file mode 100644 index 000000000..437136b9a --- /dev/null +++ b/vendor/rails-2.0.2/actionpack/test/controller/html-scanner/tokenizer_test.rb @@ -0,0 +1,125 @@ +require File.dirname(__FILE__) + '/../../abstract_unit' +require 'test/unit' + +class TokenizerTest < Test::Unit::TestCase + + def test_blank + tokenize "" + assert_end + end + + def test_space + tokenize " " + assert_next " " + assert_end + end + + def test_tag_simple_open + tokenize "<tag>" + assert_next "<tag>" + assert_end + end + + def test_tag_simple_self_closing + tokenize "<tag />" + assert_next "<tag />" + assert_end + end + + def test_tag_simple_closing + tokenize "</tag>" + assert_next "</tag>" + end + + def test_tag_with_single_quoted_attribute + tokenize %{<tag a='hello'>x} + assert_next %{<tag a='hello'>} + end + + def test_tag_with_single_quoted_attribute_with_escape + tokenize %{<tag a='hello\\''>x} + assert_next %{<tag a='hello\\''>} + end + + def test_tag_with_double_quoted_attribute + tokenize %{<tag a="hello">x} + assert_next %{<tag a="hello">} + end + + def test_tag_with_double_quoted_attribute_with_escape + tokenize %{<tag a="hello\\"">x} + assert_next %{<tag a="hello\\"">} + end + + def test_tag_with_unquoted_attribute + tokenize %{<tag a=hello>x} + assert_next %{<tag a=hello>} + end + + def test_tag_with_lt_char_in_attribute + tokenize %{<tag a="x < y">x} + assert_next %{<tag a="x < y">} + end + + def test_tag_with_gt_char_in_attribute + tokenize %{<tag a="x > y">x} + assert_next %{<tag a="x > y">} + end + + def test_doctype_tag + tokenize %{<!DOCTYPE "blah" "blah" "blah">\n <html>} + assert_next %{<!DOCTYPE "blah" "blah" "blah">} + assert_next %{\n } + assert_next %{<html>} + end + + def test_cdata_tag + tokenize %{<![CDATA[<br>]]>} + assert_next %{<![CDATA[<br>]]>} + assert_end + end + + def test_less_than_with_space + tokenize %{original < hello > world} + assert_next %{original } + assert_next %{< hello > world} + end + + def test_less_than_without_matching_greater_than + tokenize %{hello <span onmouseover="gotcha"\n<b>foo</b>\nbar</span>} + assert_next %{hello } + assert_next %{<span onmouseover="gotcha"\n} + assert_next %{<b>} + assert_next %{foo} + assert_next %{</b>} + assert_next %{\nbar} + assert_next %{</span>} + assert_end + end + + def test_unterminated_comment + tokenize %{hello <!-- neverending...} + assert_next %{hello } + assert_next %{<!-- neverending...} + assert_end + end + + private + + def tokenize(text) + @tokenizer = HTML::Tokenizer.new(text) + end + + def assert_next(expected, message=nil) + token = @tokenizer.next + assert_equal expected, token, message + end + + def assert_sequence(*expected) + assert_next expected.shift until expected.empty? + end + + def assert_end(message=nil) + assert_nil @tokenizer.next, message + end +end diff --git a/vendor/rails-2.0.2/actionpack/test/controller/http_authentication_test.rb b/vendor/rails-2.0.2/actionpack/test/controller/http_authentication_test.rb new file mode 100644 index 000000000..6f7b31a41 --- /dev/null +++ b/vendor/rails-2.0.2/actionpack/test/controller/http_authentication_test.rb @@ -0,0 +1,54 @@ +require File.dirname(__FILE__) + '/../abstract_unit' + +class HttpBasicAuthenticationTest < Test::Unit::TestCase + include ActionController::HttpAuthentication::Basic + + class DummyController + attr_accessor :headers, :renders, :request + + def initialize + @headers, @renders = {}, [] + @request = ActionController::TestRequest.new + end + + def render(options) + self.renders << options + end + end + + def setup + @controller = DummyController.new + @credentials = ActionController::HttpAuthentication::Basic.encode_credentials("dhh", "secret") + end + + def test_successful_authentication + login = Proc.new { |user_name, password| user_name == "dhh" && password == "secret" } + set_headers + assert authenticate(@controller, &login) + + set_headers '' + assert_nothing_raised do + assert !authenticate(@controller, &login) + end + + set_headers nil + set_headers @credentials, 'REDIRECT_X_HTTP_AUTHORIZATION' + assert authenticate(@controller, &login) + end + + def test_failing_authentication + set_headers + assert !authenticate(@controller) { |user_name, password| user_name == "dhh" && password == "incorrect" } + end + + def test_authentication_request + authentication_request(@controller, "Megaglobalapp") + assert_equal 'Basic realm="Megaglobalapp"', @controller.headers["WWW-Authenticate"] + assert_equal :unauthorized, @controller.renders.first[:status] + end + + private + def set_headers(value = @credentials, name = 'HTTP_AUTHORIZATION') + @controller.request.env[name] = value + end +end diff --git a/vendor/rails-2.0.2/actionpack/test/controller/integration_test.rb b/vendor/rails-2.0.2/actionpack/test/controller/integration_test.rb new file mode 100644 index 000000000..4213bb4af --- /dev/null +++ b/vendor/rails-2.0.2/actionpack/test/controller/integration_test.rb @@ -0,0 +1,255 @@ +require File.dirname(__FILE__) + '/../abstract_unit' + +$:.unshift File.dirname(__FILE__) + '/../../../railties/lib' +require 'action_controller/integration' + +uses_mocha 'integration' do + +# Stub process for testing. +module ActionController + module Integration + class Session + def process(*args) + end + + def generic_url_rewriter + end + end + end +end + +class SessionTest < Test::Unit::TestCase + def setup + @session = ActionController::Integration::Session.new + end + def test_https_bang_works_and_sets_truth_by_default + assert !@session.https? + @session.https! + assert @session.https? + @session.https! false + assert !@session.https? + end + + def test_host! + assert_not_equal "glu.ttono.us", @session.host + @session.host! "rubyonrails.com" + assert_equal "rubyonrails.com", @session.host + end + + def test_follow_redirect_raises_when_no_redirect + @session.stubs(:redirect?).returns(false) + assert_raise(RuntimeError) { @session.follow_redirect! } + end + + def test_follow_redirect_calls_get_and_returns_status + @session.stubs(:redirect?).returns(true) + @session.stubs(:headers).returns({"location" => ["www.google.com"]}) + @session.stubs(:status).returns(200) + @session.expects(:get) + assert_equal 200, @session.follow_redirect! + end + + def test_request_via_redirect_uses_given_method + path = "/somepath"; args = {:id => '1'}; headers = {"X-Test-Header" => "testvalue"} + @session.expects(:put).with(path, args, headers) + @session.stubs(:redirect?).returns(false) + @session.request_via_redirect(:put, path, args, headers) + end + + def test_request_via_redirect_follows_redirects + path = "/somepath"; args = {:id => '1'}; headers = {"X-Test-Header" => "testvalue"} + @session.stubs(:redirect?).returns(true, true, false) + @session.expects(:follow_redirect!).times(2) + @session.request_via_redirect(:get, path, args, headers) + end + + def test_request_via_redirect_returns_status + path = "/somepath"; args = {:id => '1'}; headers = {"X-Test-Header" => "testvalue"} + @session.stubs(:redirect?).returns(false) + @session.stubs(:status).returns(200) + assert_equal 200, @session.request_via_redirect(:get, path, args, headers) + end + + def test_get_via_redirect + path = "/somepath"; args = {:id => '1'}; headers = {"X-Test-Header" => "testvalue" } + @session.expects(:request_via_redirect).with(:get, path, args, headers) + @session.get_via_redirect(path, args, headers) + end + + def test_post_via_redirect + path = "/somepath"; args = {:id => '1'}; headers = {"X-Test-Header" => "testvalue" } + @session.expects(:request_via_redirect).with(:post, path, args, headers) + @session.post_via_redirect(path, args, headers) + end + + def test_put_via_redirect + path = "/somepath"; args = {:id => '1'}; headers = {"X-Test-Header" => "testvalue" } + @session.expects(:request_via_redirect).with(:put, path, args, headers) + @session.put_via_redirect(path, args, headers) + end + + def test_delete_via_redirect + path = "/somepath"; args = {:id => '1'}; headers = {"X-Test-Header" => "testvalue" } + @session.expects(:request_via_redirect).with(:delete, path, args, headers) + @session.delete_via_redirect(path, args, headers) + end + + def test_url_for_with_controller + options = {:action => 'show'} + mock_controller = mock() + mock_controller.expects(:url_for).with(options).returns('/show') + @session.stubs(:controller).returns(mock_controller) + assert_equal '/show', @session.url_for(options) + end + + def test_url_for_without_controller + options = {:action => 'show'} + mock_rewriter = mock() + mock_rewriter.expects(:rewrite).with(options).returns('/show') + @session.stubs(:generic_url_rewriter).returns(mock_rewriter) + @session.stubs(:controller).returns(nil) + assert_equal '/show', @session.url_for(options) + end + + def test_redirect_bool_with_status_in_300s + @session.stubs(:status).returns 301 + assert @session.redirect? + end + + def test_redirect_bool_with_status_in_200s + @session.stubs(:status).returns 200 + assert !@session.redirect? + end + + def test_get + path = "/index"; params = "blah"; headers = {:location => 'blah'} + @session.expects(:process).with(:get,path,params,headers) + @session.get(path,params,headers) + end + + def test_post + path = "/index"; params = "blah"; headers = {:location => 'blah'} + @session.expects(:process).with(:post,path,params,headers) + @session.post(path,params,headers) + end + + def test_put + path = "/index"; params = "blah"; headers = {:location => 'blah'} + @session.expects(:process).with(:put,path,params,headers) + @session.put(path,params,headers) + end + + def test_delete + path = "/index"; params = "blah"; headers = {:location => 'blah'} + @session.expects(:process).with(:delete,path,params,headers) + @session.delete(path,params,headers) + end + + def test_head + path = "/index"; params = "blah"; headers = {:location => 'blah'} + @session.expects(:process).with(:head,path,params,headers) + @session.head(path,params,headers) + end + + def test_xml_http_request_get + path = "/index"; params = "blah"; headers = {:location => 'blah'} + headers_after_xhr = headers.merge( + "X-Requested-With" => "XMLHttpRequest", + "Accept" => "text/javascript, text/html, application/xml, text/xml, */*" + ) + @session.expects(:process).with(:get,path,params,headers_after_xhr) + @session.xml_http_request(:get,path,params,headers) + end + + def test_xml_http_request_post + path = "/index"; params = "blah"; headers = {:location => 'blah'} + headers_after_xhr = headers.merge( + "X-Requested-With" => "XMLHttpRequest", + "Accept" => "text/javascript, text/html, application/xml, text/xml, */*" + ) + @session.expects(:process).with(:post,path,params,headers_after_xhr) + @session.xml_http_request(:post,path,params,headers) + end + + def test_xml_http_request_put + path = "/index"; params = "blah"; headers = {:location => 'blah'} + headers_after_xhr = headers.merge( + "X-Requested-With" => "XMLHttpRequest", + "Accept" => "text/javascript, text/html, application/xml, text/xml, */*" + ) + @session.expects(:process).with(:put,path,params,headers_after_xhr) + @session.xml_http_request(:put,path,params,headers) + end + + def test_xml_http_request_delete + path = "/index"; params = "blah"; headers = {:location => 'blah'} + headers_after_xhr = headers.merge( + "X-Requested-With" => "XMLHttpRequest", + "Accept" => "text/javascript, text/html, application/xml, text/xml, */*" + ) + @session.expects(:process).with(:delete,path,params,headers_after_xhr) + @session.xml_http_request(:delete,path,params,headers) + end + + def test_xml_http_request_head + path = "/index"; params = "blah"; headers = {:location => 'blah'} + headers_after_xhr = headers.merge( + "X-Requested-With" => "XMLHttpRequest", + "Accept" => "text/javascript, text/html, application/xml, text/xml, */*" + ) + @session.expects(:process).with(:head,path,params,headers_after_xhr) + @session.xml_http_request(:head,path,params,headers) + end + + def test_xml_http_request_override_accept + path = "/index"; params = "blah"; headers = {:location => 'blah', "Accept" => "application/xml"} + headers_after_xhr = headers.merge( + "X-Requested-With" => "XMLHttpRequest" + ) + @session.expects(:process).with(:post,path,params,headers_after_xhr) + @session.xml_http_request(:post,path,params,headers) + end +end + +class IntegrationTestTest < Test::Unit::TestCase + + def setup + @test = ::ActionController::IntegrationTest.new(:default_test) + @test.class.stubs(:fixture_table_names).returns([]) + @session = @test.open_session + end + + def test_opens_new_session + @test.class.expects(:fixture_table_names).times(2).returns(['foo']) + + session1 = @test.open_session { |sess| } + session2 = @test.open_session # implicit session + + assert_equal ::ActionController::Integration::Session, session1.class + assert_equal ::ActionController::Integration::Session, session2.class + assert_not_equal session1, session2 + end + +end + +# Tests that integration tests don't call Controller test methods for processing. +# Integration tests have their own setup and teardown. +class IntegrationTestUsesCorrectClass < ActionController::IntegrationTest + + def self.fixture_table_names + [] + end + + def test_integration_methods_called + %w( get post head put delete ).each do |verb| + assert_nothing_raised("'#{verb}' should use integration test methods") { send!(verb, '/') } + end + end + +end + +# TODO +# class MockCGITest < Test::Unit::TestCase +# end + +end # uses_mocha diff --git a/vendor/rails-2.0.2/actionpack/test/controller/layout_test.rb b/vendor/rails-2.0.2/actionpack/test/controller/layout_test.rb new file mode 100644 index 000000000..85cc3a084 --- /dev/null +++ b/vendor/rails-2.0.2/actionpack/test/controller/layout_test.rb @@ -0,0 +1,239 @@ +require File.dirname(__FILE__) + '/../abstract_unit' + +# The view_paths array must be set on Base and not LayoutTest so that LayoutTest's inherited +# method has access to the view_paths array when looking for a layout to automatically assign. +old_load_paths = ActionController::Base.view_paths +ActionController::Base.view_paths = [ File.dirname(__FILE__) + '/../fixtures/layout_tests/' ] + +class LayoutTest < ActionController::Base + def self.controller_path; 'views' end + self.view_paths = ActionController::Base.view_paths.dup +end + +# Restore view_paths to previous value +ActionController::Base.view_paths = old_load_paths + +class ProductController < LayoutTest +end + +class ItemController < LayoutTest +end + +class ThirdPartyTemplateLibraryController < LayoutTest +end + +module ControllerNameSpace +end + +class ControllerNameSpace::NestedController < LayoutTest +end + +class MultipleExtensions < LayoutTest +end + +class MabView + def initialize(view) + end + + def render(text, locals = {}) + text + end +end + +ActionView::Base::register_template_handler :mab, MabView + +class LayoutAutoDiscoveryTest < Test::Unit::TestCase + def setup + @request = ActionController::TestRequest.new + @response = ActionController::TestResponse.new + + @request.host = "www.nextangle.com" + end + + def test_application_layout_is_default_when_no_controller_match + @controller = ProductController.new + get :hello + assert_equal 'layout_test.rhtml hello.rhtml', @response.body + end + + def test_controller_name_layout_name_match + @controller = ItemController.new + get :hello + assert_equal 'item.rhtml hello.rhtml', @response.body + end + + def test_third_party_template_library_auto_discovers_layout + @controller = ThirdPartyTemplateLibraryController.new + get :hello + assert_equal 'layouts/third_party_template_library', @controller.active_layout + assert_equal 'layouts/third_party_template_library', @response.layout + assert_equal 'Mab', @response.body + end + + def test_namespaced_controllers_auto_detect_layouts + @controller = ControllerNameSpace::NestedController.new + get :hello + assert_equal 'layouts/controller_name_space/nested', @controller.active_layout + assert_equal 'controller_name_space/nested.rhtml hello.rhtml', @response.body + end + + def test_namespaced_controllers_auto_detect_layouts + @controller = MultipleExtensions.new + get :hello + assert_equal 'layouts/multiple_extensions', @controller.active_layout + assert_equal 'multiple_extensions.html.erb hello.rhtml', @response.body.strip + end +end + +class ExemptFromLayoutTest < Test::Unit::TestCase + def setup + @controller = LayoutTest.new + @request = ActionController::TestRequest.new + @response = ActionController::TestResponse.new + end + + def test_rjs_exempt_from_layout + assert @controller.send!(:template_exempt_from_layout?, 'test.rjs') + end + + def test_rhtml_and_rxml_not_exempt_from_layout + assert !@controller.send!(:template_exempt_from_layout?, 'test.rhtml') + assert !@controller.send!(:template_exempt_from_layout?, 'test.rxml') + end + + def test_other_extension_not_exempt_from_layout + assert !@controller.send!(:template_exempt_from_layout?, 'test.random') + end + + def test_add_extension_to_exempt_from_layout + ['rpdf', :rpdf].each do |ext| + assert_nothing_raised do + ActionController::Base.exempt_from_layout ext + end + assert @controller.send!(:template_exempt_from_layout?, "test.#{ext}") + end + end + + def test_add_regexp_to_exempt_from_layout + ActionController::Base.exempt_from_layout /\.rdoc/ + assert @controller.send!(:template_exempt_from_layout?, 'test.rdoc') + end + + def test_rhtml_exempt_from_layout_status_should_prevent_layout_render + ActionController::Base.exempt_from_layout :rhtml + + assert @controller.send!(:template_exempt_from_layout?, 'test.rhtml') + assert @controller.send!(:template_exempt_from_layout?, 'hello.rhtml') + + get :hello + assert_equal 'hello.rhtml', @response.body + ActionController::Base.exempt_from_layout.delete(/\.rhtml$/) + end +end + + +class DefaultLayoutController < LayoutTest +end + +class HasOwnLayoutController < LayoutTest + layout 'item' +end + +class SetsLayoutInRenderController < LayoutTest + def hello + render :layout => 'third_party_template_library' + end +end + +class RendersNoLayoutController < LayoutTest + def hello + render :layout => false + end +end + +class LayoutSetInResponseTest < Test::Unit::TestCase + def setup + @request = ActionController::TestRequest.new + @response = ActionController::TestResponse.new + end + + def test_layout_set_when_using_default_layout + @controller = DefaultLayoutController.new + get :hello + assert_equal 'layouts/layout_test', @response.layout + end + + def test_layout_set_when_set_in_controller + @controller = HasOwnLayoutController.new + get :hello + assert_equal 'layouts/item', @response.layout + end + + def test_layout_set_when_using_render + @controller = SetsLayoutInRenderController.new + get :hello + assert_equal 'layouts/third_party_template_library', @response.layout + end + + def test_layout_is_not_set_when_none_rendered + @controller = RendersNoLayoutController.new + get :hello + assert_nil @response.layout + end + + def test_exempt_from_layout_honored_by_render_template + ActionController::Base.exempt_from_layout :rhtml + @controller = RenderWithTemplateOptionController.new + + assert @controller.send(:template_exempt_from_layout?, 'alt/hello.rhtml') + + get :hello + assert_equal "alt/hello.rhtml", @response.body.strip + + ensure + ActionController::Base.exempt_from_layout.delete(/\.rhtml$/) + end +end + +class RenderWithTemplateOptionController < LayoutTest + def hello + render :template => 'alt/hello' + end +end + +class SetsNonExistentLayoutFile < LayoutTest + layout "nofile.rhtml" +end + +class LayoutExceptionRaised < Test::Unit::TestCase + def setup + @request = ActionController::TestRequest.new + @response = ActionController::TestResponse.new + end + + def test_exception_raised_when_layout_file_not_found + @controller = SetsNonExistentLayoutFile.new + get :hello + @response.template.class.module_eval { attr_accessor :exception } + assert_equal ActionController::MissingTemplate, @response.template.exception.class + end +end + +class LayoutStatusIsRendered < LayoutTest + def hello + render :status => 401 + end +end + +class LayoutStatusIsRenderedTest < Test::Unit::TestCase + def setup + @request = ActionController::TestRequest.new + @response = ActionController::TestResponse.new + end + + def test_layout_status_is_rendered + @controller = LayoutStatusIsRendered.new + get :hello + assert_response 401 + end +end diff --git a/vendor/rails-2.0.2/actionpack/test/controller/mime_responds_test.rb b/vendor/rails-2.0.2/actionpack/test/controller/mime_responds_test.rb new file mode 100644 index 000000000..f121dd9f8 --- /dev/null +++ b/vendor/rails-2.0.2/actionpack/test/controller/mime_responds_test.rb @@ -0,0 +1,506 @@ +require File.dirname(__FILE__) + '/../abstract_unit' + +class RespondToController < ActionController::Base + layout :set_layout + + def html_xml_or_rss + respond_to do |type| + type.html { render :text => "HTML" } + type.xml { render :text => "XML" } + type.rss { render :text => "RSS" } + type.all { render :text => "Nothing" } + end + end + + def js_or_html + respond_to do |type| + type.html { render :text => "HTML" } + type.js { render :text => "JS" } + type.all { render :text => "Nothing" } + end + end + + def json_or_yaml + respond_to do |type| + type.json { render :text => "JSON" } + type.yaml { render :text => "YAML" } + end + end + + def html_or_xml + respond_to do |type| + type.html { render :text => "HTML" } + type.xml { render :text => "XML" } + type.all { render :text => "Nothing" } + end + end + + def forced_xml + request.format = :xml + + respond_to do |type| + type.html { render :text => "HTML" } + type.xml { render :text => "XML" } + end + end + + def just_xml + respond_to do |type| + type.xml { render :text => "XML" } + end + end + + def using_defaults + respond_to do |type| + type.html + type.js + type.xml + end + end + + def using_defaults_with_type_list + respond_to(:html, :js, :xml) + end + + def made_for_content_type + respond_to do |type| + type.rss { render :text => "RSS" } + type.atom { render :text => "ATOM" } + type.all { render :text => "Nothing" } + end + end + + def custom_type_handling + respond_to do |type| + type.html { render :text => "HTML" } + type.custom("application/crazy-xml") { render :text => "Crazy XML" } + type.all { render :text => "Nothing" } + end + end + + def custom_constant_handling + Mime::Type.register("text/x-mobile", :mobile) + + respond_to do |type| + type.html { render :text => "HTML" } + type.mobile { render :text => "Mobile" } + end + ensure + Mime.module_eval { remove_const :MOBILE if const_defined?(:MOBILE) } + end + + def custom_constant_handling_without_block + Mime::Type.register("text/x-mobile", :mobile) + + respond_to do |type| + type.html { render :text => "HTML" } + type.mobile + end + + ensure + Mime.module_eval { remove_const :MOBILE if const_defined?(:MOBILE) } + end + + def handle_any + respond_to do |type| + type.html { render :text => "HTML" } + type.any(:js, :xml) { render :text => "Either JS or XML" } + end + end + + def all_types_with_layout + respond_to do |type| + type.html + type.js + end + end + + def iphone_with_html_response_type + Mime::Type.register_alias("text/html", :iphone) + request.format = :iphone if request.env["HTTP_ACCEPT"] == "text/iphone" + + respond_to do |type| + type.html { @type = "Firefox" } + type.iphone { @type = "iPhone" } + end + + ensure + Mime.module_eval { remove_const :IPHONE if const_defined?(:IPHONE) } + end + + def iphone_with_html_response_type_without_layout + Mime::Type.register_alias("text/html", :iphone) + request.format = "iphone" if request.env["HTTP_ACCEPT"] == "text/iphone" + + respond_to do |type| + type.html { @type = "Firefox"; render :action => "iphone_with_html_response_type" } + type.iphone { @type = "iPhone" ; render :action => "iphone_with_html_response_type" } + end + + ensure + Mime.module_eval { remove_const :IPHONE if const_defined?(:IPHONE) } + end + + def rescue_action(e) + raise + end + + protected + def set_layout + if ["all_types_with_layout", "iphone_with_html_response_type"].include?(action_name) + "respond_to/layouts/standard" + elsif action_name == "iphone_with_html_response_type_without_layout" + "respond_to/layouts/missing" + end + end +end + +RespondToController.view_paths = [ File.dirname(__FILE__) + "/../fixtures/" ] + +class MimeControllerTest < Test::Unit::TestCase + def setup + @request = ActionController::TestRequest.new + @response = ActionController::TestResponse.new + + @controller = RespondToController.new + @request.host = "www.example.com" + end + + def test_html + @request.env["HTTP_ACCEPT"] = "text/html" + get :js_or_html + assert_equal 'HTML', @response.body + + get :html_or_xml + assert_equal 'HTML', @response.body + + get :just_xml + assert_response 406 + end + + def test_all + @request.env["HTTP_ACCEPT"] = "*/*" + get :js_or_html + assert_equal 'HTML', @response.body # js is not part of all + + get :html_or_xml + assert_equal 'HTML', @response.body + + get :just_xml + assert_equal 'XML', @response.body + end + + def test_xml + @request.env["HTTP_ACCEPT"] = "application/xml" + get :html_xml_or_rss + assert_equal 'XML', @response.body + end + + def test_js_or_html + @request.env["HTTP_ACCEPT"] = "text/javascript, text/html" + get :js_or_html + assert_equal 'JS', @response.body + + get :html_or_xml + assert_equal 'HTML', @response.body + + get :just_xml + assert_response 406 + end + + def test_json_or_yaml + get :json_or_yaml + assert_equal 'JSON', @response.body + + get :json_or_yaml, :format => 'json' + assert_equal 'JSON', @response.body + + get :json_or_yaml, :format => 'yaml' + assert_equal 'YAML', @response.body + + { 'YAML' => %w(text/yaml), + 'JSON' => %w(application/json text/x-json) + }.each do |body, content_types| + content_types.each do |content_type| + @request.env['HTTP_ACCEPT'] = content_type + get :json_or_yaml + assert_equal body, @response.body + end + end + end + + def test_js_or_anything + @request.env["HTTP_ACCEPT"] = "text/javascript, */*" + get :js_or_html + assert_equal 'JS', @response.body + + get :html_or_xml + assert_equal 'HTML', @response.body + + get :just_xml + assert_equal 'XML', @response.body + end + + def test_using_defaults + @request.env["HTTP_ACCEPT"] = "*/*" + get :using_defaults + assert_equal "text/html", @response.content_type + assert_equal 'Hello world!', @response.body + + @request.env["HTTP_ACCEPT"] = "text/javascript" + get :using_defaults + assert_equal "text/javascript", @response.content_type + assert_equal '$("body").visualEffect("highlight");', @response.body + + @request.env["HTTP_ACCEPT"] = "application/xml" + get :using_defaults + assert_equal "application/xml", @response.content_type + assert_equal "<p>Hello world!</p>\n", @response.body + end + + def test_using_defaults_with_type_list + @request.env["HTTP_ACCEPT"] = "*/*" + get :using_defaults_with_type_list + assert_equal "text/html", @response.content_type + assert_equal 'Hello world!', @response.body + + @request.env["HTTP_ACCEPT"] = "text/javascript" + get :using_defaults_with_type_list + assert_equal "text/javascript", @response.content_type + assert_equal '$("body").visualEffect("highlight");', @response.body + + @request.env["HTTP_ACCEPT"] = "application/xml" + get :using_defaults_with_type_list + assert_equal "application/xml", @response.content_type + assert_equal "<p>Hello world!</p>\n", @response.body + end + + def test_with_atom_content_type + @request.env["CONTENT_TYPE"] = "application/atom+xml" + get :made_for_content_type + assert_equal "ATOM", @response.body + end + + def test_with_rss_content_type + @request.env["CONTENT_TYPE"] = "application/rss+xml" + get :made_for_content_type + assert_equal "RSS", @response.body + end + + def test_synonyms + @request.env["HTTP_ACCEPT"] = "application/javascript" + get :js_or_html + assert_equal 'JS', @response.body + + @request.env["HTTP_ACCEPT"] = "application/x-xml" + get :html_xml_or_rss + assert_equal "XML", @response.body + end + + def test_custom_types + @request.env["HTTP_ACCEPT"] = "application/crazy-xml" + get :custom_type_handling + assert_equal "application/crazy-xml", @response.content_type + assert_equal 'Crazy XML', @response.body + + @request.env["HTTP_ACCEPT"] = "text/html" + get :custom_type_handling + assert_equal "text/html", @response.content_type + assert_equal 'HTML', @response.body + end + + def test_xhtml_alias + @request.env["HTTP_ACCEPT"] = "application/xhtml+xml,application/xml" + get :html_or_xml + assert_equal 'HTML', @response.body + end + + def test_firefox_simulation + @request.env["HTTP_ACCEPT"] = "text/xml,application/xml,application/xhtml+xml,text/html;q=0.9,text/plain;q=0.8,image/png,*/*;q=0.5" + get :html_or_xml + assert_equal 'HTML', @response.body + end + + def test_handle_any + @request.env["HTTP_ACCEPT"] = "*/*" + get :handle_any + assert_equal 'HTML', @response.body + + @request.env["HTTP_ACCEPT"] = "text/javascript" + get :handle_any + assert_equal 'Either JS or XML', @response.body + + @request.env["HTTP_ACCEPT"] = "text/xml" + get :handle_any + assert_equal 'Either JS or XML', @response.body + end + + def test_rjs_type_skips_layout + @request.env["HTTP_ACCEPT"] = "text/javascript" + get :all_types_with_layout + assert_equal 'RJS for all_types_with_layout', @response.body + end + + def test_html_type_with_layout + @request.env["HTTP_ACCEPT"] = "text/html" + get :all_types_with_layout + assert_equal '<html><div id="html">HTML for all_types_with_layout</div></html>', @response.body + end + + def test_xhr + xhr :get, :js_or_html + assert_equal 'JS', @response.body + + xhr :get, :using_defaults + assert_equal '$("body").visualEffect("highlight");', @response.body + end + + def test_custom_constant + get :custom_constant_handling, :format => "mobile" + assert_equal "text/x-mobile", @response.content_type + assert_equal "Mobile", @response.body + end + + def test_custom_constant_handling_without_block + get :custom_constant_handling_without_block, :format => "mobile" + assert_equal "text/x-mobile", @response.content_type + assert_equal "Mobile", @response.body + end + + def test_forced_format + get :html_xml_or_rss + assert_equal "HTML", @response.body + + get :html_xml_or_rss, :format => "html" + assert_equal "HTML", @response.body + + get :html_xml_or_rss, :format => "xml" + assert_equal "XML", @response.body + + get :html_xml_or_rss, :format => "rss" + assert_equal "RSS", @response.body + end + + def test_internally_forced_format + get :forced_xml + assert_equal "XML", @response.body + + get :forced_xml, :format => "html" + assert_equal "XML", @response.body + end + + def test_extension_synonyms + get :html_xml_or_rss, :format => "xhtml" + assert_equal "HTML", @response.body + end + + def test_render_action_for_html + @controller.instance_eval do + def render(*args) + unless args.empty? + @action = args.first[:action] + end + response.body = "#{@action} - #{@template.template_format}" + end + end + + get :using_defaults + assert_equal "using_defaults - html", @response.body + + get :using_defaults, :format => "xml" + assert_equal "using_defaults - xml", @response.body + end + + def test_format_with_custom_response_type + get :iphone_with_html_response_type + assert_equal '<html><div id="html">Hello future from Firefox!</div></html>', @response.body + + get :iphone_with_html_response_type, :format => "iphone" + assert_equal "text/html", @response.content_type + assert_equal '<html><div id="iphone">Hello iPhone future from iPhone!</div></html>', @response.body + end + + def test_format_with_custom_response_type_and_request_headers + @request.env["HTTP_ACCEPT"] = "text/iphone" + get :iphone_with_html_response_type + assert_equal '<html><div id="iphone">Hello iPhone future from iPhone!</div></html>', @response.body + assert_equal "text/html", @response.content_type + end + + def test_format_with_custom_response_type_and_request_headers_with_only_one_layout_present + get :iphone_with_html_response_type_without_layout + assert_equal '<html><div id="html_missing">Hello future from Firefox!</div></html>', @response.body + + @request.env["HTTP_ACCEPT"] = "text/iphone" + assert_raises(ActionController::MissingTemplate) { get :iphone_with_html_response_type_without_layout } + end +end + +class AbstractPostController < ActionController::Base + class << self + def view_paths + [ File.dirname(__FILE__) + "/../fixtures/post_test/" ] + end + end +end + +# For testing layouts which are set automatically +class PostController < AbstractPostController + around_filter :with_iphone + + def index + respond_to do |type| + type.html + type.iphone + end + end + + protected + def with_iphone + Mime::Type.register_alias("text/html", :iphone) + request.format = "iphone" if request.env["HTTP_ACCEPT"] == "text/iphone" + yield + ensure + Mime.module_eval { remove_const :IPHONE if const_defined?(:IPHONE) } + end +end + +class SuperPostController < PostController + def index + respond_to do |type| + type.html + type.iphone + end + end +end + +class MimeControllerLayoutsTest < Test::Unit::TestCase + def setup + @request = ActionController::TestRequest.new + @response = ActionController::TestResponse.new + + @controller = PostController.new + @request.host = "www.example.com" + end + + def test_missing_layout_renders_properly + get :index + assert_equal '<html><div id="html">Hello Firefox</div></html>', @response.body + + @request.env["HTTP_ACCEPT"] = "text/iphone" + get :index + assert_equal 'Hello iPhone', @response.body + end + + def test_format_with_inherited_layouts + @controller = SuperPostController.new + + get :index + assert_equal 'Super Firefox', @response.body + + @request.env["HTTP_ACCEPT"] = "text/iphone" + get :index + assert_equal '<html><div id="super_iphone">Super iPhone</div></html>', @response.body + end +end + diff --git a/vendor/rails-2.0.2/actionpack/test/controller/mime_type_test.rb b/vendor/rails-2.0.2/actionpack/test/controller/mime_type_test.rb new file mode 100644 index 000000000..d4aea3c01 --- /dev/null +++ b/vendor/rails-2.0.2/actionpack/test/controller/mime_type_test.rb @@ -0,0 +1,55 @@ +require File.dirname(__FILE__) + '/../abstract_unit' + +class MimeTypeTest < Test::Unit::TestCase + Mime::Type.register "image/png", :png + Mime::Type.register "application/pdf", :pdf + + def test_parse_single + Mime::LOOKUP.keys.each do |mime_type| + assert_equal [Mime::Type.lookup(mime_type)], Mime::Type.parse(mime_type) + end + end + + def test_parse_without_q + accept = "text/xml,application/xhtml+xml,text/yaml,application/xml,text/html,image/png,text/plain,application/pdf,*/*" + expect = [Mime::HTML, Mime::XML, Mime::YAML, Mime::PNG, Mime::TEXT, Mime::PDF, Mime::ALL] + assert_equal expect, Mime::Type.parse(accept) + end + + def test_parse_with_q + accept = "text/xml,application/xhtml+xml,text/yaml; q=0.3,application/xml,text/html; q=0.8,image/png,text/plain; q=0.5,application/pdf,*/*; q=0.2" + expect = [Mime::HTML, Mime::XML, Mime::PNG, Mime::PDF, Mime::TEXT, Mime::YAML, Mime::ALL] + assert_equal expect, Mime::Type.parse(accept) + end + + # Accept header send with user HTTP_USER_AGENT: Sunrise/0.42j (Windows XP) + def test_parse_crappy_broken_acceptlines + accept = "text/xml,application/xml,application/xhtml+xml,text/html;q=0.9,text/plain;q=0.8,image/*,,*/*;q=0.5" + expect = [Mime::HTML, Mime::XML, "image/*", Mime::TEXT, Mime::ALL] + assert_equal expect, Mime::Type.parse(accept).collect { |c| c.to_s } + end + + def test_custom_type + Mime::Type.register("image/gif", :gif) + assert_nothing_raised do + Mime::GIF + assert_equal Mime::GIF, Mime::SET.last + end + ensure + Mime.module_eval { remove_const :GIF if const_defined?(:GIF) } + end + + def test_type_convenience_methods + types = [:html, :xml, :png, :pdf, :yaml, :url_encoded_form] + types.each do |type| + mime = Mime.const_get(type.to_s.upcase) + assert mime.send("#{type}?"), "Mime::#{type.to_s.upcase} is not #{type}?" + (types - [type]).each { |t| assert !mime.send("#{t}?"), "Mime::#{t.to_s.upcase} is #{t}?" } + end + end + + def test_mime_all_is_html + assert Mime::ALL.all?, "Mime::ALL is not all?" + assert Mime::ALL.html?, "Mime::ALL is not html?" + end +end diff --git a/vendor/rails-2.0.2/actionpack/test/controller/new_render_test.rb b/vendor/rails-2.0.2/actionpack/test/controller/new_render_test.rb new file mode 100644 index 000000000..3168daeae --- /dev/null +++ b/vendor/rails-2.0.2/actionpack/test/controller/new_render_test.rb @@ -0,0 +1,832 @@ +require File.dirname(__FILE__) + '/../abstract_unit' +require File.dirname(__FILE__) + '/fake_models' + +class CustomersController < ActionController::Base +end + +module Fun + class GamesController < ActionController::Base + def hello_world + end + end +end + +module NewRenderTestHelper + def rjs_helper_method_from_module + page.visual_effect :highlight + end +end + +class NewRenderTestController < ActionController::Base + layout :determine_layout + + def self.controller_name; "test"; end + def self.controller_path; "test"; end + + def hello_world + end + + def render_hello_world + render :template => "test/hello_world" + end + + def render_hello_world_from_variable + @person = "david" + render :text => "hello #{@person}" + end + + def render_action_hello_world + render :action => "hello_world" + end + + def render_action_hello_world_as_symbol + render :action => :hello_world + end + + def render_text_hello_world + render :text => "hello world" + end + + def render_text_hello_world_with_layout + @variable_for_layout = ", I'm here!" + render :text => "hello world", :layout => true + end + + def hello_world_with_layout_false + render :layout => false + end + + def render_custom_code + render :text => "hello world", :status => "404 Moved" + end + + def render_file_with_instance_variables + @secret = 'in the sauce' + path = File.join(File.dirname(__FILE__), '../fixtures/test/render_file_with_ivar.erb') + render :file => path + end + + def render_file_with_locals + path = File.join(File.dirname(__FILE__), '../fixtures/test/render_file_with_locals.erb') + render :file => path, :locals => {:secret => 'in the sauce'} + end + + def render_file_not_using_full_path + @secret = 'in the sauce' + render :file => 'test/render_file_with_ivar', :use_full_path => true + end + + def render_file_not_using_full_path_with_relative_path + @secret = 'in the sauce' + render :file => 'test/../test/render_file_with_ivar', :use_full_path => true + end + + def render_file_not_using_full_path_with_dot_in_path + @secret = 'in the sauce' + render :file => 'test/dot.directory/render_file_with_ivar', :use_full_path => true + end + + def render_xml_hello + @name = "David" + render :template => "test/hello" + end + + def greeting + # let's just rely on the template + end + + def layout_test + render :action => "hello_world" + end + + def layout_test_with_different_layout + render :action => "hello_world", :layout => "standard" + end + + def rendering_without_layout + render :action => "hello_world", :layout => false + end + + def layout_overriding_layout + render :action => "hello_world", :layout => "standard" + end + + def rendering_nothing_on_layout + render :nothing => true + end + + def builder_layout_test + render :action => "hello" + end + + def partials_list + @test_unchanged = 'hello' + @customers = [ Customer.new("david"), Customer.new("mary") ] + render :action => "list" + end + + def partial_only + render :partial => true + end + + def partial_only_with_layout + render :partial => "partial_only", :layout => true + end + + def partial_with_locals + render :partial => "customer", :locals => { :customer => Customer.new("david") } + end + + def partial_collection + render :partial => "customer", :collection => [ Customer.new("david"), Customer.new("mary") ] + end + + def partial_collection_with_locals + render :partial => "customer_greeting", :collection => [ Customer.new("david"), Customer.new("mary") ], :locals => { :greeting => "Bonjour" } + end + + def empty_partial_collection + render :partial => "customer", :collection => [] + end + + def partial_with_hash_object + render :partial => "hash_object", :object => {:first_name => "Sam"} + end + + def partial_hash_collection + render :partial => "hash_object", :collection => [ {:first_name => "Pratik"}, {:first_name => "Amy"} ] + end + + def partial_hash_collection_with_locals + render :partial => "hash_greeting", :collection => [ {:first_name => "Pratik"}, {:first_name => "Amy"} ], :locals => { :greeting => "Hola" } + end + + def partial_with_implicit_local_assignment + @customer = Customer.new("Marcel") + render :partial => "customer" + end + + def missing_partial + render :partial => 'thisFileIsntHere' + end + + def hello_in_a_string + @customers = [ Customer.new("david"), Customer.new("mary") ] + render :text => "How's there? " << render_to_string(:template => "test/list") + end + + def render_to_string_with_assigns + @before = "i'm before the render" + render_to_string :text => "foo" + @after = "i'm after the render" + render :action => "test/hello_world" + end + + def render_to_string_with_partial + @partial_only = render_to_string :partial => "partial_only" + @partial_with_locals = render_to_string :partial => "customer", :locals => { :customer => Customer.new("david") } + render :action => "test/hello_world" + end + + def render_to_string_with_exception + render_to_string :file => "exception that will not be caught - this will certainly not work", :use_full_path => true + end + + def render_to_string_with_caught_exception + @before = "i'm before the render" + begin + render_to_string :file => "exception that will be caught- hope my future instance vars still work!", :use_full_path => true + rescue + end + @after = "i'm after the render" + render :action => "test/hello_world" + end + + def accessing_params_in_template + render :inline => "Hello: <%= params[:name] %>" + end + + def accessing_params_in_template_with_layout + render :layout => nil, :inline => "Hello: <%= params[:name] %>" + end + + def render_with_explicit_template + render :template => "test/hello_world" + end + + def double_render + render :text => "hello" + render :text => "world" + end + + def double_redirect + redirect_to :action => "double_render" + redirect_to :action => "double_render" + end + + def render_and_redirect + render :text => "hello" + redirect_to :action => "double_render" + end + + def render_to_string_and_render + @stuff = render_to_string :text => "here is some cached stuff" + render :text => "Hi web users! #{@stuff}" + end + + def rendering_with_conflicting_local_vars + @name = "David" + def @template.name() nil end + render :action => "potential_conflicts" + end + + def hello_world_from_rxml_using_action + render :action => "hello_world_from_rxml.builder" + end + + def hello_world_from_rxml_using_template + render :template => "test/hello_world_from_rxml.builder" + end + + def head_with_location_header + head :location => "/foo" + end + + def head_with_symbolic_status + head :status => params[:status].intern + end + + def head_with_integer_status + head :status => params[:status].to_i + end + + def head_with_string_status + head :status => params[:status] + end + + def head_with_custom_header + head :x_custom_header => "something" + end + + def head_with_status_code_first + head :forbidden, :x_custom_header => "something" + end + + def render_with_location + render :xml => "<hello/>", :location => "http://example.com", :status => 201 + end + + def render_with_object_location + customer = Customer.new("Some guy", 1) + render :xml => "<customer/>", :location => customer_url(customer), :status => :created + end + + def render_with_to_xml + to_xmlable = Class.new do + def to_xml + "<i-am-xml/>" + end + end.new + + render :xml => to_xmlable + end + + helper NewRenderTestHelper + helper do + def rjs_helper_method(value) + page.visual_effect :highlight, value + end + end + + def enum_rjs_test + render :update do |page| + page.select('.product').each do |value| + page.rjs_helper_method_from_module + page.rjs_helper_method(value) + page.sortable(value, :url => { :action => "order" }) + page.draggable(value) + end + end + end + + def delete_with_js + @project_id = 4 + end + + def render_js_with_explicit_template + @project_id = 4 + render :template => 'test/delete_with_js' + end + + def render_js_with_explicit_action_template + @project_id = 4 + render :action => 'delete_with_js' + end + + def update_page + render :update do |page| + page.replace_html 'balance', '$37,000,000.00' + page.visual_effect :highlight, 'balance' + end + end + + def update_page_with_instance_variables + @money = '$37,000,000.00' + @div_id = 'balance' + render :update do |page| + page.replace_html @div_id, @money + page.visual_effect :highlight, @div_id + end + end + + def action_talk_to_layout + # Action template sets variable that's picked up by layout + end + + def render_text_with_assigns + @hello = "world" + render :text => "foo" + end + + def yield_content_for + render :action => "content_for", :layout => "yield" + end + + def render_content_type_from_body + response.content_type = Mime::RSS + render :text => "hello world!" + end + + def render_call_to_partial_with_layout + render :action => "calling_partial_with_layout" + end + + def render_using_layout_around_block + render :action => "using_layout_around_block" + end + + def rescue_action(e) raise end + + private + def determine_layout + case action_name + when "hello_world", "layout_test", "rendering_without_layout", + "rendering_nothing_on_layout", "render_text_hello_world", + "render_text_hello_world_with_layout", + "hello_world_with_layout_false", + "partial_only", "partial_only_with_layout", + "accessing_params_in_template", + "accessing_params_in_template_with_layout", + "render_with_explicit_template", + "render_js_with_explicit_template", + "render_js_with_explicit_action_template", + "delete_with_js", "update_page", "update_page_with_instance_variables" + + "layouts/standard" + when "builder_layout_test" + "layouts/builder" + when "action_talk_to_layout", "layout_overriding_layout" + "layouts/talk_from_action" + end + end +end + +NewRenderTestController.view_paths = [ File.dirname(__FILE__) + "/../fixtures/" ] +Fun::GamesController.view_paths = [ File.dirname(__FILE__) + "/../fixtures/" ] + +class NewRenderTest < Test::Unit::TestCase + def setup + @controller = NewRenderTestController.new + + # enable a logger so that (e.g.) the benchmarking stuff runs, so we can get + # a more accurate simulation of what happens in "real life". + @controller.logger = Logger.new(nil) + + @request = ActionController::TestRequest.new + @response = ActionController::TestResponse.new + + @request.host = "www.nextangle.com" + end + + def test_simple_show + get :hello_world + assert_response :success + assert_template "test/hello_world" + assert_equal "<html>Hello world!</html>", @response.body + end + + def test_do_with_render + get :render_hello_world + assert_template "test/hello_world" + end + + def test_do_with_render_from_variable + get :render_hello_world_from_variable + assert_equal "hello david", @response.body + end + + def test_do_with_render_action + get :render_action_hello_world + assert_template "test/hello_world" + end + + def test_do_with_render_action_as_symbol + get :render_action_hello_world_as_symbol + assert_template "test/hello_world" + end + + def test_do_with_render_text + get :render_text_hello_world + assert_equal "hello world", @response.body + end + + def test_do_with_render_text_and_layout + get :render_text_hello_world_with_layout + assert_equal "<html>hello world, I'm here!</html>", @response.body + end + + def test_do_with_render_action_and_layout_false + get :hello_world_with_layout_false + assert_equal 'Hello world!', @response.body + end + + def test_do_with_render_custom_code + get :render_custom_code + assert_response :missing + end + + def test_render_file_with_instance_variables + get :render_file_with_instance_variables + assert_equal "The secret is in the sauce\n", @response.body + end + + def test_render_file_not_using_full_path + get :render_file_not_using_full_path + assert_equal "The secret is in the sauce\n", @response.body + end + + def test_render_file_not_using_full_path_with_relative_path + get :render_file_not_using_full_path_with_relative_path + assert_equal "The secret is in the sauce\n", @response.body + end + + def test_render_file_not_using_full_path_with_dot_in_path + get :render_file_not_using_full_path_with_dot_in_path + assert_equal "The secret is in the sauce\n", @response.body + end + + def test_render_file_with_locals + get :render_file_with_locals + assert_equal "The secret is in the sauce\n", @response.body + end + + def test_attempt_to_access_object_method + assert_raises(ActionController::UnknownAction, "No action responded to [clone]") { get :clone } + end + + def test_private_methods + assert_raises(ActionController::UnknownAction, "No action responded to [determine_layout]") { get :determine_layout } + end + + def test_access_to_request_in_view + view_internals_old_value = ActionController::Base.view_controller_internals + + ActionController::Base.view_controller_internals = false + ActionController::Base.protected_variables_cache = nil + + get :hello_world + assert !assigns.include?('request'), 'request should not be in assigns' + + ActionController::Base.view_controller_internals = true + ActionController::Base.protected_variables_cache = nil + + get :hello_world + assert !assigns.include?('request'), 'request should not be in assigns' + assert_kind_of ActionController::AbstractRequest, assigns['_request'] + assert_kind_of ActionController::AbstractRequest, @response.template.request + + ensure + ActionController::Base.view_controller_internals = view_internals_old_value + ActionController::Base.protected_variables_cache = nil + end + + def test_render_xml + get :render_xml_hello + assert_equal "<html>\n <p>Hello David</p>\n<p>This is grand!</p>\n</html>\n", @response.body + end + + def test_enum_rjs_test + get :enum_rjs_test + assert_equal <<-EOS.strip, @response.body +$$(".product").each(function(value, index) { +new Effect.Highlight(element,{}); +new Effect.Highlight(value,{}); +Sortable.create(value, {onUpdate:function(){new Ajax.Request('/test/order', {asynchronous:true, evalScripts:true, parameters:Sortable.serialize(value)})}}); +new Draggable(value, {}); +}); +EOS + end + + def test_render_xml_with_default + get :greeting + assert_equal "<p>This is grand!</p>\n", @response.body + end + + def test_render_rjs_with_default + get :delete_with_js + assert_equal %!Element.remove("person");\nnew Effect.Highlight(\"project-4\",{});!, @response.body + end + + def test_render_rjs_template_explicitly + get :render_js_with_explicit_template + assert_equal %!Element.remove("person");\nnew Effect.Highlight(\"project-4\",{});!, @response.body + end + + def test_rendering_rjs_action_explicitly + get :render_js_with_explicit_action_template + assert_equal %!Element.remove("person");\nnew Effect.Highlight(\"project-4\",{});!, @response.body + end + + def test_layout_rendering + get :layout_test + assert_equal "<html>Hello world!</html>", @response.body + end + + def test_layout_test_with_different_layout + get :layout_test_with_different_layout + assert_equal "<html>Hello world!</html>", @response.body + end + + def test_rendering_without_layout + get :rendering_without_layout + assert_equal "Hello world!", @response.body + end + + def test_layout_overriding_layout + get :layout_overriding_layout + assert_no_match %r{<title>}, @response.body + end + + def test_rendering_nothing_on_layout + get :rendering_nothing_on_layout + assert_equal " ", @response.body + end + + def test_render_xml_with_layouts + get :builder_layout_test + assert_equal "<wrapper>\n<html>\n <p>Hello </p>\n<p>This is grand!</p>\n</html>\n</wrapper>\n", @response.body + end + + def test_partial_only + get :partial_only + assert_equal "only partial", @response.body + end + + def test_partial_only_with_layout + get :partial_only_with_layout + assert_equal "<html>only partial</html>", @response.body + end + + def test_render_to_string + assert_not_deprecated { get :hello_in_a_string } + assert_equal "How's there? goodbyeHello: davidHello: marygoodbye\n", @response.body + end + + def test_render_to_string_doesnt_break_assigns + get :render_to_string_with_assigns + assert_equal "i'm before the render", assigns(:before) + assert_equal "i'm after the render", assigns(:after) + end + + def test_render_to_string_partial + get :render_to_string_with_partial + assert_equal "only partial", assigns(:partial_only) + assert_equal "Hello: david", assigns(:partial_with_locals) + end + + def test_bad_render_to_string_still_throws_exception + assert_raises(ActionController::MissingTemplate) { get :render_to_string_with_exception } + end + + def test_render_to_string_that_throws_caught_exception_doesnt_break_assigns + assert_nothing_raised { get :render_to_string_with_caught_exception } + assert_equal "i'm before the render", assigns(:before) + assert_equal "i'm after the render", assigns(:after) + end + + def test_nested_rendering + get :hello_world + assert_equal "Living in a nested world", Fun::GamesController.process(@request, @response).body + end + + def test_accessing_params_in_template + get :accessing_params_in_template, :name => "David" + assert_equal "Hello: David", @response.body + end + + def test_accessing_params_in_template_with_layout + get :accessing_params_in_template_with_layout, :name => "David" + assert_equal "<html>Hello: David</html>", @response.body + end + + def test_render_with_explicit_template + get :render_with_explicit_template + assert_response :success + end + + def test_double_render + assert_raises(ActionController::DoubleRenderError) { get :double_render } + end + + def test_double_redirect + assert_raises(ActionController::DoubleRenderError) { get :double_redirect } + end + + def test_render_and_redirect + assert_raises(ActionController::DoubleRenderError) { get :render_and_redirect } + end + + # specify the one exception to double render rule - render_to_string followed by render + def test_render_to_string_and_render + get :render_to_string_and_render + assert_equal("Hi web users! here is some cached stuff", @response.body) + end + + def test_rendering_with_conflicting_local_vars + get :rendering_with_conflicting_local_vars + assert_equal("First: David\nSecond: Stephan\nThird: David\nFourth: David\nFifth: ", @response.body) + end + + def test_action_talk_to_layout + get :action_talk_to_layout + assert_equal "<title>Talking to the layout</title>\nAction was here!", @response.body + end + + def test_partials_list + get :partials_list + assert_equal "goodbyeHello: davidHello: marygoodbye\n", @response.body + end + + def test_partial_with_locals + get :partial_with_locals + assert_equal "Hello: david", @response.body + end + + def test_partial_collection + get :partial_collection + assert_equal "Hello: davidHello: mary", @response.body + end + + def test_partial_collection_with_locals + get :partial_collection_with_locals + assert_equal "Bonjour: davidBonjour: mary", @response.body + end + + def test_empty_partial_collection + get :empty_partial_collection + assert_equal " ", @response.body + end + + def test_partial_with_hash_object + get :partial_with_hash_object + assert_equal "Sam\nmaS\n", @response.body + end + + def test_hash_partial_collection + get :partial_hash_collection + assert_equal "Pratik\nkitarP\nAmy\nymA\n", @response.body + end + + def test_partial_hash_collection_with_locals + get :partial_hash_collection_with_locals + assert_equal "Hola: PratikHola: Amy", @response.body + end + + def test_partial_with_implicit_local_assignment + get :partial_with_implicit_local_assignment + assert_equal "Hello: Marcel", @response.body + end + + def test_render_missing_partial_template + assert_raises(ActionView::ActionViewError) do + get :missing_partial + end + end + + def test_render_text_with_assigns + get :render_text_with_assigns + assert_equal "world", assigns["hello"] + end + + def test_update_page + get :update_page + assert_template nil + assert_equal 'text/javascript; charset=utf-8', @response.headers['type'] + assert_equal 2, @response.body.split($/).length + end + + def test_update_page_with_instance_variables + get :update_page_with_instance_variables + assert_template nil + assert_equal 'text/javascript; charset=utf-8', @response.headers['type'] + assert_match /balance/, @response.body + assert_match /\$37/, @response.body + end + + def test_yield_content_for + assert_not_deprecated { get :yield_content_for } + assert_equal "<title>Putting stuff in the title!</title>\n\nGreat stuff!\n", @response.body + end + + + def test_overwritting_rendering_relative_file_with_extension + get :hello_world_from_rxml_using_template + assert_equal "<html>\n <p>Hello</p>\n</html>\n", @response.body + + get :hello_world_from_rxml_using_action + assert_equal "<html>\n <p>Hello</p>\n</html>\n", @response.body + end + + + def test_head_with_location_header + get :head_with_location_header + assert @response.body.blank? + assert_equal "/foo", @response.headers["Location"] + assert_response :ok + end + + def test_head_with_custom_header + get :head_with_custom_header + assert @response.body.blank? + assert_equal "something", @response.headers["X-Custom-Header"] + assert_response :ok + end + + def test_head_with_symbolic_status + get :head_with_symbolic_status, :status => "ok" + assert_equal "200 OK", @response.headers["Status"] + assert_response :ok + + get :head_with_symbolic_status, :status => "not_found" + assert_equal "404 Not Found", @response.headers["Status"] + assert_response :not_found + + ActionController::StatusCodes::SYMBOL_TO_STATUS_CODE.each do |status, code| + get :head_with_symbolic_status, :status => status.to_s + assert_equal code, @response.response_code + assert_response status + end + end + + def test_head_with_integer_status + ActionController::StatusCodes::STATUS_CODES.each do |code, message| + get :head_with_integer_status, :status => code.to_s + assert_equal message, @response.message + end + end + + def test_head_with_string_status + get :head_with_string_status, :status => "404 Eat Dirt" + assert_equal 404, @response.response_code + assert_equal "Eat Dirt", @response.message + assert_response :not_found + end + + def test_head_with_status_code_first + get :head_with_status_code_first + assert_equal 403, @response.response_code + assert_equal "Forbidden", @response.message + assert_equal "something", @response.headers["X-Custom-Header"] + assert_response :forbidden + end + + def test_rendering_with_location_should_set_header + get :render_with_location + assert_equal "http://example.com", @response.headers["Location"] + end + + def test_rendering_xml_should_call_to_xml_if_possible + get :render_with_to_xml + assert_equal "<i-am-xml/>", @response.body + end + + def test_rendering_with_object_location_should_set_header_with_url_for + ActionController::Routing::Routes.draw do |map| + map.resources :customers + map.connect ':controller/:action/:id' + end + + get :render_with_object_location + assert_equal "http://www.nextangle.com/customers/1", @response.headers["Location"] + end + + def test_render_call_to_partial_with_layout + get :render_call_to_partial_with_layout + assert_equal "Before (David)\nInside from partial (David)\nAfter", @response.body + end + + def test_using_layout_around_block + get :using_layout_around_block + assert_equal "Before (David)\nInside from block\nAfter", @response.body + end +end diff --git a/vendor/rails-2.0.2/actionpack/test/controller/polymorphic_routes_test.rb b/vendor/rails-2.0.2/actionpack/test/controller/polymorphic_routes_test.rb new file mode 100644 index 000000000..3e72063e9 --- /dev/null +++ b/vendor/rails-2.0.2/actionpack/test/controller/polymorphic_routes_test.rb @@ -0,0 +1,98 @@ +require File.dirname(__FILE__) + '/../abstract_unit' + +class Article + attr_reader :id + def save; @id = 1 end + def new_record?; @id.nil? end + def name + @id.nil? ? 'new post' : "post ##{@id}" + end +end + +class Comment + attr_reader :id + def post_id; 1 end + def save; @id = 1 end + def new_record?; @id.nil? end + def name + @id.nil? ? 'new comment' : "comment ##{@id}" + end +end + +class Comment::Nested < Comment; end + +class Test::Unit::TestCase + protected + def articles_url + 'http://www.example.com/articles' + end + alias_method :new_article_url, :articles_url + + def article_url(article) + "http://www.example.com/articles/#{article.id}" + end + + def article_comments_url(article) + "http://www.example.com/articles/#{article.id}/comments" + end + + def article_comment_url(article, comment) + "http://www.example.com/articles/#{article.id}/comments/#{comment.id}" + end + + def admin_articles_url + "http://www.example.com/admin/articles" + end + alias_method :new_admin_article_url, :admin_articles_url + + def admin_article_url(article) + "http://www.example.com/admin/articles/#{article.id}" + end + + def admin_article_comments_url(article) + "http://www.example.com/admin/articles/#{article.id}/comments" + end + + def admin_article_comment_url(article, comment) + "http://www.example.com/admin/test/articles/#{article.id}/comments/#{comment.id}" + end +end + + +class PolymorphicRoutesTest < Test::Unit::TestCase + include ActionController::PolymorphicRoutes + + def setup + @article = Article.new + @comment = Comment.new + end + + def test_with_record + assert_equal(articles_url, polymorphic_url(@article, :action => 'new')) + assert_equal(articles_url, polymorphic_url(@article)) + @article.save + assert_equal(article_url(@article), polymorphic_url(@article)) + end + + # TODO: Needs to be updated to correctly know about whether the object is in a hash or not + def xtest_with_hash + @article.save + assert_equal(article_url(@article), polymorphic_url(:id => @article)) + end + + def test_with_array + assert_equal(article_comments_url(@article), polymorphic_url([@article, @comment])) + @comment.save + assert_equal(article_comment_url(@article, @comment), polymorphic_url([@article, @comment])) + end + + def test_with_array_and_namespace + assert_equal(admin_articles_url, polymorphic_url([:admin, @article], :action => 'new')) + assert_equal(admin_articles_url, polymorphic_url([:admin, @article])) + @article.save + assert_equal(admin_article_url(@article), polymorphic_url([:admin, @article])) + assert_equal(admin_article_comments_url(@article), polymorphic_url([:admin, @article, @comment])) + @comment.save + assert_equal(admin_article_comment_url(@article, @comment), polymorphic_url([:admin, @article, @comment])) + end +end diff --git a/vendor/rails-2.0.2/actionpack/test/controller/record_identifier_test.rb b/vendor/rails-2.0.2/actionpack/test/controller/record_identifier_test.rb new file mode 100644 index 000000000..86d196cfd --- /dev/null +++ b/vendor/rails-2.0.2/actionpack/test/controller/record_identifier_test.rb @@ -0,0 +1,103 @@ +require File.dirname(__FILE__) + '/../abstract_unit' + +class Comment + attr_reader :id + def save; @id = 1 end + def new_record?; @id.nil? end + def name + @id.nil? ? 'new comment' : "comment ##{@id}" + end +end + +class Comment::Nested < Comment; end + +class Test::Unit::TestCase + protected + def comments_url + 'http://www.example.com/comments' + end + + def comment_url(comment) + "http://www.example.com/comments/#{comment.id}" + end +end + + +class RecordIdentifierTest < Test::Unit::TestCase + include ActionController::RecordIdentifier + + def setup + @klass = Comment + @record = @klass.new + @singular = 'comment' + @plural = 'comments' + end + + def test_dom_id_with_new_record + assert_equal "new_#{@singular}", dom_id(@record) + end + + def test_dom_id_with_new_record_and_prefix + assert_equal "custom_prefix_#{@singular}", dom_id(@record, :custom_prefix) + end + + def test_dom_id_with_saved_record + @record.save + assert_equal "#{@singular}_1", dom_id(@record) + end + + def test_dom_id_with_prefix + @record.save + assert_equal "edit_#{@singular}_1", dom_id(@record, :edit) + end + + def test_partial_path + expected = "#{@plural}/#{@singular}" + assert_equal expected, partial_path(@record) + assert_equal expected, partial_path(Comment) + end + + def test_dom_class + assert_equal @singular, dom_class(@record) + end + + def test_dom_class_with_prefix + assert_equal "custom_prefix_#{@singular}", dom_class(@record, :custom_prefix) + end + + def test_singular_class_name + assert_equal @singular, singular_class_name(@record) + end + + def test_singular_class_name_for_class + assert_equal @singular, singular_class_name(@klass) + end + + def test_plural_class_name + assert_equal @plural, plural_class_name(@record) + end + + def test_plural_class_name_for_class + assert_equal @plural, plural_class_name(@klass) + end + + private + def method_missing(method, *args) + RecordIdentifier.send(method, *args) + end +end + +class NestedRecordIdentifierTest < RecordIdentifierTest + def setup + @klass = Comment::Nested + @record = @klass.new + @singular = 'comment_nested' + @plural = 'comment_nesteds' + end + + def test_partial_path + expected = "comment/nesteds/nested" + assert_equal expected, partial_path(@record) + assert_equal expected, partial_path(Comment::Nested) + end +end
\ No newline at end of file diff --git a/vendor/rails-2.0.2/actionpack/test/controller/redirect_test.rb b/vendor/rails-2.0.2/actionpack/test/controller/redirect_test.rb new file mode 100755 index 000000000..4a3b8254a --- /dev/null +++ b/vendor/rails-2.0.2/actionpack/test/controller/redirect_test.rb @@ -0,0 +1,258 @@ +require File.dirname(__FILE__) + '/../abstract_unit' + +class WorkshopsController < ActionController::Base +end + +class Workshop + attr_accessor :id, :new_record + + def initialize(id, new_record) + @id, @new_record = id, new_record + end + + def new_record? + @new_record + end + + def to_s + id.to_s + end +end + +class RedirectController < ActionController::Base + def simple_redirect + redirect_to :action => "hello_world" + end + + def redirect_with_status + redirect_to({:action => "hello_world", :status => 301}) + end + + def redirect_with_status_hash + redirect_to({:action => "hello_world"}, {:status => 301}) + end + + def url_redirect_with_status + redirect_to("http://www.example.com", :status => :moved_permanently) + end + + def url_redirect_with_status_hash + redirect_to("http://www.example.com", {:status => 301}) + end + + def relative_url_redirect_with_status + redirect_to("/things/stuff", :status => :found) + end + + def relative_url_redirect_with_status_hash + redirect_to("/things/stuff", {:status => 301}) + end + + def redirect_to_back_with_status + redirect_to :back, :status => 307 + end + + def host_redirect + redirect_to :action => "other_host", :only_path => false, :host => 'other.test.host' + end + + def module_redirect + redirect_to :controller => 'module_test/module_redirect', :action => "hello_world" + end + + def redirect_with_assigns + @hello = "world" + redirect_to :action => "hello_world" + end + + def redirect_to_back + redirect_to :back + end + + def redirect_to_existing_record + redirect_to Workshop.new(5, false) + end + + def redirect_to_new_record + redirect_to Workshop.new(5, true) + end + + def rescue_errors(e) raise e end + + def rescue_action(e) raise end + + protected + def dashbord_url(id, message) + url_for :action => "dashboard", :params => { "id" => id, "message" => message } + end +end + +class RedirectTest < Test::Unit::TestCase + def setup + @controller = RedirectController.new + @request = ActionController::TestRequest.new + @response = ActionController::TestResponse.new + end + + def test_simple_redirect + get :simple_redirect + assert_response :redirect + assert_equal "http://test.host/redirect/hello_world", redirect_to_url + end + + def test_redirect_with_no_status + get :simple_redirect + assert_response 302 + assert_equal "http://test.host/redirect/hello_world", redirect_to_url + end + + def test_redirect_with_status + get :redirect_with_status + assert_response 301 + assert_equal "http://test.host/redirect/hello_world", redirect_to_url + end + + def test_redirect_with_status_hash + get :redirect_with_status_hash + assert_response 301 + assert_equal "http://test.host/redirect/hello_world", redirect_to_url + end + + def test_url_redirect_with_status + get :url_redirect_with_status + assert_response 301 + assert_equal "http://www.example.com", redirect_to_url + end + + def test_url_redirect_with_status_hash + get :url_redirect_with_status_hash + assert_response 301 + assert_equal "http://www.example.com", redirect_to_url + end + + + def test_relative_url_redirect_with_status + get :relative_url_redirect_with_status + assert_response 302 + assert_equal "http://test.host/things/stuff", redirect_to_url + end + + def test_relative_url_redirect_with_status_hash + get :relative_url_redirect_with_status_hash + assert_response 301 + assert_equal "http://test.host/things/stuff", redirect_to_url + end + + def test_redirect_to_back_with_status + @request.env["HTTP_REFERER"] = "http://www.example.com/coming/from" + get :redirect_to_back_with_status + assert_response 307 + assert_equal "http://www.example.com/coming/from", redirect_to_url + end + + def test_simple_redirect_using_options + get :host_redirect + assert_response :redirect + assert_redirected_to :action => "other_host", :only_path => false, :host => 'other.test.host' + end + + def test_redirect_error_with_pretty_diff + get :host_redirect + assert_response :redirect + begin + assert_redirected_to :action => "other_host", :only_path => true + rescue Test::Unit::AssertionFailedError => err + expected_msg, redirection_msg, diff_msg = err.message.scan(/<\{[^\}]+\}>/).collect { |s| s[2..-3] } + assert_match %r("only_path"=>false), redirection_msg + assert_match %r("host"=>"other.test.host"), redirection_msg + assert_match %r("action"=>"other_host"), redirection_msg + assert_match %r("only_path"=>false), diff_msg + assert_match %r("host"=>"other.test.host"), diff_msg + end + end + + def test_module_redirect + get :module_redirect + assert_response :redirect + assert_redirected_to "http://test.host/module_test/module_redirect/hello_world" + end + + def test_module_redirect_using_options + get :module_redirect + assert_response :redirect + assert_redirected_to :controller => 'module_test/module_redirect', :action => 'hello_world' + end + + def test_redirect_with_assigns + get :redirect_with_assigns + assert_response :redirect + assert_equal "world", assigns["hello"] + end + + def test_redirect_to_back + @request.env["HTTP_REFERER"] = "http://www.example.com/coming/from" + get :redirect_to_back + assert_response :redirect + assert_equal "http://www.example.com/coming/from", redirect_to_url + end + + def test_redirect_to_back_with_no_referer + assert_raises(ActionController::RedirectBackError) { + @request.env["HTTP_REFERER"] = nil + get :redirect_to_back + } + end + + def test_redirect_to_record + ActionController::Routing::Routes.draw do |map| + map.resources :workshops + map.connect ':controller/:action/:id' + end + + get :redirect_to_existing_record + assert_equal "http://test.host/workshops/5", redirect_to_url + + get :redirect_to_new_record + assert_equal "http://test.host/workshops", redirect_to_url + end +end + +module ModuleTest + class ModuleRedirectController < ::RedirectController + def module_redirect + redirect_to :controller => '/redirect', :action => "hello_world" + end + end + + class ModuleRedirectTest < Test::Unit::TestCase + def setup + @controller = ModuleRedirectController.new + @request = ActionController::TestRequest.new + @response = ActionController::TestResponse.new + end + + def test_simple_redirect + get :simple_redirect + assert_response :redirect + assert_equal "http://test.host/module_test/module_redirect/hello_world", redirect_to_url + end + + def test_simple_redirect_using_options + get :host_redirect + assert_response :redirect + assert_redirected_to :action => "other_host", :only_path => false, :host => 'other.test.host' + end + + def test_module_redirect + get :module_redirect + assert_response :redirect + assert_equal "http://test.host/redirect/hello_world", redirect_to_url + end + + def test_module_redirect_using_options + get :module_redirect + assert_response :redirect + assert_redirected_to :controller => 'redirect', :action => "hello_world" + end + end +end diff --git a/vendor/rails-2.0.2/actionpack/test/controller/render_test.rb b/vendor/rails-2.0.2/actionpack/test/controller/render_test.rb new file mode 100644 index 000000000..2827d7b71 --- /dev/null +++ b/vendor/rails-2.0.2/actionpack/test/controller/render_test.rb @@ -0,0 +1,464 @@ +require File.dirname(__FILE__) + '/../abstract_unit' +require File.dirname(__FILE__) + '/fake_models' + +module Fun + class GamesController < ActionController::Base + def hello_world + end + end +end + + +# FIXME: crashes Ruby 1.9 +class TestController < ActionController::Base + layout :determine_layout + + def hello_world + end + + def render_hello_world + render :template => "test/hello_world" + end + + def render_hello_world_from_variable + @person = "david" + render :text => "hello #{@person}" + end + + def render_action_hello_world + render :action => "hello_world" + end + + def render_action_hello_world_with_symbol + render :action => :hello_world + end + + def render_text_hello_world + render :text => "hello world" + end + + def render_json_hello_world + render :json => {:hello => 'world'}.to_json + end + + def render_json_hello_world_with_callback + render :json => {:hello => 'world'}.to_json, :callback => 'alert' + end + + def render_json_with_custom_content_type + render :json => {:hello => 'world'}.to_json, :content_type => 'text/javascript' + end + + def render_symbol_json + render :json => {:hello => 'world'}.to_json + end + + def render_custom_code + render :text => "hello world", :status => 404 + end + + def render_nothing_with_appendix + render :text => "appended" + end + + def render_invalid_args + render("test/hello") + end + + def render_xml_hello + @name = "David" + render :template => "test/hello" + end + + def render_xml_with_custom_content_type + render :xml => "<blah/>", :content_type => "application/atomsvc+xml" + end + + def heading + head :ok + end + + def greeting + # let's just rely on the template + end + + def layout_test + render :action => "hello_world" + end + + def builder_layout_test + render :action => "hello" + end + + def builder_partial_test + render :action => "hello_world_container" + end + + def partials_list + @test_unchanged = 'hello' + @customers = [ Customer.new("david"), Customer.new("mary") ] + render :action => "list" + end + + def partial_only + render :partial => true + end + + def hello_in_a_string + @customers = [ Customer.new("david"), Customer.new("mary") ] + render :text => "How's there? " + render_to_string(:template => "test/list") + end + + def accessing_params_in_template + render :inline => "Hello: <%= params[:name] %>" + end + + def accessing_local_assigns_in_inline_template + name = params[:local_name] + render :inline => "<%= 'Goodbye, ' + local_name %>", + :locals => { :local_name => name } + end + + def accessing_local_assigns_in_inline_template_with_string_keys + name = params[:local_name] + ActionView::Base.local_assigns_support_string_keys = true + render :inline => "<%= 'Goodbye, ' + local_name %>", + :locals => { "local_name" => name } + ActionView::Base.local_assigns_support_string_keys = false + end + + def formatted_html_erb + end + + def formatted_xml_erb + end + + def render_to_string_test + @foo = render_to_string :inline => "this is a test" + end + + def partial + render :partial => 'partial' + end + + def partial_dot_html + render :partial => 'partial.html.erb' + end + + def partial_as_rjs + render :update do |page| + page.replace :foo, :partial => 'partial' + end + end + + def respond_to_partial_as_rjs + respond_to do |format| + format.js do + render :update do |page| + page.replace :foo, :partial => 'partial' + end + end + end + end + + def default_render + if @alternate_default_render + @alternate_default_render.call + else + render + end + end + + def render_alternate_default + # For this test, the method "default_render" is overridden: + @alternate_default_render = lambda { + render :update do |page| + page.replace :foo, :partial => 'partial' + end + } + end + + def rescue_action(e) raise end + + private + def determine_layout + case action_name + when "layout_test"; "layouts/standard" + when "builder_layout_test"; "layouts/builder" + when "render_symbol_json"; "layouts/standard" # to make sure layouts don't interfere + end + end +end + +TestController.view_paths = [ File.dirname(__FILE__) + "/../fixtures/" ] +Fun::GamesController.view_paths = [ File.dirname(__FILE__) + "/../fixtures/" ] + +class RenderTest < Test::Unit::TestCase + def setup + @request = ActionController::TestRequest.new + @response = ActionController::TestResponse.new + @controller = TestController.new + + @request.host = "www.nextangle.com" + end + + def test_simple_show + get :hello_world + assert_response 200 + assert_template "test/hello_world" + end + + def test_render + get :render_hello_world + assert_template "test/hello_world" + end + + def test_render_from_variable + get :render_hello_world_from_variable + assert_equal "hello david", @response.body + end + + def test_render_action + get :render_action_hello_world + assert_template "test/hello_world" + end + + def test_render_action_with_symbol + get :render_action_hello_world_with_symbol + assert_template "test/hello_world" + end + + def test_render_text + get :render_text_hello_world + assert_equal "hello world", @response.body + end + + def test_render_json + get :render_json_hello_world + assert_equal '{"hello": "world"}', @response.body + assert_equal 'application/json', @response.content_type + end + + def test_render_json_with_callback + get :render_json_hello_world_with_callback + assert_equal 'alert({"hello": "world"})', @response.body + assert_equal 'application/json', @response.content_type + end + + def test_render_json_with_custom_content_type + get :render_json_with_custom_content_type + assert_equal '{"hello": "world"}', @response.body + assert_equal 'text/javascript', @response.content_type + end + + def test_render_symbol_json + get :render_symbol_json + assert_equal '{"hello": "world"}', @response.body + assert_equal 'application/json', @response.content_type + end + + def test_render_custom_code + get :render_custom_code + assert_response 404 + assert_equal 'hello world', @response.body + end + + def test_render_nothing_with_appendix + get :render_nothing_with_appendix + assert_response 200 + assert_equal 'appended', @response.body + end + + def test_attempt_to_render_with_invalid_arguments + assert_raises(ActionController::RenderError) { get :render_invalid_args } + end + + def test_attempt_to_access_object_method + assert_raises(ActionController::UnknownAction, "No action responded to [clone]") { get :clone } + end + + def test_private_methods + assert_raises(ActionController::UnknownAction, "No action responded to [determine_layout]") { get :determine_layout } + end + + def test_render_xml + get :render_xml_hello + assert_equal "<html>\n <p>Hello David</p>\n<p>This is grand!</p>\n</html>\n", @response.body + assert_equal "application/xml", @response.content_type + end + + def test_render_xml_with_default + get :greeting + assert_equal "<p>This is grand!</p>\n", @response.body + end + + def test_render_xml_with_partial + get :builder_partial_test + assert_equal "<test>\n <hello/>\n</test>\n", @response.body + end + + def test_layout_rendering + get :layout_test + assert_equal "<html>Hello world!</html>", @response.body + end + + def test_render_xml_with_layouts + get :builder_layout_test + assert_equal "<wrapper>\n<html>\n <p>Hello </p>\n<p>This is grand!</p>\n</html>\n</wrapper>\n", @response.body + end + + # def test_partials_list + # get :partials_list + # assert_equal "goodbyeHello: davidHello: marygoodbye\n", process_request.body + # end + + def test_partial_only + get :partial_only + assert_equal "only partial", @response.body + end + + def test_render_to_string + get :hello_in_a_string + assert_equal "How's there? goodbyeHello: davidHello: marygoodbye\n", @response.body + end + + def test_render_to_string_resets_assigns + get :render_to_string_test + assert_equal "The value of foo is: ::this is a test::\n", @response.body + end + + def test_nested_rendering + @controller = Fun::GamesController.new + get :hello_world + assert_equal "Living in a nested world", @response.body + end + + def test_accessing_params_in_template + get :accessing_params_in_template, :name => "David" + assert_equal "Hello: David", @response.body + end + + def test_accessing_local_assigns_in_inline_template + get :accessing_local_assigns_in_inline_template, :local_name => "Local David" + assert_equal "Goodbye, Local David", @response.body + end + + def test_accessing_local_assigns_in_inline_template_with_string_keys + get :accessing_local_assigns_in_inline_template_with_string_keys, :local_name => "Local David" + assert_equal "Goodbye, Local David", @response.body + end + + def test_render_200_should_set_etag + get :render_hello_world_from_variable + assert_equal etag_for("hello david"), @response.headers['ETag'] + assert_equal "private, max-age=0, must-revalidate", @response.headers['Cache-Control'] + end + + def test_render_against_etag_request_should_304_when_match + @request.headers["HTTP_IF_NONE_MATCH"] = etag_for("hello david") + get :render_hello_world_from_variable + assert_equal "304 Not Modified", @response.headers['Status'] + assert @response.body.empty? + end + + def test_render_against_etag_request_should_200_when_no_match + @request.headers["HTTP_IF_NONE_MATCH"] = etag_for("hello somewhere else") + get :render_hello_world_from_variable + assert_equal "200 OK", @response.headers['Status'] + assert !@response.body.empty? + end + + def test_render_with_etag + get :render_hello_world_from_variable + expected_etag = etag_for('hello david') + assert_equal expected_etag, @response.headers['ETag'] + + @request.headers["HTTP_IF_NONE_MATCH"] = expected_etag + get :render_hello_world_from_variable + assert_equal "304 Not Modified", @response.headers['Status'] + + @request.headers["HTTP_IF_NONE_MATCH"] = "\"diftag\"" + get :render_hello_world_from_variable + assert_equal "200 OK", @response.headers['Status'] + end + + def render_with_404_shouldnt_have_etag + get :render_custom_code + assert_nil @response.headers['ETag'] + end + + def test_etag_should_not_be_changed_when_already_set + expected_etag = etag_for("hello somewhere else") + @response.headers["ETag"] = expected_etag + get :render_hello_world_from_variable + assert_equal expected_etag, @response.headers['ETag'] + end + + def test_etag_should_govern_renders_with_layouts_too + get :builder_layout_test + assert_equal "<wrapper>\n<html>\n <p>Hello </p>\n<p>This is grand!</p>\n</html>\n</wrapper>\n", @response.body + assert_equal etag_for("<wrapper>\n<html>\n <p>Hello </p>\n<p>This is grand!</p>\n</html>\n</wrapper>\n"), @response.headers['ETag'] + end + + def test_should_render_formatted_template + get :formatted_html_erb + assert_equal 'formatted html erb', @response.body + end + + def test_should_render_formatted_xml_erb_template + get :formatted_xml_erb, :format => :xml + assert_equal '<test>passed formatted xml erb</test>', @response.body + end + + def test_should_render_formatted_html_erb_template + get :formatted_xml_erb + assert_equal '<test>passed formatted html erb</test>', @response.body + end + + def test_should_render_formatted_html_erb_template_with_faulty_accepts_header + @request.env["HTTP_ACCEPT"] = "image/gif, image/x-xbitmap, image/jpeg, image/pjpeg, appliction/x-shockwave-flash, */*" + get :formatted_xml_erb + assert_equal '<test>passed formatted html erb</test>', @response.body + end + + def test_should_render_html_formatted_partial + get :partial + assert_equal 'partial html', @response.body + end + + def test_should_render_html_partial_with_dot + get :partial_dot_html + assert_equal 'partial html', @response.body + end + + def test_should_render_html_formatted_partial_with_rjs + xhr :get, :partial_as_rjs + assert_equal %(Element.replace("foo", "partial html");), @response.body + end + + def test_should_render_html_formatted_partial_with_rjs_and_js_format + xhr :get, :respond_to_partial_as_rjs + assert_equal %(Element.replace("foo", "partial html");), @response.body + end + + def test_should_render_js_partial + xhr :get, :partial, :format => 'js' + assert_equal 'partial js', @response.body + end + + def test_should_render_with_alternate_default_render + xhr :get, :render_alternate_default + assert_equal %(Element.replace("foo", "partial html");), @response.body + end + + def test_should_render_xml_but_keep_custom_content_type + get :render_xml_with_custom_content_type + assert_equal "application/atomsvc+xml", @response.content_type + end + + protected + + def etag_for(text) + %("#{Digest::MD5.hexdigest(text)}") + end +end diff --git a/vendor/rails-2.0.2/actionpack/test/controller/request_forgery_protection_test.rb b/vendor/rails-2.0.2/actionpack/test/controller/request_forgery_protection_test.rb new file mode 100644 index 000000000..616ff4f21 --- /dev/null +++ b/vendor/rails-2.0.2/actionpack/test/controller/request_forgery_protection_test.rb @@ -0,0 +1,217 @@ +require File.dirname(__FILE__) + '/../abstract_unit' +require 'digest/sha1' + +ActionController::Routing::Routes.draw do |map| + map.connect ':controller/:action/:id' +end + +# simulates cookie session store +class FakeSessionDbMan + def self.generate_digest(data) + Digest::SHA1.hexdigest("secure") + end +end + +# common controller actions +module RequestForgeryProtectionActions + def index + render :inline => "<%= form_tag('/') {} %>" + end + + def show_button + render :inline => "<%= button_to('New', '/') {} %>" + end + + def unsafe + render :text => 'pwn' + end + + def rescue_action(e) raise e end +end + +# sample controllers +class RequestForgeryProtectionController < ActionController::Base + include RequestForgeryProtectionActions + protect_from_forgery :only => :index, :secret => 'abc' +end + +class RequestForgeryProtectionWithoutSecretController < ActionController::Base + include RequestForgeryProtectionActions + protect_from_forgery +end + +# no token is given, assume the cookie store is used +class CsrfCookieMonsterController < ActionController::Base + include RequestForgeryProtectionActions + protect_from_forgery :only => :index +end + +class FreeCookieController < CsrfCookieMonsterController + self.allow_forgery_protection = false + + def index + render :inline => "<%= form_tag('/') {} %>" + end + + def show_button + render :inline => "<%= button_to('New', '/') {} %>" + end +end + +# common test methods + +module RequestForgeryProtectionTests + def teardown + ActionController::Base.request_forgery_protection_token = nil + end + + def test_should_render_form_with_token_tag + get :index + assert_select 'form>div>input[name=?][value=?]', 'authenticity_token', @token + end + + def test_should_render_button_to_with_token_tag + get :show_button + assert_select 'form>div>input[name=?][value=?]', 'authenticity_token', @token + end + + def test_should_allow_get + get :index + assert_response :success + end + + def test_should_allow_post_without_token_on_unsafe_action + post :unsafe + assert_response :success + end + + def test_should_not_allow_post_without_token + assert_raises(ActionController::InvalidAuthenticityToken) { post :index } + end + + def test_should_not_allow_put_without_token + assert_raises(ActionController::InvalidAuthenticityToken) { put :index } + end + + def test_should_not_allow_delete_without_token + assert_raises(ActionController::InvalidAuthenticityToken) { delete :index } + end + + def test_should_not_allow_xhr_post_without_token + assert_raises(ActionController::InvalidAuthenticityToken) { xhr :post, :index } + end + + def test_should_not_allow_xhr_put_without_token + assert_raises(ActionController::InvalidAuthenticityToken) { xhr :put, :index } + end + + def test_should_not_allow_xhr_delete_without_token + assert_raises(ActionController::InvalidAuthenticityToken) { xhr :delete, :index } + end + + def test_should_allow_post_with_token + post :index, :authenticity_token => @token + assert_response :success + end + + def test_should_allow_put_with_token + put :index, :authenticity_token => @token + assert_response :success + end + + def test_should_allow_delete_with_token + delete :index, :authenticity_token => @token + assert_response :success + end + + def test_should_allow_post_with_xml + post :index, :format => 'xml' + assert_response :success + end + + def test_should_allow_put_with_xml + put :index, :format => 'xml' + assert_response :success + end + + def test_should_allow_delete_with_xml + delete :index, :format => 'xml' + assert_response :success + end +end + +# OK let's get our test on + +class RequestForgeryProtectionControllerTest < Test::Unit::TestCase + include RequestForgeryProtectionTests + def setup + @controller = RequestForgeryProtectionController.new + @request = ActionController::TestRequest.new + @response = ActionController::TestResponse.new + class << @request.session + def session_id() '123' end + end + @token = OpenSSL::HMAC.hexdigest(OpenSSL::Digest::Digest.new('SHA1'), 'abc', '123') + ActionController::Base.request_forgery_protection_token = :authenticity_token + end +end + +class RequestForgeryProtectionWithoutSecretControllerTest < Test::Unit::TestCase + def setup + @controller = RequestForgeryProtectionWithoutSecretController.new + @request = ActionController::TestRequest.new + @response = ActionController::TestResponse.new + class << @request.session + def session_id() '123' end + end + @token = OpenSSL::HMAC.hexdigest(OpenSSL::Digest::Digest.new('SHA1'), 'abc', '123') + ActionController::Base.request_forgery_protection_token = :authenticity_token + end + + def test_should_raise_error_without_secret + assert_raises ActionController::InvalidAuthenticityToken do + get :index + end + end +end + +class CsrfCookieMonsterControllerTest < Test::Unit::TestCase + include RequestForgeryProtectionTests + def setup + @controller = CsrfCookieMonsterController.new + @request = ActionController::TestRequest.new + @response = ActionController::TestResponse.new + class << @request.session + attr_accessor :dbman + end + # simulate a cookie session store + @request.session.dbman = FakeSessionDbMan + @token = Digest::SHA1.hexdigest("secure") + ActionController::Base.request_forgery_protection_token = :authenticity_token + end +end + +class FreeCookieControllerTest < Test::Unit::TestCase + def setup + @controller = FreeCookieController.new + @request = ActionController::TestRequest.new + @response = ActionController::TestResponse.new + @token = OpenSSL::HMAC.hexdigest(OpenSSL::Digest::Digest.new('SHA1'), 'abc', '123') + end + + def test_should_not_render_form_with_token_tag + get :index + assert_select 'form>div>input[name=?][value=?]', 'authenticity_token', @token, false + end + + def test_should_not_render_button_to_with_token_tag + get :show_button + assert_select 'form>div>input[name=?][value=?]', 'authenticity_token', @token, false + end + + def test_should_allow_all_methods_without_token + [:post, :put, :delete].each do |method| + assert_nothing_raised { send(method, :index)} + end + end +end diff --git a/vendor/rails-2.0.2/actionpack/test/controller/request_test.rb b/vendor/rails-2.0.2/actionpack/test/controller/request_test.rb new file mode 100644 index 000000000..698d3cbd2 --- /dev/null +++ b/vendor/rails-2.0.2/actionpack/test/controller/request_test.rb @@ -0,0 +1,836 @@ +require File.dirname(__FILE__) + '/../abstract_unit' +require 'action_controller/integration' + +class RequestTest < Test::Unit::TestCase + def setup + @request = ActionController::TestRequest.new + end + + def test_remote_ip + assert_equal '0.0.0.0', @request.remote_ip + + @request.remote_addr = '1.2.3.4' + assert_equal '1.2.3.4', @request.remote_ip + + @request.env['HTTP_CLIENT_IP'] = '2.3.4.5' + assert_equal '2.3.4.5', @request.remote_ip + @request.env.delete 'HTTP_CLIENT_IP' + + @request.env['HTTP_X_FORWARDED_FOR'] = '3.4.5.6' + assert_equal '3.4.5.6', @request.remote_ip + + @request.env['HTTP_X_FORWARDED_FOR'] = 'unknown,3.4.5.6' + assert_equal '3.4.5.6', @request.remote_ip + + @request.env['HTTP_X_FORWARDED_FOR'] = '172.16.0.1,3.4.5.6' + assert_equal '3.4.5.6', @request.remote_ip + + @request.env['HTTP_X_FORWARDED_FOR'] = '192.168.0.1,3.4.5.6' + assert_equal '3.4.5.6', @request.remote_ip + + @request.env['HTTP_X_FORWARDED_FOR'] = '10.0.0.1,3.4.5.6' + assert_equal '3.4.5.6', @request.remote_ip + + @request.env['HTTP_X_FORWARDED_FOR'] = '10.0.0.1, 10.0.0.1, 3.4.5.6' + assert_equal '3.4.5.6', @request.remote_ip + + @request.env['HTTP_X_FORWARDED_FOR'] = '127.0.0.1,3.4.5.6' + assert_equal '127.0.0.1', @request.remote_ip + + @request.env['HTTP_X_FORWARDED_FOR'] = 'unknown,192.168.0.1' + assert_equal '1.2.3.4', @request.remote_ip + @request.env.delete 'HTTP_X_FORWARDED_FOR' + end + + def test_domains + @request.host = "www.rubyonrails.org" + assert_equal "rubyonrails.org", @request.domain + + @request.host = "www.rubyonrails.co.uk" + assert_equal "rubyonrails.co.uk", @request.domain(2) + + @request.host = "192.168.1.200" + assert_nil @request.domain + + @request.host = "foo.192.168.1.200" + assert_nil @request.domain + + @request.host = "192.168.1.200.com" + assert_equal "200.com", @request.domain + + @request.host = nil + assert_nil @request.domain + end + + def test_subdomains + @request.host = "www.rubyonrails.org" + assert_equal %w( www ), @request.subdomains + + @request.host = "www.rubyonrails.co.uk" + assert_equal %w( www ), @request.subdomains(2) + + @request.host = "dev.www.rubyonrails.co.uk" + assert_equal %w( dev www ), @request.subdomains(2) + + @request.host = "foobar.foobar.com" + assert_equal %w( foobar ), @request.subdomains + + @request.host = "192.168.1.200" + assert_equal [], @request.subdomains + + @request.host = "foo.192.168.1.200" + assert_equal [], @request.subdomains + + @request.host = "192.168.1.200.com" + assert_equal %w( 192 168 1 ), @request.subdomains + + @request.host = nil + assert_equal [], @request.subdomains + end + + def test_port_string + @request.port = 80 + assert_equal "", @request.port_string + + @request.port = 8080 + assert_equal ":8080", @request.port_string + end + + def test_relative_url_root + @request.env['SCRIPT_NAME'] = "/hieraki/dispatch.cgi" + @request.env['SERVER_SOFTWARE'] = 'lighttpd/1.2.3' + assert_equal '', @request.relative_url_root, "relative_url_root should be disabled on lighttpd" + + @request.env['SERVER_SOFTWARE'] = 'apache/1.2.3 some random text' + + @request.env['SCRIPT_NAME'] = nil + assert_equal "", @request.relative_url_root + + @request.env['SCRIPT_NAME'] = "/dispatch.cgi" + assert_equal "", @request.relative_url_root + + @request.env['SCRIPT_NAME'] = "/myapp.rb" + assert_equal "", @request.relative_url_root + + @request.relative_url_root = nil + @request.env['SCRIPT_NAME'] = "/hieraki/dispatch.cgi" + assert_equal "/hieraki", @request.relative_url_root + + @request.relative_url_root = nil + @request.env['SCRIPT_NAME'] = "/collaboration/hieraki/dispatch.cgi" + assert_equal "/collaboration/hieraki", @request.relative_url_root + + # apache/scgi case + @request.relative_url_root = nil + @request.env['SCRIPT_NAME'] = "/collaboration/hieraki" + assert_equal "/collaboration/hieraki", @request.relative_url_root + + @request.relative_url_root = nil + @request.env['SCRIPT_NAME'] = "/hieraki/dispatch.cgi" + @request.env['SERVER_SOFTWARE'] = 'lighttpd/1.2.3' + @request.env['RAILS_RELATIVE_URL_ROOT'] = "/hieraki" + assert_equal "/hieraki", @request.relative_url_root + + # @env overrides path guess + @request.relative_url_root = nil + @request.env['SCRIPT_NAME'] = "/hieraki/dispatch.cgi" + @request.env['SERVER_SOFTWARE'] = 'apache/1.2.3 some random text' + @request.env['RAILS_RELATIVE_URL_ROOT'] = "/real_url" + assert_equal "/real_url", @request.relative_url_root + end + + def test_request_uri + @request.env['SERVER_SOFTWARE'] = 'Apache 42.342.3432' + + @request.relative_url_root = nil + @request.set_REQUEST_URI "http://www.rubyonrails.org/path/of/some/uri?mapped=1" + assert_equal "/path/of/some/uri?mapped=1", @request.request_uri + assert_equal "/path/of/some/uri", @request.path + + @request.relative_url_root = nil + @request.set_REQUEST_URI "http://www.rubyonrails.org/path/of/some/uri" + assert_equal "/path/of/some/uri", @request.request_uri + assert_equal "/path/of/some/uri", @request.path + + @request.relative_url_root = nil + @request.set_REQUEST_URI "/path/of/some/uri" + assert_equal "/path/of/some/uri", @request.request_uri + assert_equal "/path/of/some/uri", @request.path + + @request.relative_url_root = nil + @request.set_REQUEST_URI "/" + assert_equal "/", @request.request_uri + assert_equal "/", @request.path + + @request.relative_url_root = nil + @request.set_REQUEST_URI "/?m=b" + assert_equal "/?m=b", @request.request_uri + assert_equal "/", @request.path + + @request.relative_url_root = nil + @request.set_REQUEST_URI "/" + @request.env['SCRIPT_NAME'] = "/dispatch.cgi" + assert_equal "/", @request.request_uri + assert_equal "/", @request.path + + @request.relative_url_root = nil + @request.set_REQUEST_URI "/hieraki/" + @request.env['SCRIPT_NAME'] = "/hieraki/dispatch.cgi" + assert_equal "/hieraki/", @request.request_uri + assert_equal "/", @request.path + + @request.relative_url_root = nil + @request.set_REQUEST_URI "/collaboration/hieraki/books/edit/2" + @request.env['SCRIPT_NAME'] = "/collaboration/hieraki/dispatch.cgi" + assert_equal "/collaboration/hieraki/books/edit/2", @request.request_uri + assert_equal "/books/edit/2", @request.path + + # The following tests are for when REQUEST_URI is not supplied (as in IIS) + @request.relative_url_root = nil + @request.set_REQUEST_URI nil + @request.env['PATH_INFO'] = "/path/of/some/uri?mapped=1" + @request.env['SCRIPT_NAME'] = nil #"/path/dispatch.rb" + assert_equal "/path/of/some/uri?mapped=1", @request.request_uri + assert_equal "/path/of/some/uri", @request.path + + @request.set_REQUEST_URI nil + @request.relative_url_root = nil + @request.env['PATH_INFO'] = "/path/of/some/uri?mapped=1" + @request.env['SCRIPT_NAME'] = "/path/dispatch.rb" + assert_equal "/path/of/some/uri?mapped=1", @request.request_uri + assert_equal "/of/some/uri", @request.path + + @request.set_REQUEST_URI nil + @request.relative_url_root = nil + @request.env['PATH_INFO'] = "/path/of/some/uri" + @request.env['SCRIPT_NAME'] = nil + assert_equal "/path/of/some/uri", @request.request_uri + assert_equal "/path/of/some/uri", @request.path + + @request.set_REQUEST_URI nil + @request.relative_url_root = nil + @request.env['PATH_INFO'] = "/" + assert_equal "/", @request.request_uri + assert_equal "/", @request.path + + @request.set_REQUEST_URI nil + @request.relative_url_root = nil + @request.env['PATH_INFO'] = "/?m=b" + assert_equal "/?m=b", @request.request_uri + assert_equal "/", @request.path + + @request.set_REQUEST_URI nil + @request.relative_url_root = nil + @request.env['PATH_INFO'] = "/" + @request.env['SCRIPT_NAME'] = "/dispatch.cgi" + assert_equal "/", @request.request_uri + assert_equal "/", @request.path + + @request.set_REQUEST_URI nil + @request.relative_url_root = nil + @request.env['PATH_INFO'] = "/hieraki/" + @request.env['SCRIPT_NAME'] = "/hieraki/dispatch.cgi" + assert_equal "/hieraki/", @request.request_uri + assert_equal "/", @request.path + + @request.set_REQUEST_URI '/hieraki/dispatch.cgi' + @request.relative_url_root = '/hieraki' + assert_equal "/dispatch.cgi", @request.path + @request.relative_url_root = nil + + @request.set_REQUEST_URI '/hieraki/dispatch.cgi' + @request.relative_url_root = '/foo' + assert_equal "/hieraki/dispatch.cgi", @request.path + @request.relative_url_root = nil + + # This test ensures that Rails uses REQUEST_URI over PATH_INFO + @request.relative_url_root = nil + @request.env['REQUEST_URI'] = "/some/path" + @request.env['PATH_INFO'] = "/another/path" + @request.env['SCRIPT_NAME'] = "/dispatch.cgi" + assert_equal "/some/path", @request.request_uri + assert_equal "/some/path", @request.path + end + + + def test_host_with_default_port + @request.host = "rubyonrails.org" + @request.port = 80 + assert_equal "rubyonrails.org", @request.host_with_port + end + + def test_host_with_non_default_port + @request.host = "rubyonrails.org" + @request.port = 81 + assert_equal "rubyonrails.org:81", @request.host_with_port + end + + def test_server_software + assert_equal nil, @request.server_software + + @request.env['SERVER_SOFTWARE'] = 'Apache3.422' + assert_equal 'apache', @request.server_software + + @request.env['SERVER_SOFTWARE'] = 'lighttpd(1.1.4)' + assert_equal 'lighttpd', @request.server_software + end + + def test_xml_http_request + assert !@request.xml_http_request? + assert !@request.xhr? + + @request.env['HTTP_X_REQUESTED_WITH'] = "DefinitelyNotAjax1.0" + assert !@request.xml_http_request? + assert !@request.xhr? + + @request.env['HTTP_X_REQUESTED_WITH'] = "XMLHttpRequest" + assert @request.xml_http_request? + assert @request.xhr? + end + + def test_reports_ssl + assert !@request.ssl? + @request.env['HTTPS'] = 'on' + assert @request.ssl? + end + + def test_reports_ssl_when_proxied_via_lighttpd + assert !@request.ssl? + @request.env['HTTP_X_FORWARDED_PROTO'] = 'https' + assert @request.ssl? + end + + def test_symbolized_request_methods + [:get, :post, :put, :delete].each do |method| + set_request_method_to method + assert_equal method, @request.method + end + end + + def test_invalid_http_method_raises_exception + set_request_method_to :random_method + assert_raises(ActionController::UnknownHttpMethod) do + @request.method + end + end + + def test_allow_method_hacking_on_post + set_request_method_to :post + [:get, :head, :options, :put, :post, :delete].each do |method| + @request.instance_eval { @parameters = { :_method => method } ; @request_method = nil } + assert_equal(method == :head ? :get : method, @request.method) + end + end + + def test_invalid_method_hacking_on_post_raises_exception + set_request_method_to :post + @request.instance_eval { @parameters = { :_method => :random_method } ; @request_method = nil } + assert_raises(ActionController::UnknownHttpMethod) do + @request.method + end + end + + def test_restrict_method_hacking + @request.instance_eval { @parameters = { :_method => 'put' } } + [:get, :put, :delete].each do |method| + set_request_method_to method + assert_equal method, @request.method + end + end + + def test_head_masquarading_as_get + set_request_method_to :head + assert_equal :get, @request.method + assert @request.get? + assert @request.head? + end + + def test_xml_format + @request.instance_eval { @parameters = { :format => 'xml' } } + assert_equal Mime::XML, @request.format + end + + def test_xhtml_format + @request.instance_eval { @parameters = { :format => 'xhtml' } } + assert_equal Mime::HTML, @request.format + end + + def test_txt_format + @request.instance_eval { @parameters = { :format => 'txt' } } + assert_equal Mime::TEXT, @request.format + end + + def test_nil_format + @request.instance_eval { @parameters = { :format => nil } } + @request.env["HTTP_ACCEPT"] = "text/javascript" + assert_equal Mime::JS, @request.format + end + + def test_content_type + @request.env["CONTENT_TYPE"] = "text/html" + assert_equal Mime::HTML, @request.content_type + end + + def test_content_no_type + assert_equal nil, @request.content_type + end + + def test_content_type_xml + @request.env["CONTENT_TYPE"] = "application/xml" + assert_equal Mime::XML, @request.content_type + end + + def test_content_type_with_charset + @request.env["CONTENT_TYPE"] = "application/xml; charset=UTF-8" + assert_equal Mime::XML, @request.content_type + end + + def test_user_agent + assert_not_nil @request.user_agent + end + + def test_parameters + @request.instance_eval { @request_parameters = { "foo" => 1 } } + @request.instance_eval { @query_parameters = { "bar" => 2 } } + + assert_equal({"foo" => 1, "bar" => 2}, @request.parameters) + assert_equal({"foo" => 1}, @request.request_parameters) + assert_equal({"bar" => 2}, @request.query_parameters) + end + + protected + def set_request_method_to(method) + @request.env['REQUEST_METHOD'] = method.to_s.upcase + @request.instance_eval { @request_method = nil } + end +end + + +class UrlEncodedRequestParameterParsingTest < Test::Unit::TestCase + def setup + @query_string = "action=create_customer&full_name=David%20Heinemeier%20Hansson&customerId=1" + @query_string_with_empty = "action=create_customer&full_name=" + @query_string_with_array = "action=create_customer&selected[]=1&selected[]=2&selected[]=3" + @query_string_with_amps = "action=create_customer&name=Don%27t+%26+Does" + @query_string_with_multiple_of_same_name = + "action=update_order&full_name=Lau%20Taarnskov&products=4&products=2&products=3" + @query_string_with_many_equal = "action=create_customer&full_name=abc=def=ghi" + @query_string_without_equal = "action" + @query_string_with_many_ampersands = + "&action=create_customer&&&full_name=David%20Heinemeier%20Hansson" + @query_string_with_empty_key = "action=create_customer&full_name=David%20Heinemeier%20Hansson&=Save" + end + + def test_query_string + assert_equal( + { "action" => "create_customer", "full_name" => "David Heinemeier Hansson", "customerId" => "1"}, + ActionController::AbstractRequest.parse_query_parameters(@query_string) + ) + end + + def test_deep_query_string + expected = {'x' => {'y' => {'z' => '10'}}} + assert_equal(expected, ActionController::AbstractRequest.parse_query_parameters('x[y][z]=10')) + end + + def test_deep_query_string_with_array + assert_equal({'x' => {'y' => {'z' => ['10']}}}, ActionController::AbstractRequest.parse_query_parameters('x[y][z][]=10')) + assert_equal({'x' => {'y' => {'z' => ['10', '5']}}}, ActionController::AbstractRequest.parse_query_parameters('x[y][z][]=10&x[y][z][]=5')) + end + + def test_deep_query_string_with_array_of_hash + assert_equal({'x' => {'y' => [{'z' => '10'}]}}, ActionController::AbstractRequest.parse_query_parameters('x[y][][z]=10')) + assert_equal({'x' => {'y' => [{'z' => '10', 'w' => '10'}]}}, ActionController::AbstractRequest.parse_query_parameters('x[y][][z]=10&x[y][][w]=10')) + end + + def test_deep_query_string_with_array_of_hashes_with_one_pair + assert_equal({'x' => {'y' => [{'z' => '10'}, {'z' => '20'}]}}, ActionController::AbstractRequest.parse_query_parameters('x[y][][z]=10&x[y][][z]=20')) + assert_equal("10", ActionController::AbstractRequest.parse_query_parameters('x[y][][z]=10&x[y][][z]=20')["x"]["y"].first["z"]) + assert_equal("10", ActionController::AbstractRequest.parse_query_parameters('x[y][][z]=10&x[y][][z]=20').with_indifferent_access[:x][:y].first[:z]) + end + + def test_deep_query_string_with_array_of_hashes_with_multiple_pairs + assert_equal( + {'x' => {'y' => [{'z' => '10', 'w' => 'a'}, {'z' => '20', 'w' => 'b'}]}}, + ActionController::AbstractRequest.parse_query_parameters('x[y][][z]=10&x[y][][w]=a&x[y][][z]=20&x[y][][w]=b') + ) + end + + def test_query_string_with_nil + assert_equal( + { "action" => "create_customer", "full_name" => ''}, + ActionController::AbstractRequest.parse_query_parameters(@query_string_with_empty) + ) + end + + def test_query_string_with_array + assert_equal( + { "action" => "create_customer", "selected" => ["1", "2", "3"]}, + ActionController::AbstractRequest.parse_query_parameters(@query_string_with_array) + ) + end + + def test_query_string_with_amps + assert_equal( + { "action" => "create_customer", "name" => "Don't & Does"}, + ActionController::AbstractRequest.parse_query_parameters(@query_string_with_amps) + ) + end + + def test_query_string_with_many_equal + assert_equal( + { "action" => "create_customer", "full_name" => "abc=def=ghi"}, + ActionController::AbstractRequest.parse_query_parameters(@query_string_with_many_equal) + ) + end + + def test_query_string_without_equal + assert_equal( + { "action" => nil }, + ActionController::AbstractRequest.parse_query_parameters(@query_string_without_equal) + ) + end + + def test_query_string_with_empty_key + assert_equal( + { "action" => "create_customer", "full_name" => "David Heinemeier Hansson" }, + ActionController::AbstractRequest.parse_query_parameters(@query_string_with_empty_key) + ) + end + + def test_query_string_with_many_ampersands + assert_equal( + { "action" => "create_customer", "full_name" => "David Heinemeier Hansson"}, + ActionController::AbstractRequest.parse_query_parameters(@query_string_with_many_ampersands) + ) + end + + def test_unbalanced_query_string_with_array + assert_equal( + {'location' => ["1", "2"], 'age_group' => ["2"]}, + ActionController::AbstractRequest.parse_query_parameters("location[]=1&location[]=2&age_group[]=2") + ) + assert_equal( + {'location' => ["1", "2"], 'age_group' => ["2"]}, + ActionController::AbstractRequest.parse_request_parameters({'location[]' => ["1", "2"], + 'age_group[]' => ["2"]}) + ) + end + + + def test_request_hash_parsing + query = { + "note[viewers][viewer][][type]" => ["User", "Group"], + "note[viewers][viewer][][id]" => ["1", "2"] + } + + expected = { "note" => { "viewers"=>{"viewer"=>[{ "id"=>"1", "type"=>"User"}, {"type"=>"Group", "id"=>"2"} ]} } } + + assert_equal(expected, ActionController::AbstractRequest.parse_request_parameters(query)) + end + + + def test_parse_params + input = { + "customers[boston][first][name]" => [ "David" ], + "customers[boston][first][url]" => [ "http://David" ], + "customers[boston][second][name]" => [ "Allan" ], + "customers[boston][second][url]" => [ "http://Allan" ], + "something_else" => [ "blah" ], + "something_nil" => [ nil ], + "something_empty" => [ "" ], + "products[first]" => [ "Apple Computer" ], + "products[second]" => [ "Pc" ], + "" => [ 'Save' ] + } + + expected_output = { + "customers" => { + "boston" => { + "first" => { + "name" => "David", + "url" => "http://David" + }, + "second" => { + "name" => "Allan", + "url" => "http://Allan" + } + } + }, + "something_else" => "blah", + "something_empty" => "", + "something_nil" => "", + "products" => { + "first" => "Apple Computer", + "second" => "Pc" + } + } + + assert_equal expected_output, ActionController::AbstractRequest.parse_request_parameters(input) + end + + UploadedStringIO = ActionController::UploadedStringIO + class MockUpload < UploadedStringIO + def initialize(content_type, original_path, *args) + self.content_type = content_type + self.original_path = original_path + super *args + end + end + + def test_parse_params_from_multipart_upload + file = MockUpload.new('img/jpeg', 'foo.jpg') + ie_file = MockUpload.new('img/jpeg', 'c:\\Documents and Settings\\foo\\Desktop\\bar.jpg') + non_file_text_part = MockUpload.new('text/plain', '', 'abc') + + input = { + "something" => [ UploadedStringIO.new("") ], + "array_of_stringios" => [[ UploadedStringIO.new("One"), UploadedStringIO.new("Two") ]], + "mixed_types_array" => [[ UploadedStringIO.new("Three"), "NotStringIO" ]], + "mixed_types_as_checkboxes[strings][nested]" => [[ file, "String", UploadedStringIO.new("StringIO")]], + "ie_mixed_types_as_checkboxes[strings][nested]" => [[ ie_file, "String", UploadedStringIO.new("StringIO")]], + "products[string]" => [ UploadedStringIO.new("Apple Computer") ], + "products[file]" => [ file ], + "ie_products[string]" => [ UploadedStringIO.new("Microsoft") ], + "ie_products[file]" => [ ie_file ], + "text_part" => [non_file_text_part] + } + + expected_output = { + "something" => "", + "array_of_stringios" => ["One", "Two"], + "mixed_types_array" => [ "Three", "NotStringIO" ], + "mixed_types_as_checkboxes" => { + "strings" => { + "nested" => [ file, "String", "StringIO" ] + }, + }, + "ie_mixed_types_as_checkboxes" => { + "strings" => { + "nested" => [ ie_file, "String", "StringIO" ] + }, + }, + "products" => { + "string" => "Apple Computer", + "file" => file + }, + "ie_products" => { + "string" => "Microsoft", + "file" => ie_file + }, + "text_part" => "abc" + } + + params = ActionController::AbstractRequest.parse_request_parameters(input) + assert_equal expected_output, params + + # Lone filenames are preserved. + assert_equal 'foo.jpg', params['mixed_types_as_checkboxes']['strings']['nested'].first.original_filename + assert_equal 'foo.jpg', params['products']['file'].original_filename + + # But full Windows paths are reduced to their basename. + assert_equal 'bar.jpg', params['ie_mixed_types_as_checkboxes']['strings']['nested'].first.original_filename + assert_equal 'bar.jpg', params['ie_products']['file'].original_filename + end + + def test_parse_params_with_file + input = { + "customers[boston][first][name]" => [ "David" ], + "something_else" => [ "blah" ], + "logo" => [ File.new(File.dirname(__FILE__) + "/cgi_test.rb").path ] + } + + expected_output = { + "customers" => { + "boston" => { + "first" => { + "name" => "David" + } + } + }, + "something_else" => "blah", + "logo" => File.new(File.dirname(__FILE__) + "/cgi_test.rb").path, + } + + assert_equal expected_output, ActionController::AbstractRequest.parse_request_parameters(input) + end + + def test_parse_params_with_array + input = { "selected[]" => [ "1", "2", "3" ] } + + expected_output = { "selected" => [ "1", "2", "3" ] } + + assert_equal expected_output, ActionController::AbstractRequest.parse_request_parameters(input) + end + + def test_parse_params_with_non_alphanumeric_name + input = { "a/b[c]" => %w(d) } + expected = { "a/b" => { "c" => "d" }} + assert_equal expected, ActionController::AbstractRequest.parse_request_parameters(input) + end + + def test_parse_params_with_single_brackets_in_middle + input = { "a/b[c]d" => %w(e) } + expected = { "a/b" => {} } + assert_equal expected, ActionController::AbstractRequest.parse_request_parameters(input) + end + + def test_parse_params_with_separated_brackets + input = { "a/b@[c]d[e]" => %w(f) } + expected = { "a/b@" => { }} + assert_equal expected, ActionController::AbstractRequest.parse_request_parameters(input) + end + + def test_parse_params_with_separated_brackets_and_array + input = { "a/b@[c]d[e][]" => %w(f) } + expected = { "a/b@" => { }} + assert_equal expected , ActionController::AbstractRequest.parse_request_parameters(input) + end + + def test_parse_params_with_unmatched_brackets_and_array + input = { "a/b@[c][d[e][]" => %w(f) } + expected = { "a/b@" => { "c" => { }}} + assert_equal expected, ActionController::AbstractRequest.parse_request_parameters(input) + end + + def test_parse_params_with_nil_key + input = { nil => nil, "test2" => %w(value1) } + expected = { "test2" => "value1" } + assert_equal expected, ActionController::AbstractRequest.parse_request_parameters(input) + end +end + + +class MultipartRequestParameterParsingTest < Test::Unit::TestCase + FIXTURE_PATH = File.dirname(__FILE__) + '/../fixtures/multipart' + + def test_single_parameter + params = process('single_parameter') + assert_equal({ 'foo' => 'bar' }, params) + end + + def test_bracketed_param + assert_equal({ 'foo' => { 'baz' => 'bar'}}, process('bracketed_param')) + end + + def test_text_file + params = process('text_file') + assert_equal %w(file foo), params.keys.sort + assert_equal 'bar', params['foo'] + + file = params['file'] + assert_kind_of StringIO, file + assert_equal 'file.txt', file.original_filename + assert_equal "text/plain", file.content_type + assert_equal 'contents', file.read + end + + def test_large_text_file + params = process('large_text_file') + assert_equal %w(file foo), params.keys.sort + assert_equal 'bar', params['foo'] + + file = params['file'] + assert_kind_of Tempfile, file + assert_equal 'file.txt', file.original_filename + assert_equal "text/plain", file.content_type + assert ('a' * 20480) == file.read + end + + uses_mocha "test_no_rewind_stream" do + def test_no_rewind_stream + # Ensures that parse_multipart_form_parameters works with streams that cannot be rewound + file = File.open(File.join(FIXTURE_PATH, 'large_text_file'), 'rb') + file.expects(:rewind).raises(Errno::ESPIPE) + params = ActionController::AbstractRequest.parse_multipart_form_parameters(file, 'AaB03x', file.stat.size, {}) + assert_not_equal 0, file.pos # file was not rewound after reading + end + end + + def test_binary_file + params = process('binary_file') + assert_equal %w(file flowers foo), params.keys.sort + assert_equal 'bar', params['foo'] + + file = params['file'] + assert_kind_of StringIO, file + assert_equal 'file.csv', file.original_filename + assert_nil file.content_type + assert_equal 'contents', file.read + + file = params['flowers'] + assert_kind_of StringIO, file + assert_equal 'flowers.jpg', file.original_filename + assert_equal "image/jpeg", file.content_type + assert_equal 19512, file.size + #assert_equal File.read(File.dirname(__FILE__) + '/../../../activerecord/test/fixtures/flowers.jpg'), file.read + end + + def test_mixed_files + params = process('mixed_files') + assert_equal %w(files foo), params.keys.sort + assert_equal 'bar', params['foo'] + + # Ruby CGI doesn't handle multipart/mixed for us. + assert_kind_of String, params['files'] + assert_equal 19756, params['files'].size + end + + private + def process(name) + File.open(File.join(FIXTURE_PATH, name), 'rb') do |file| + params = ActionController::AbstractRequest.parse_multipart_form_parameters(file, 'AaB03x', file.stat.size, {}) + assert_equal 0, file.pos # file was rewound after reading + params + end + end +end + + +class XmlParamsParsingTest < Test::Unit::TestCase + def test_single_file + person = parse_body("<person><name>David</name><avatar type='file' name='me.jpg' content_type='image/jpg'>#{Base64.encode64('ABC')}</avatar></person>") + + assert_equal "image/jpg", person['person']['avatar'].content_type + assert_equal "me.jpg", person['person']['avatar'].original_filename + assert_equal "ABC", person['person']['avatar'].read + end + + def test_multiple_files + person = parse_body(<<-end_body) + <person> + <name>David</name> + <avatars> + <avatar type='file' name='me.jpg' content_type='image/jpg'>#{Base64.encode64('ABC')}</avatar> + <avatar type='file' name='you.gif' content_type='image/gif'>#{Base64.encode64('DEF')}</avatar> + </avatars> + </person> + end_body + + assert_equal "image/jpg", person['person']['avatars']['avatar'].first.content_type + assert_equal "me.jpg", person['person']['avatars']['avatar'].first.original_filename + assert_equal "ABC", person['person']['avatars']['avatar'].first.read + + assert_equal "image/gif", person['person']['avatars']['avatar'].last.content_type + assert_equal "you.gif", person['person']['avatars']['avatar'].last.original_filename + assert_equal "DEF", person['person']['avatars']['avatar'].last.read + end + + private + def parse_body(body) + env = { 'CONTENT_TYPE' => 'application/xml', + 'CONTENT_LENGTH' => body.size.to_s } + cgi = ActionController::Integration::Session::StubCGI.new(env, body) + ActionController::CgiRequest.new(cgi).request_parameters + end +end + +class LegacyXmlParamsParsingTest < XmlParamsParsingTest + private + def parse_body(body) + env = { 'HTTP_X_POST_DATA_FORMAT' => 'xml', + 'CONTENT_LENGTH' => body.size.to_s } + cgi = ActionController::Integration::Session::StubCGI.new(env, body) + ActionController::CgiRequest.new(cgi).request_parameters + end +end diff --git a/vendor/rails-2.0.2/actionpack/test/controller/rescue_test.rb b/vendor/rails-2.0.2/actionpack/test/controller/rescue_test.rb new file mode 100644 index 000000000..a63fd0600 --- /dev/null +++ b/vendor/rails-2.0.2/actionpack/test/controller/rescue_test.rb @@ -0,0 +1,501 @@ +require File.dirname(__FILE__) + '/../abstract_unit' + +uses_mocha 'rescue' do + +class RescueController < ActionController::Base + class NotAuthorized < StandardError + end + class NotAuthorizedToRescueAsString < StandardError + end + + class RecordInvalid < StandardError + end + class RecordInvalidToRescueAsString < StandardError + end + + class NotAllowed < StandardError + end + class NotAllowedToRescueAsString < StandardError + end + + class InvalidRequest < StandardError + end + class InvalidRequestToRescueAsString < StandardError + end + + class BadGateway < StandardError + end + class BadGatewayToRescueAsString < StandardError + end + + class ResourceUnavailable < StandardError + end + class ResourceUnavailableToRescueAsString < StandardError + end + + # We use a fully-qualified name in some strings, and a relative constant + # name in some other to test correct handling of both cases. + + rescue_from NotAuthorized, :with => :deny_access + rescue_from 'RescueController::NotAuthorizedToRescueAsString', :with => :deny_access + + rescue_from RecordInvalid, :with => :show_errors + rescue_from 'RescueController::RecordInvalidToRescueAsString', :with => :show_errors + + rescue_from NotAllowed, :with => proc { head :forbidden } + rescue_from 'RescueController::NotAllowedToRescueAsString', :with => proc { head :forbidden } + + rescue_from InvalidRequest, :with => proc { |exception| render :text => exception.message } + rescue_from 'InvalidRequestToRescueAsString', :with => proc { |exception| render :text => exception.message } + + rescue_from BadGateway do + head :status => 502 + end + rescue_from 'BadGatewayToRescueAsString' do + head :status => 502 + end + + rescue_from ResourceUnavailable do |exception| + render :text => exception.message + end + rescue_from 'ResourceUnavailableToRescueAsString' do |exception| + render :text => exception.message + end + + def raises + render :text => 'already rendered' + raise "don't panic!" + end + + def method_not_allowed + raise ActionController::MethodNotAllowed.new(:get, :head, :put) + end + + def not_implemented + raise ActionController::NotImplemented.new(:get, :put) + end + + def not_authorized + raise NotAuthorized + end + def not_authorized_raise_as_string + raise NotAuthorizedToRescueAsString + end + + def not_allowed + raise NotAllowed + end + def not_allowed_raise_as_string + raise NotAllowedToRescueAsString + end + + def invalid_request + raise InvalidRequest + end + def invalid_request_raise_as_string + raise InvalidRequestToRescueAsString + end + + def record_invalid + raise RecordInvalid + end + def record_invalid_raise_as_string + raise RecordInvalidToRescueAsString + end + + def bad_gateway + raise BadGateway + end + def bad_gateway_raise_as_string + raise BadGatewayToRescueAsString + end + + def resource_unavailable + raise ResourceUnavailable + end + def resource_unavailable_raise_as_string + raise ResourceUnavailableToRescueAsString + end + + def missing_template + end + + protected + def deny_access + head :forbidden + end + + def show_errors(exception) + head :unprocessable_entity + end +end + +class RescueTest < Test::Unit::TestCase + FIXTURE_PUBLIC = "#{File.dirname(__FILE__)}/../fixtures".freeze + + def setup + @controller = RescueController.new + @request = ActionController::TestRequest.new + @response = ActionController::TestResponse.new + + RescueController.consider_all_requests_local = true + @request.remote_addr = '1.2.3.4' + @request.host = 'example.com' + + begin + raise 'foo' + rescue => @exception + end + end + + def test_rescue_action_locally_if_all_requests_local + @controller.expects(:local_request?).never + @controller.expects(:rescue_action_locally).with(@exception) + @controller.expects(:rescue_action_in_public).never + + with_all_requests_local do + @controller.send :rescue_action, @exception + end + end + + def test_rescue_action_locally_if_remote_addr_is_localhost + @controller.expects(:local_request?).returns(true) + @controller.expects(:rescue_action_locally).with(@exception) + @controller.expects(:rescue_action_in_public).never + + with_all_requests_local false do + @controller.send :rescue_action, @exception + end + end + + def test_rescue_action_in_public_otherwise + @controller.expects(:local_request?).returns(false) + @controller.expects(:rescue_action_locally).never + @controller.expects(:rescue_action_in_public).with(@exception) + + with_all_requests_local false do + @controller.send :rescue_action, @exception + end + end + + def test_rescue_action_in_public_with_error_file + with_rails_root FIXTURE_PUBLIC do + with_all_requests_local false do + get :raises + end + end + + assert_response :internal_server_error + body = File.read("#{FIXTURE_PUBLIC}/public/500.html") + assert_equal body, @response.body + end + + def test_rescue_action_in_public_without_error_file + with_rails_root '/tmp' do + with_all_requests_local false do + get :raises + end + end + + assert_response :internal_server_error + assert_equal ' ', @response.body + end + + def test_rescue_unknown_action_in_public_with_error_file + with_rails_root FIXTURE_PUBLIC do + with_all_requests_local false do + get :foobar_doesnt_exist + end + end + + assert_response :not_found + body = File.read("#{FIXTURE_PUBLIC}/public/404.html") + assert_equal body, @response.body + end + + def test_rescue_unknown_action_in_public_without_error_file + with_rails_root '/tmp' do + with_all_requests_local false do + get :foobar_doesnt_exist + end + end + + assert_response :not_found + assert_equal ' ', @response.body + end + + def test_rescue_missing_template_in_public + with_rails_root FIXTURE_PUBLIC do + with_all_requests_local true do + get :missing_template + end + end + + assert_response :internal_server_error + assert @response.body.include?('missing_template'), "Response should include the template name." + end + + def test_rescue_action_locally + get :raises + assert_response :internal_server_error + assert_template 'diagnostics.erb' + assert @response.body.include?('RescueController#raises'), "Response should include controller and action." + assert @response.body.include?("don't panic"), "Response should include exception message." + end + + def test_local_request_when_remote_addr_is_localhost + @controller.expects(:request).returns(@request).at_least_once + with_remote_addr '127.0.0.1' do + assert @controller.send(:local_request?) + end + end + + def test_local_request_when_remote_addr_isnt_locahost + @controller.expects(:request).returns(@request) + with_remote_addr '1.2.3.4' do + assert !@controller.send(:local_request?) + end + end + + def test_rescue_responses + responses = ActionController::Base.rescue_responses + + assert_equal ActionController::Rescue::DEFAULT_RESCUE_RESPONSE, responses.default + assert_equal ActionController::Rescue::DEFAULT_RESCUE_RESPONSE, responses[Exception.new] + + assert_equal :not_found, responses[ActionController::RoutingError.name] + assert_equal :not_found, responses[ActionController::UnknownAction.name] + assert_equal :not_found, responses['ActiveRecord::RecordNotFound'] + assert_equal :conflict, responses['ActiveRecord::StaleObjectError'] + assert_equal :unprocessable_entity, responses['ActiveRecord::RecordInvalid'] + assert_equal :unprocessable_entity, responses['ActiveRecord::RecordNotSaved'] + assert_equal :method_not_allowed, responses['ActionController::MethodNotAllowed'] + assert_equal :not_implemented, responses['ActionController::NotImplemented'] + end + + def test_rescue_templates + templates = ActionController::Base.rescue_templates + + assert_equal ActionController::Rescue::DEFAULT_RESCUE_TEMPLATE, templates.default + assert_equal ActionController::Rescue::DEFAULT_RESCUE_TEMPLATE, templates[Exception.new] + + assert_equal 'missing_template', templates[ActionController::MissingTemplate.name] + assert_equal 'routing_error', templates[ActionController::RoutingError.name] + assert_equal 'unknown_action', templates[ActionController::UnknownAction.name] + assert_equal 'template_error', templates[ActionView::TemplateError.name] + end + + def test_clean_backtrace + with_rails_root nil do + # No action if RAILS_ROOT isn't set. + cleaned = @controller.send(:clean_backtrace, @exception) + assert_equal @exception.backtrace, cleaned + end + + with_rails_root Dir.pwd do + # RAILS_ROOT is removed from backtrace. + cleaned = @controller.send(:clean_backtrace, @exception) + expected = @exception.backtrace.map { |line| line.sub(RAILS_ROOT, '') } + assert_equal expected, cleaned + + # No action if backtrace is nil. + assert_nil @controller.send(:clean_backtrace, Exception.new) + end + end + + def test_not_implemented + with_all_requests_local false do + head :not_implemented + end + assert_response :not_implemented + assert_equal "GET, PUT", @response.headers['Allow'] + end + + def test_method_not_allowed + with_all_requests_local false do + get :method_not_allowed + end + assert_response :method_not_allowed + assert_equal "GET, HEAD, PUT", @response.headers['Allow'] + end + + def test_rescue_handler + get :not_authorized + assert_response :forbidden + end + def test_rescue_handler_string + get :not_authorized_raise_as_string + assert_response :forbidden + end + + def test_rescue_handler_with_argument + @controller.expects(:show_errors).once.with { |e| e.is_a?(Exception) } + get :record_invalid + end + def test_rescue_handler_with_argument_as_string + @controller.expects(:show_errors).once.with { |e| e.is_a?(Exception) } + get :record_invalid_raise_as_string + end + + def test_proc_rescue_handler + get :not_allowed + assert_response :forbidden + end + def test_proc_rescue_handler_as_string + get :not_allowed_raise_as_string + assert_response :forbidden + end + + def test_proc_rescue_handle_with_argument + get :invalid_request + assert_equal "RescueController::InvalidRequest", @response.body + end + def test_proc_rescue_handle_with_argument_as_string + get :invalid_request_raise_as_string + assert_equal "RescueController::InvalidRequestToRescueAsString", @response.body + end + + def test_block_rescue_handler + get :bad_gateway + assert_response 502 + end + def test_block_rescue_handler_as_string + get :bad_gateway_raise_as_string + assert_response 502 + end + + def test_block_rescue_handler_with_argument + get :resource_unavailable + assert_equal "RescueController::ResourceUnavailable", @response.body + end + + def test_block_rescue_handler_with_argument_as_string + get :resource_unavailable_raise_as_string + assert_equal "RescueController::ResourceUnavailableToRescueAsString", @response.body + end + + + protected + def with_all_requests_local(local = true) + old_local, ActionController::Base.consider_all_requests_local = + ActionController::Base.consider_all_requests_local, local + yield + ensure + ActionController::Base.consider_all_requests_local = old_local + end + + def with_remote_addr(addr) + old_remote_addr, @request.remote_addr = @request.remote_addr, addr + yield + ensure + @request.remote_addr = old_remote_addr + end + + def with_rails_root(path = nil) + old_rails_root = RAILS_ROOT if defined?(RAILS_ROOT) + if path + silence_warnings { Object.const_set(:RAILS_ROOT, path) } + else + Object.remove_const(:RAILS_ROOT) rescue nil + end + + yield + + ensure + if old_rails_root + silence_warnings { Object.const_set(:RAILS_ROOT, old_rails_root) } + else + Object.remove_const(:RAILS_ROOT) rescue nil + end + end +end + +class ExceptionInheritanceRescueController < ActionController::Base + + class ParentException < StandardError + end + + class ChildException < ParentException + end + + class GrandchildException < ChildException + end + + rescue_from ChildException, :with => lambda { head :ok } + rescue_from ParentException, :with => lambda { head :created } + rescue_from GrandchildException, :with => lambda { head :no_content } + + def raise_parent_exception + raise ParentException + end + + def raise_child_exception + raise ChildException + end + + def raise_grandchild_exception + raise GrandchildException + end +end + +class ExceptionInheritanceRescueTest < Test::Unit::TestCase + + def setup + @controller = ExceptionInheritanceRescueController.new + @request = ActionController::TestRequest.new + @response = ActionController::TestResponse.new + end + + def test_bottom_first + get :raise_grandchild_exception + assert_response :no_content + end + + def test_inheritance_works + get :raise_child_exception + assert_response :created + end +end + +class ControllerInheritanceRescueController < ExceptionInheritanceRescueController + class FirstExceptionInChildController < StandardError + end + + class SecondExceptionInChildController < StandardError + end + + rescue_from FirstExceptionInChildController, 'SecondExceptionInChildController', :with => lambda { head :gone } + + def raise_first_exception_in_child_controller + raise FirstExceptionInChildController + end + + def raise_second_exception_in_child_controller + raise SecondExceptionInChildController + end +end + +class ControllerInheritanceRescueControllerTest < Test::Unit::TestCase + + def setup + @controller = ControllerInheritanceRescueController.new + @request = ActionController::TestRequest.new + @response = ActionController::TestResponse.new + end + + def test_first_exception_in_child_controller + get :raise_first_exception_in_child_controller + assert_response :gone + end + + def test_second_exception_in_child_controller + get :raise_second_exception_in_child_controller + assert_response :gone + end + + def test_exception_in_parent_controller + get :raise_parent_exception + assert_response :created + end +end +end # uses_mocha diff --git a/vendor/rails-2.0.2/actionpack/test/controller/resources_test.rb b/vendor/rails-2.0.2/actionpack/test/controller/resources_test.rb new file mode 100644 index 000000000..8772e6628 --- /dev/null +++ b/vendor/rails-2.0.2/actionpack/test/controller/resources_test.rb @@ -0,0 +1,787 @@ +require File.dirname(__FILE__) + '/../abstract_unit' + +class ResourcesController < ActionController::Base + def index() render :nothing => true end + alias_method :show, :index + def rescue_action(e) raise e end +end + +class ThreadsController < ResourcesController; end +class MessagesController < ResourcesController; end +class CommentsController < ResourcesController; end +class AuthorsController < ResourcesController; end +class LogosController < ResourcesController; end + +class AccountsController < ResourcesController; end +class AdminController < ResourcesController; end + +module Backoffice + class ProductsController < ResourcesController; end + class TagsController < ResourcesController; end + class ManufacturersController < ResourcesController; end + class ImagesController < ResourcesController; end + + module Admin + class ProductsController < ResourcesController; end + class ImagesController < ResourcesController; end + end +end + +class ResourcesTest < Test::Unit::TestCase + + + # The assertions in these tests are incompatible with the hash method + # optimisation. This could indicate user level problems + def setup + ActionController::Base.optimise_named_routes = false + end + + def tear_down + ActionController::Base.optimise_named_routes = true + end + + def test_should_arrange_actions + resource = ActionController::Resources::Resource.new(:messages, + :collection => { :rss => :get, :reorder => :post, :csv => :post }, + :member => { :rss => :get, :atom => :get, :upload => :post, :fix => :post }, + :new => { :preview => :get, :draft => :get }) + + assert_resource_methods [:rss], resource, :collection, :get + assert_resource_methods [:csv, :reorder], resource, :collection, :post + assert_resource_methods [:edit, :rss, :atom], resource, :member, :get + assert_resource_methods [:upload, :fix], resource, :member, :post + assert_resource_methods [:new, :preview, :draft], resource, :new, :get + end + + def test_should_resource_controller_name_equal_resource_name_by_default + resource = ActionController::Resources::Resource.new(:messages, {}) + assert_equal 'messages', resource.controller + end + + def test_should_resource_controller_name_equal_controller_option + resource = ActionController::Resources::Resource.new(:messages, :controller => 'posts') + assert_equal 'posts', resource.controller + end + + def test_should_all_singleton_paths_be_the_same + [ :path, :nesting_path_prefix, :member_path ].each do |method| + resource = ActionController::Resources::SingletonResource.new(:messages, :path_prefix => 'admin') + assert_equal 'admin/messages', resource.send(method) + end + end + + def test_default_restful_routes + with_restful_routing :messages do + assert_simply_restful_for :messages + end + end + + def test_multiple_default_restful_routes + with_restful_routing :messages, :comments do + assert_simply_restful_for :messages + assert_simply_restful_for :comments + end + end + + def test_with_custom_conditions + with_restful_routing :messages, :conditions => { :subdomain => 'app' } do + assert_equal 'app', ActionController::Routing::Routes.named_routes.routes[:messages].conditions[:subdomain] + end + end + + def test_irregular_id_with_no_requirements_should_raise_error + expected_options = {:controller => 'messages', :action => 'show', :id => '1.1.1'} + + with_restful_routing :messages do + assert_raises(ActionController::RoutingError) do + assert_recognizes(expected_options, :path => 'messages/1.1.1', :method => :get) + end + end + end + + def test_irregular_id_with_requirements_should_pass + expected_options = {:controller => 'messages', :action => 'show', :id => '1.1.1'} + + with_restful_routing(:messages, :requirements => {:id => /[0-9]\.[0-9]\.[0-9]/}) do + assert_recognizes(expected_options, :path => 'messages/1.1.1', :method => :get) + end + end + + def test_with_path_prefix_requirements + expected_options = {:controller => 'messages', :action => 'show', :thread_id => '1.1.1', :id => '1'} + with_restful_routing :messages, :path_prefix => '/thread/:thread_id', :requirements => {:thread_id => /[0-9]\.[0-9]\.[0-9]/} do + assert_recognizes(expected_options, :path => 'thread/1.1.1/messages/1', :method => :get) + end + end + + def test_with_path_prefix + with_restful_routing :messages, :path_prefix => '/thread/:thread_id' do + assert_simply_restful_for :messages, :path_prefix => 'thread/5/', :options => { :thread_id => '5' } + end + end + + def test_multiple_with_path_prefix + with_restful_routing :messages, :comments, :path_prefix => '/thread/:thread_id' do + assert_simply_restful_for :messages, :path_prefix => 'thread/5/', :options => { :thread_id => '5' } + assert_simply_restful_for :comments, :path_prefix => 'thread/5/', :options => { :thread_id => '5' } + end + end + + def test_with_name_prefix + with_restful_routing :messages, :name_prefix => 'post_' do + assert_simply_restful_for :messages, :name_prefix => 'post_' + end + end + + def test_with_collection_actions + actions = { 'a' => :get, 'b' => :put, 'c' => :post, 'd' => :delete } + + with_restful_routing :messages, :collection => actions do + assert_restful_routes_for :messages do |options| + actions.each do |action, method| + assert_recognizes(options.merge(:action => action), :path => "/messages/#{action}", :method => method) + end + end + + assert_restful_named_routes_for :messages do |options| + actions.keys.each do |action| + assert_named_route "/messages/#{action}", "#{action}_messages_path", :action => action + end + end + end + end + + def test_with_collection_actions_and_name_prefix + actions = { 'a' => :get, 'b' => :put, 'c' => :post, 'd' => :delete } + + with_restful_routing :messages, :path_prefix => '/threads/:thread_id', :name_prefix => "thread_", :collection => actions do + assert_restful_routes_for :messages, :path_prefix => 'threads/1/', :name_prefix => 'thread_', :options => { :thread_id => '1' } do |options| + actions.each do |action, method| + assert_recognizes(options.merge(:action => action), :path => "/threads/1/messages/#{action}", :method => method) + end + end + + assert_restful_named_routes_for :messages, :path_prefix => 'threads/1/', :name_prefix => 'thread_', :options => { :thread_id => '1' } do |options| + actions.keys.each do |action| + assert_named_route "/threads/1/messages/#{action}", "#{action}_thread_messages_path", :action => action + end + end + end + end + + def test_with_collection_action_and_name_prefix_and_formatted + actions = { 'a' => :get, 'b' => :put, 'c' => :post, 'd' => :delete } + + with_restful_routing :messages, :path_prefix => '/threads/:thread_id', :name_prefix => "thread_", :collection => actions do + assert_restful_routes_for :messages, :path_prefix => 'threads/1/', :name_prefix => 'thread_', :options => { :thread_id => '1' } do |options| + actions.each do |action, method| + assert_recognizes(options.merge(:action => action, :format => 'xml'), :path => "/threads/1/messages/#{action}.xml", :method => method) + end + end + + assert_restful_named_routes_for :messages, :path_prefix => 'threads/1/', :name_prefix => 'thread_', :options => { :thread_id => '1' } do |options| + actions.keys.each do |action| + assert_named_route "/threads/1/messages/#{action}.xml", "formatted_#{action}_thread_messages_path", :action => action, :format => 'xml' + end + end + end + end + + def test_with_member_action + [:put, :post].each do |method| + with_restful_routing :messages, :member => { :mark => method } do + mark_options = {:action => 'mark', :id => '1'} + mark_path = "/messages/1/mark" + assert_restful_routes_for :messages do |options| + assert_recognizes(options.merge(mark_options), :path => mark_path, :method => method) + end + + assert_restful_named_routes_for :messages do |options| + assert_named_route mark_path, :mark_message_path, mark_options + end + end + end + end + + def test_with_two_member_actions_with_same_method + [:put, :post].each do |method| + with_restful_routing :messages, :member => { :mark => method, :unmark => method } do + %w(mark unmark).each do |action| + action_options = {:action => action, :id => '1'} + action_path = "/messages/1/#{action}" + assert_restful_routes_for :messages do |options| + assert_recognizes(options.merge(action_options), :path => action_path, :method => method) + end + + assert_restful_named_routes_for :messages do |options| + assert_named_route action_path, "#{action}_message_path".to_sym, action_options + end + end + end + end + end + + def test_with_new_action + with_restful_routing :messages, :new => { :preview => :post } do + preview_options = {:action => 'preview'} + preview_path = "/messages/new/preview" + assert_restful_routes_for :messages do |options| + assert_recognizes(options.merge(preview_options), :path => preview_path, :method => :post) + end + + assert_restful_named_routes_for :messages do |options| + assert_named_route preview_path, :preview_new_message_path, preview_options + end + end + end + + def test_with_new_action_with_name_prefix + with_restful_routing :messages, :new => { :preview => :post }, :path_prefix => '/threads/:thread_id', :name_prefix => 'thread_' do + preview_options = {:action => 'preview', :thread_id => '1'} + preview_path = "/threads/1/messages/new/preview" + assert_restful_routes_for :messages, :path_prefix => 'threads/1/', :name_prefix => 'thread_', :options => { :thread_id => '1' } do |options| + assert_recognizes(options.merge(preview_options), :path => preview_path, :method => :post) + end + + assert_restful_named_routes_for :messages, :path_prefix => 'threads/1/', :name_prefix => 'thread_', :options => { :thread_id => '1' } do |options| + assert_named_route preview_path, :preview_new_thread_message_path, preview_options + end + end + end + + def test_with_formatted_new_action_with_name_prefix + with_restful_routing :messages, :new => { :preview => :post }, :path_prefix => '/threads/:thread_id', :name_prefix => 'thread_' do + preview_options = {:action => 'preview', :thread_id => '1', :format => 'xml'} + preview_path = "/threads/1/messages/new/preview.xml" + assert_restful_routes_for :messages, :path_prefix => 'threads/1/', :name_prefix => 'thread_', :options => { :thread_id => '1' } do |options| + assert_recognizes(options.merge(preview_options), :path => preview_path, :method => :post) + end + + assert_restful_named_routes_for :messages, :path_prefix => 'threads/1/', :name_prefix => 'thread_', :options => { :thread_id => '1' } do |options| + assert_named_route preview_path, :formatted_preview_new_thread_message_path, preview_options + end + end + end + + def test_override_new_method + with_restful_routing :messages do + assert_restful_routes_for :messages do |options| + assert_recognizes(options.merge(:action => "new"), :path => "/messages/new", :method => :get) + assert_raises(ActionController::MethodNotAllowed) do + ActionController::Routing::Routes.recognize_path("/messages/new", :method => :post) + end + end + end + + with_restful_routing :messages, :new => { :new => :any } do + assert_restful_routes_for :messages do |options| + assert_recognizes(options.merge(:action => "new"), :path => "/messages/new", :method => :post) + assert_recognizes(options.merge(:action => "new"), :path => "/messages/new", :method => :get) + end + end + end + + def test_nested_restful_routes + with_routing do |set| + set.draw do |map| + map.resources :threads do |map| + map.resources :messages do |map| + map.resources :comments + end + end + end + + assert_simply_restful_for :threads + assert_simply_restful_for :messages, + :name_prefix => 'thread_', + :path_prefix => 'threads/1/', + :options => { :thread_id => '1' } + assert_simply_restful_for :comments, + :name_prefix => 'thread_message_', + :path_prefix => 'threads/1/messages/2/', + :options => { :thread_id => '1', :message_id => '2' } + end + end + + def test_nested_restful_routes_with_overwritten_defaults + with_routing do |set| + set.draw do |map| + map.resources :threads do |map| + map.resources :messages, :name_prefix => nil do |map| + map.resources :comments, :name_prefix => nil + end + end + end + + assert_simply_restful_for :threads + assert_simply_restful_for :messages, + :path_prefix => 'threads/1/', + :options => { :thread_id => '1' } + assert_simply_restful_for :comments, + :path_prefix => 'threads/1/messages/2/', + :options => { :thread_id => '1', :message_id => '2' } + end + end + + def test_restful_routes_dont_generate_duplicates + with_restful_routing :messages do + routes = ActionController::Routing::Routes.routes + routes.each do |route| + routes.each do |r| + next if route === r # skip the comparison instance + assert distinct_routes?(route, r), "Duplicate Route: #{route}" + end + end + end + end + + def test_should_create_singleton_resource_routes + with_singleton_resources :account do + assert_singleton_restful_for :account + end + end + + def test_should_create_multiple_singleton_resource_routes + with_singleton_resources :account, :logo do + assert_singleton_restful_for :account + assert_singleton_restful_for :logo + end + end + + def test_should_create_nested_singleton_resource_routes + with_routing do |set| + set.draw do |map| + map.resource :admin, :controller => 'admin' do |admin| + admin.resource :account + end + end + + assert_singleton_restful_for :admin, :controller => 'admin' + assert_singleton_restful_for :account, :name_prefix => "admin_", :path_prefix => 'admin/' + end + end + + def test_resource_has_many_should_become_nested_resources + with_routing do |set| + set.draw do |map| + map.resources :messages, :has_many => [ :comments, :authors ] + end + + assert_simply_restful_for :messages + assert_simply_restful_for :comments, :name_prefix => "message_", :path_prefix => 'messages/1/', :options => { :message_id => '1' } + assert_simply_restful_for :authors, :name_prefix => "message_", :path_prefix => 'messages/1/', :options => { :message_id => '1' } + end + end + + def test_resource_has_one_should_become_nested_resources + with_routing do |set| + set.draw do |map| + map.resources :messages, :has_one => :logo + end + + assert_simply_restful_for :messages + assert_singleton_restful_for :logo, :name_prefix => 'message_', :path_prefix => 'messages/1/', :options => { :message_id => '1' } + end + end + + def test_singleton_resource_with_member_action + [:put, :post].each do |method| + with_singleton_resources :account, :member => { :reset => method } do + reset_options = {:action => 'reset'} + reset_path = "/account/reset" + assert_singleton_routes_for :account do |options| + assert_recognizes(options.merge(reset_options), :path => reset_path, :method => method) + end + + assert_singleton_named_routes_for :account do |options| + assert_named_route reset_path, :reset_account_path, reset_options + end + end + end + end + + def test_singleton_resource_with_two_member_actions_with_same_method + [:put, :post].each do |method| + with_singleton_resources :account, :member => { :reset => method, :disable => method } do + %w(reset disable).each do |action| + action_options = {:action => action} + action_path = "/account/#{action}" + assert_singleton_routes_for :account do |options| + assert_recognizes(options.merge(action_options), :path => action_path, :method => method) + end + + assert_singleton_named_routes_for :account do |options| + assert_named_route action_path, "#{action}_account_path".to_sym, action_options + end + end + end + end + end + + def test_should_nest_resources_in_singleton_resource + with_routing do |set| + set.draw do |map| + map.resource :account do |account| + account.resources :messages + end + end + + assert_singleton_restful_for :account + assert_simply_restful_for :messages, :name_prefix => "account_", :path_prefix => 'account/' + end + end + + def test_should_nest_resources_in_singleton_resource_with_path_prefix + with_routing do |set| + set.draw do |map| + map.resource(:account, :path_prefix => ':site_id') do |account| + account.resources :messages + end + end + + assert_singleton_restful_for :account, :path_prefix => '7/', :options => { :site_id => '7' } + assert_simply_restful_for :messages, :name_prefix => "account_", :path_prefix => '7/account/', :options => { :site_id => '7' } + end + end + + def test_should_nest_singleton_resource_in_resources + with_routing do |set| + set.draw do |map| + map.resources :threads do |thread| + thread.resource :admin, :controller => 'admin' + end + end + + assert_simply_restful_for :threads + assert_singleton_restful_for :admin, :controller => 'admin', :name_prefix => 'thread_', :path_prefix => 'threads/5/', :options => { :thread_id => '5' } + end + end + + def test_should_not_allow_delete_or_put_on_collection_path + controller_name = :messages + with_restful_routing controller_name do + options = { :controller => controller_name.to_s } + collection_path = "/#{controller_name}" + + assert_raises(ActionController::MethodNotAllowed) do + assert_recognizes(options.merge(:action => 'update'), :path => collection_path, :method => :put) + end + + assert_raises(ActionController::MethodNotAllowed) do + assert_recognizes(options.merge(:action => 'destroy'), :path => collection_path, :method => :delete) + end + end + end + + def test_resource_action_separator + with_routing do |set| + set.draw do |map| + map.resources :messages, :collection => {:search => :get}, :new => {:preview => :any}, :name_prefix => 'thread_', :path_prefix => '/threads/:thread_id' + map.resource :account, :member => {:login => :get}, :new => {:preview => :any}, :name_prefix => 'admin_', :path_prefix => '/admin' + end + + action_separator = ActionController::Base.resource_action_separator + + assert_simply_restful_for :messages, :name_prefix => 'thread_', :path_prefix => 'threads/1/', :options => { :thread_id => '1' } + assert_named_route "/threads/1/messages#{action_separator}search", "search_thread_messages_path", {} + assert_named_route "/threads/1/messages/new", "new_thread_message_path", {} + assert_named_route "/threads/1/messages/new#{action_separator}preview", "preview_new_thread_message_path", {} + assert_singleton_restful_for :account, :name_prefix => 'admin_', :path_prefix => 'admin/' + assert_named_route "/admin/account#{action_separator}login", "login_admin_account_path", {} + assert_named_route "/admin/account/new", "new_admin_account_path", {} + assert_named_route "/admin/account/new#{action_separator}preview", "preview_new_admin_account_path", {} + end + end + + def test_new_style_named_routes_for_resource + with_routing do |set| + set.draw do |map| + map.resources :messages, :collection => {:search => :get}, :new => {:preview => :any}, :name_prefix => 'thread_', :path_prefix => '/threads/:thread_id' + end + assert_simply_restful_for :messages, :name_prefix => 'thread_', :path_prefix => 'threads/1/', :options => { :thread_id => '1' } + assert_named_route "/threads/1/messages/search", "search_thread_messages_path", {} + assert_named_route "/threads/1/messages/new", "new_thread_message_path", {} + assert_named_route "/threads/1/messages/new/preview", "preview_new_thread_message_path", {} + end + end + + def test_new_style_named_routes_for_singleton_resource + with_routing do |set| + set.draw do |map| + map.resource :account, :member => {:login => :get}, :new => {:preview => :any}, :name_prefix => 'admin_', :path_prefix => '/admin' + end + assert_singleton_restful_for :account, :name_prefix => 'admin_', :path_prefix => 'admin/' + assert_named_route "/admin/account/login", "login_admin_account_path", {} + assert_named_route "/admin/account/new", "new_admin_account_path", {} + assert_named_route "/admin/account/new/preview", "preview_new_admin_account_path", {} + end + end + + def test_resources_in_namespace + with_routing do |set| + set.draw do |map| + map.namespace :backoffice do |backoffice| + backoffice.resources :products + end + end + + assert_simply_restful_for :products, :controller => "backoffice/products", :name_prefix => 'backoffice_', :path_prefix => 'backoffice/' + end + end + + def test_resource_has_many_in_namespace + with_routing do |set| + set.draw do |map| + map.namespace :backoffice do |backoffice| + backoffice.resources :products, :has_many => :tags + end + end + + assert_simply_restful_for :products, :controller => "backoffice/products", :name_prefix => 'backoffice_', :path_prefix => 'backoffice/' + assert_simply_restful_for :tags, :controller => "backoffice/tags", :name_prefix => "backoffice_product_", :path_prefix => 'backoffice/products/1/', :options => { :product_id => '1' } + end + end + + def test_resource_has_one_in_namespace + with_routing do |set| + set.draw do |map| + map.namespace :backoffice do |backoffice| + backoffice.resources :products, :has_one => :manufacturer + end + end + + assert_simply_restful_for :products, :controller => "backoffice/products", :name_prefix => 'backoffice_', :path_prefix => 'backoffice/' + assert_singleton_restful_for :manufacturer, :controller => "backoffice/manufacturers", :name_prefix => 'backoffice_product_', :path_prefix => 'backoffice/products/1/', :options => { :product_id => '1' } + end + end + + def test_resources_in_nested_namespace + with_routing do |set| + set.draw do |map| + map.namespace :backoffice do |backoffice| + backoffice.namespace :admin do |admin| + admin.resources :products + end + end + end + + assert_simply_restful_for :products, :controller => "backoffice/admin/products", :name_prefix => 'backoffice_admin_', :path_prefix => 'backoffice/admin/' + end + end + + def test_resources_using_namespace + with_routing do |set| + set.draw do |map| + map.resources :products, :namespace => "backoffice/" + end + + assert_simply_restful_for :products, :controller => "backoffice/products" + end + end + + def test_nested_resources_using_namespace + with_routing do |set| + set.draw do |map| + map.namespace :backoffice do |backoffice| + backoffice.resources :products do |products| + products.resources :images + end + end + end + + assert_simply_restful_for :images, :controller => "backoffice/images", :name_prefix => 'backoffice_product_', :path_prefix => 'backoffice/products/1/', :options => {:product_id => '1'} + end + end + + def test_nested_resources_in_nested_namespace + with_routing do |set| + set.draw do |map| + map.namespace :backoffice do |backoffice| + backoffice.namespace :admin do |admin| + admin.resources :products do |products| + products.resources :images + end + end + end + end + + assert_simply_restful_for :images, :controller => "backoffice/admin/images", :name_prefix => 'backoffice_admin_product_', :path_prefix => 'backoffice/admin/products/1/', :options => {:product_id => '1'} + end + end + + protected + def with_restful_routing(*args) + with_routing do |set| + set.draw { |map| map.resources(*args) } + yield + end + end + + def with_singleton_resources(*args) + with_routing do |set| + set.draw { |map| map.resource(*args) } + yield + end + end + + # runs assert_restful_routes_for and assert_restful_named_routes for on the controller_name and options, without passing a block. + def assert_simply_restful_for(controller_name, options = {}) + assert_restful_routes_for controller_name, options + assert_restful_named_routes_for controller_name, nil, options + end + + def assert_singleton_restful_for(singleton_name, options = {}) + assert_singleton_routes_for singleton_name, options + assert_singleton_named_routes_for singleton_name, options + end + + def assert_restful_routes_for(controller_name, options = {}) + options[:options] ||= {} + options[:options][:controller] = options[:controller] || controller_name.to_s + + collection_path = "/#{options[:path_prefix]}#{controller_name}" + member_path = "#{collection_path}/1" + new_path = "#{collection_path}/new" + edit_member_path = "#{member_path}/edit" + formatted_edit_member_path = "#{member_path}/edit.xml" + + with_options(options[:options]) do |controller| + controller.assert_routing collection_path, :action => 'index' + controller.assert_routing new_path, :action => 'new' + controller.assert_routing member_path, :action => 'show', :id => '1' + controller.assert_routing edit_member_path, :action => 'edit', :id => '1' + controller.assert_routing "#{collection_path}.xml", :action => 'index', :format => 'xml' + controller.assert_routing "#{new_path}.xml", :action => 'new', :format => 'xml' + controller.assert_routing "#{member_path}.xml", :action => 'show', :id => '1', :format => 'xml' + controller.assert_routing formatted_edit_member_path, :action => 'edit', :id => '1', :format => 'xml' + end + + assert_recognizes(options[:options].merge(:action => 'index'), :path => collection_path, :method => :get) + assert_recognizes(options[:options].merge(:action => 'new'), :path => new_path, :method => :get) + assert_recognizes(options[:options].merge(:action => 'create'), :path => collection_path, :method => :post) + assert_recognizes(options[:options].merge(:action => 'show', :id => '1'), :path => member_path, :method => :get) + assert_recognizes(options[:options].merge(:action => 'edit', :id => '1'), :path => edit_member_path, :method => :get) + assert_recognizes(options[:options].merge(:action => 'update', :id => '1'), :path => member_path, :method => :put) + assert_recognizes(options[:options].merge(:action => 'destroy', :id => '1'), :path => member_path, :method => :delete) + + assert_recognizes(options[:options].merge(:action => 'index', :format => 'xml'), :path => "#{collection_path}.xml", :method => :get) + assert_recognizes(options[:options].merge(:action => 'new', :format => 'xml'), :path => "#{new_path}.xml", :method => :get) + assert_recognizes(options[:options].merge(:action => 'create', :format => 'xml'), :path => "#{collection_path}.xml", :method => :post) + assert_recognizes(options[:options].merge(:action => 'show', :id => '1', :format => 'xml'), :path => "#{member_path}.xml", :method => :get) + assert_recognizes(options[:options].merge(:action => 'edit', :id => '1', :format => 'xml'), :path => formatted_edit_member_path, :method => :get) + assert_recognizes(options[:options].merge(:action => 'update', :id => '1', :format => 'xml'), :path => "#{member_path}.xml", :method => :put) + assert_recognizes(options[:options].merge(:action => 'destroy', :id => '1', :format => 'xml'), :path => "#{member_path}.xml", :method => :delete) + + yield options[:options] if block_given? + end + + # test named routes like foo_path and foos_path map to the correct options. + def assert_restful_named_routes_for(controller_name, singular_name = nil, options = {}) + if singular_name.is_a?(Hash) + options = singular_name + singular_name = nil + end + singular_name ||= controller_name.to_s.singularize + + options[:options] ||= {} + options[:options][:controller] = options[:controller] || controller_name.to_s + + @controller = "#{options[:options][:controller].camelize}Controller".constantize.new + @request = ActionController::TestRequest.new + @response = ActionController::TestResponse.new + get :index, options[:options] + options[:options].delete :action + + full_prefix = "/#{options[:path_prefix]}#{controller_name}" + name_prefix = options[:name_prefix] + + assert_named_route "#{full_prefix}", "#{name_prefix}#{controller_name}_path", options[:options] + assert_named_route "#{full_prefix}.xml", "formatted_#{name_prefix}#{controller_name}_path", options[:options].merge( :format => 'xml') + assert_named_route "#{full_prefix}/1", "#{name_prefix}#{singular_name}_path", options[:options].merge(:id => '1') + assert_named_route "#{full_prefix}/1.xml", "formatted_#{name_prefix}#{singular_name}_path", options[:options].merge(:id => '1', :format => 'xml') + + assert_named_route "#{full_prefix}/new", "new_#{name_prefix}#{singular_name}_path", options[:options] + assert_named_route "#{full_prefix}/new.xml", "formatted_new_#{name_prefix}#{singular_name}_path", options[:options].merge( :format => 'xml') + assert_named_route "#{full_prefix}/1/edit", "edit_#{name_prefix}#{singular_name}_path", options[:options].merge(:id => '1') + assert_named_route "#{full_prefix}/1/edit.xml", "formatted_edit_#{name_prefix}#{singular_name}_path", options[:options].merge(:id => '1', :format => 'xml') + + yield options[:options] if block_given? + end + + def assert_singleton_routes_for(singleton_name, options = {}) + options[:options] ||= {} + options[:options][:controller] = options[:controller] || singleton_name.to_s.pluralize + + full_path = "/#{options[:path_prefix]}#{singleton_name}" + new_path = "#{full_path}/new" + edit_path = "#{full_path}/edit" + formatted_edit_path = "#{full_path}/edit.xml" + + with_options options[:options] do |controller| + controller.assert_routing full_path, :action => 'show' + controller.assert_routing new_path, :action => 'new' + controller.assert_routing edit_path, :action => 'edit' + controller.assert_routing "#{full_path}.xml", :action => 'show', :format => 'xml' + controller.assert_routing "#{new_path}.xml", :action => 'new', :format => 'xml' + controller.assert_routing formatted_edit_path, :action => 'edit', :format => 'xml' + end + + assert_recognizes(options[:options].merge(:action => 'show'), :path => full_path, :method => :get) + assert_recognizes(options[:options].merge(:action => 'new'), :path => new_path, :method => :get) + assert_recognizes(options[:options].merge(:action => 'edit'), :path => edit_path, :method => :get) + assert_recognizes(options[:options].merge(:action => 'create'), :path => full_path, :method => :post) + assert_recognizes(options[:options].merge(:action => 'update'), :path => full_path, :method => :put) + assert_recognizes(options[:options].merge(:action => 'destroy'), :path => full_path, :method => :delete) + + assert_recognizes(options[:options].merge(:action => 'show', :format => 'xml'), :path => "#{full_path}.xml", :method => :get) + assert_recognizes(options[:options].merge(:action => 'new', :format => 'xml'), :path => "#{new_path}.xml", :method => :get) + assert_recognizes(options[:options].merge(:action => 'edit', :format => 'xml'), :path => formatted_edit_path, :method => :get) + assert_recognizes(options[:options].merge(:action => 'create', :format => 'xml'), :path => "#{full_path}.xml", :method => :post) + assert_recognizes(options[:options].merge(:action => 'update', :format => 'xml'), :path => "#{full_path}.xml", :method => :put) + assert_recognizes(options[:options].merge(:action => 'destroy', :format => 'xml'), :path => "#{full_path}.xml", :method => :delete) + + yield options[:options] if block_given? + end + + def assert_singleton_named_routes_for(singleton_name, options = {}) + (options[:options] ||= {})[:controller] ||= singleton_name.to_s.pluralize + @controller = "#{options[:options][:controller].camelize}Controller".constantize.new + @request = ActionController::TestRequest.new + @response = ActionController::TestResponse.new + get :show, options[:options] + options[:options].delete :action + + full_path = "/#{options[:path_prefix]}#{singleton_name}" + name_prefix = options[:name_prefix] + + assert_named_route "#{full_path}", "#{name_prefix}#{singleton_name}_path", options[:options] + assert_named_route "#{full_path}.xml", "formatted_#{name_prefix}#{singleton_name}_path", options[:options].merge(:format => 'xml') + + assert_named_route "#{full_path}/new", "new_#{name_prefix}#{singleton_name}_path", options[:options] + assert_named_route "#{full_path}/new.xml", "formatted_new_#{name_prefix}#{singleton_name}_path", options[:options].merge(:format => 'xml') + assert_named_route "#{full_path}/edit", "edit_#{name_prefix}#{singleton_name}_path", options[:options] + assert_named_route "#{full_path}/edit.xml", "formatted_edit_#{name_prefix}#{singleton_name}_path", options[:options].merge(:format => 'xml') + end + + def assert_named_route(expected, route, options) + actual = @controller.send(route, options) rescue $!.class.name + assert_equal expected, actual, "Error on route: #{route}(#{options.inspect})" + end + + def assert_resource_methods(expected, resource, action_method, method) + assert_equal expected.length, resource.send("#{action_method}_methods")[method].size, "#{resource.send("#{action_method}_methods")[method].inspect}" + expected.each do |action| + assert resource.send("#{action_method}_methods")[method].include?(action), + "#{method} not in #{action_method} methods: #{resource.send("#{action_method}_methods")[method].inspect}" + end + end + + def distinct_routes? (r1, r2) + if r1.conditions == r2.conditions and r1.requirements == r2.requirements then + if r1.segments.collect(&:to_s) == r2.segments.collect(&:to_s) then + return false + end + end + true + end +end
\ No newline at end of file diff --git a/vendor/rails-2.0.2/actionpack/test/controller/routing_test.rb b/vendor/rails-2.0.2/actionpack/test/controller/routing_test.rb new file mode 100644 index 000000000..281ef13b3 --- /dev/null +++ b/vendor/rails-2.0.2/actionpack/test/controller/routing_test.rb @@ -0,0 +1,2203 @@ +require "#{File.dirname(__FILE__)}/../abstract_unit" +require "#{File.dirname(__FILE__)}/fake_controllers" +require 'action_controller/routing' + +class MilestonesController < ActionController::Base + def index() head :ok end + alias_method :show, :index + def rescue_action(e) raise e end +end + +RunTimeTests = ARGV.include? 'time' +ROUTING = ActionController::Routing + +class ROUTING::RouteBuilder + attr_reader :warn_output + + def warn(msg) + (@warn_output ||= []) << msg + end +end + +# See RFC 3986, section 3.3 for allowed path characters. +class UriReservedCharactersRoutingTest < Test::Unit::TestCase + def setup + ActionController::Routing.use_controllers! ['controller'] + @set = ActionController::Routing::RouteSet.new + @set.draw do |map| + map.connect ':controller/:action/:variable' + end + + safe, unsafe = %w(: @ & = + $ , ;), %w(^ / ? # [ ]) + hex = unsafe.map { |char| '%' + char.unpack('H2').first.upcase } + + @segment = "#{safe}#{unsafe}".freeze + @escaped = "#{safe}#{hex}".freeze + end + + def test_route_generation_escapes_unsafe_path_characters + assert_equal "/contr#{@segment}oller/act#{@escaped}ion/var#{@escaped}iable", + @set.generate(:controller => "contr#{@segment}oller", + :action => "act#{@segment}ion", + :variable => "var#{@segment}iable") + end + + def test_route_recognition_unescapes_path_components + options = { :controller => "controller", + :action => "act#{@segment}ion", + :variable => "var#{@segment}iable" } + assert_equal options, @set.recognize_path("/controller/act#{@escaped}ion/var#{@escaped}iable") + end +end + +class LegacyRouteSetTests < Test::Unit::TestCase + attr_reader :rs + def setup + # These tests assume optimisation is on, so re-enable it. + ActionController::Base.optimise_named_routes = true + + @rs = ::ActionController::Routing::RouteSet.new + @rs.draw {|m| m.connect ':controller/:action/:id' } + + ActionController::Routing.use_controllers! %w(content admin/user admin/news_feed) + end + + def test_default_setup + assert_equal({:controller => "content", :action => 'index'}, rs.recognize_path("/content")) + assert_equal({:controller => "content", :action => 'list'}, rs.recognize_path("/content/list")) + assert_equal({:controller => "content", :action => 'show', :id => '10'}, rs.recognize_path("/content/show/10")) + + assert_equal({:controller => "admin/user", :action => 'show', :id => '10'}, rs.recognize_path("/admin/user/show/10")) + + assert_equal '/admin/user/show/10', rs.generate(:controller => 'admin/user', :action => 'show', :id => 10) + + assert_equal '/admin/user/show', rs.generate({:action => 'show'}, {:controller => 'admin/user', :action => 'list', :id => '10'}) + assert_equal '/admin/user/list/10', rs.generate({}, {:controller => 'admin/user', :action => 'list', :id => '10'}) + + assert_equal '/admin/stuff', rs.generate({:controller => 'stuff'}, {:controller => 'admin/user', :action => 'list', :id => '10'}) + assert_equal '/stuff', rs.generate({:controller => '/stuff'}, {:controller => 'admin/user', :action => 'list', :id => '10'}) + end + + def test_ignores_leading_slash + @rs.draw {|m| m.connect '/:controller/:action/:id'} + test_default_setup + end + + def test_time_recognition + n = 10000 + if RunTimeTests + GC.start + rectime = Benchmark.realtime do + n.times do + rs.recognize_path("content") + rs.recognize_path("content/list") + rs.recognize_path("content/show/10") + rs.recognize_path("admin/user") + rs.recognize_path("admin/user/list") + rs.recognize_path("admin/user/show/10") + end + end + puts "\n\nRecognition (RouteSet):" + per_url = rectime / (n * 6) + puts "#{per_url * 1000} ms/url" + puts "#{1 / per_url} url/s\n\n" + end + end + def test_time_generation + n = 5000 + if RunTimeTests + GC.start + pairs = [ + [{:controller => 'content', :action => 'index'}, {:controller => 'content', :action => 'show'}], + [{:controller => 'content'}, {:controller => 'content', :action => 'index'}], + [{:controller => 'content', :action => 'list'}, {:controller => 'content', :action => 'index'}], + [{:controller => 'content', :action => 'show', :id => '10'}, {:controller => 'content', :action => 'list'}], + [{:controller => 'admin/user', :action => 'index'}, {:controller => 'admin/user', :action => 'show'}], + [{:controller => 'admin/user'}, {:controller => 'admin/user', :action => 'index'}], + [{:controller => 'admin/user', :action => 'list'}, {:controller => 'admin/user', :action => 'index'}], + [{:controller => 'admin/user', :action => 'show', :id => '10'}, {:controller => 'admin/user', :action => 'list'}], + ] + p = nil + gentime = Benchmark.realtime do + n.times do + pairs.each {|(a, b)| rs.generate(a, b)} + end + end + + puts "\n\nGeneration (RouteSet): (#{(n * 8)} urls)" + per_url = gentime / (n * 8) + puts "#{per_url * 1000} ms/url" + puts "#{1 / per_url} url/s\n\n" + end + end + + def test_route_with_colon_first + rs.draw do |map| + map.connect '/:controller/:action/:id', :action => 'index', :id => nil + map.connect ':url', :controller => 'tiny_url', :action => 'translate' + end + end + + def test_route_with_regexp_for_controller + rs.draw do |map| + map.connect ':controller/:admintoken/:action/:id', :controller => /admin\/.+/ + map.connect ':controller/:action/:id' + end + assert_equal({:controller => "admin/user", :admintoken => "foo", :action => "index"}, + rs.recognize_path("/admin/user/foo")) + assert_equal({:controller => "content", :action => "foo"}, rs.recognize_path("/content/foo")) + assert_equal '/admin/user/foo', rs.generate(:controller => "admin/user", :admintoken => "foo", :action => "index") + assert_equal '/content/foo', rs.generate(:controller => "content", :action => "foo") + end + + def test_route_with_regexp_and_dot + rs.draw do |map| + map.connect ':controller/:action/:file', + :controller => /admin|user/, + :action => /upload|download/, + :defaults => {:file => nil}, + :requirements => {:file => %r{[^/]+(\.[^/]+)?}} + end + # Without a file extension + assert_equal '/user/download/file', + rs.generate(:controller => "user", :action => "download", :file => "file") + assert_equal( + {:controller => "user", :action => "download", :file => "file"}, + rs.recognize_path("/user/download/file")) + + # Now, let's try a file with an extension, really a dot (.) + assert_equal '/user/download/file.jpg', + rs.generate( + :controller => "user", :action => "download", :file => "file.jpg") + assert_equal( + {:controller => "user", :action => "download", :file => "file.jpg"}, + rs.recognize_path("/user/download/file.jpg")) + end + + def test_basic_named_route + rs.add_named_route :home, '', :controller => 'content', :action => 'list' + x = setup_for_named_route + assert_equal("http://named.route.test/", + x.send(:home_url)) + end + + def test_basic_named_route_with_relative_url_root + rs.add_named_route :home, '', :controller => 'content', :action => 'list' + x = setup_for_named_route + x.relative_url_root="/foo" + assert_equal("http://named.route.test/foo/", + x.send(:home_url)) + assert_equal "/foo/", x.send(:home_path) + end + + def test_named_route_with_option + rs.add_named_route :page, 'page/:title', :controller => 'content', :action => 'show_page' + x = setup_for_named_route + assert_equal("http://named.route.test/page/new%20stuff", + x.send(:page_url, :title => 'new stuff')) + end + + def test_named_route_with_default + rs.add_named_route :page, 'page/:title', :controller => 'content', :action => 'show_page', :title => 'AboutPage' + x = setup_for_named_route + assert_equal("http://named.route.test/page/AboutRails", + x.send(:page_url, :title => "AboutRails")) + + end + + def test_named_route_with_nested_controller + rs.add_named_route :users, 'admin/user', :controller => 'admin/user', :action => 'index' + x = setup_for_named_route + assert_equal("http://named.route.test/admin/user", + x.send(:users_url)) + end + + uses_mocha "named route optimisation" do + def test_optimised_named_route_call_never_uses_url_for + rs.add_named_route :users, 'admin/user', :controller => '/admin/user', :action => 'index' + rs.add_named_route :user, 'admin/user/:id', :controller=>'/admin/user', :action=>'show' + x = setup_for_named_route + x.expects(:url_for).never + x.send(:users_url) + x.send(:users_path) + x.send(:user_url, 2, :foo=>"bar") + x.send(:user_path, 3, :bar=>"foo") + end + + def test_optimised_named_route_with_host + rs.add_named_route :pages, 'pages', :controller => 'content', :action => 'show_page', :host => 'foo.com' + x = setup_for_named_route + x.expects(:url_for).with(:host => 'foo.com', :only_path => false, :controller => 'content', :action => 'show_page', :use_route => :pages).once + x.send(:pages_url) + end + end + + def setup_for_named_route + klass = Class.new(MockController) + rs.install_helpers(klass) + klass.new(rs) + end + + def test_named_route_without_hash + rs.draw do |map| + map.normal ':controller/:action/:id' + end + end + + def test_named_route_root + rs.draw do |map| + map.root :controller => "hello" + end + x = setup_for_named_route + assert_equal("http://named.route.test/", x.send(:root_url)) + assert_equal("/", x.send(:root_path)) + end + + def test_named_route_with_regexps + rs.draw do |map| + map.article 'page/:year/:month/:day/:title', :controller => 'page', :action => 'show', + :year => /\d+/, :month => /\d+/, :day => /\d+/ + map.connect ':controller/:action/:id' + end + x = setup_for_named_route + # assert_equal( + # {:controller => 'page', :action => 'show', :title => 'hi', :use_route => :article, :only_path => false}, + # x.send(:article_url, :title => 'hi') + # ) + assert_equal( + "http://named.route.test/page/2005/6/10/hi", + x.send(:article_url, :title => 'hi', :day => 10, :year => 2005, :month => 6) + ) + end + + def test_changing_controller + assert_equal '/admin/stuff/show/10', rs.generate( + {:controller => 'stuff', :action => 'show', :id => 10}, + {:controller => 'admin/user', :action => 'index'} + ) + end + + def test_paths_escaped + rs.draw do |map| + map.path 'file/*path', :controller => 'content', :action => 'show_file' + map.connect ':controller/:action/:id' + end + + # No + to space in URI escaping, only for query params. + results = rs.recognize_path "/file/hello+world/how+are+you%3F" + assert results, "Recognition should have succeeded" + assert_equal ['hello+world', 'how+are+you?'], results[:path] + + # Use %20 for space instead. + results = rs.recognize_path "/file/hello%20world/how%20are%20you%3F" + assert results, "Recognition should have succeeded" + assert_equal ['hello world', 'how are you?'], results[:path] + + results = rs.recognize_path "/file" + assert results, "Recognition should have succeeded" + assert_equal [], results[:path] + end + + def test_paths_slashes_unescaped_with_ordered_parameters + rs.add_named_route :path, '/file/*path', :controller => 'content' + + # No / to %2F in URI, only for query params. + x = setup_for_named_route + assert_equal("/file/hello/world", x.send(:path_path, 'hello/world')) + end + + def test_non_controllers_cannot_be_matched + rs.draw do |map| + map.connect ':controller/:action/:id' + end + assert_raises(ActionController::RoutingError) { rs.recognize_path("/not_a/show/10") } + end + + def test_paths_do_not_accept_defaults + assert_raises(ActionController::RoutingError) do + rs.draw do |map| + map.path 'file/*path', :controller => 'content', :action => 'show_file', :path => %w(fake default) + map.connect ':controller/:action/:id' + end + end + + rs.draw do |map| + map.path 'file/*path', :controller => 'content', :action => 'show_file', :path => [] + map.connect ':controller/:action/:id' + end + end + + def test_should_list_options_diff_when_routing_requirements_dont_match + rs.draw do |map| + map.post 'post/:id', :controller=> 'post', :action=> 'show', :requirements => {:id => /\d+/} + end + exception = assert_raise(ActionController::RoutingError) { rs.generate(:controller => 'post', :action => 'show', :bad_param => "foo", :use_route => "post") } + assert_match /^post_url failed to generate/, exception.message + from_match = exception.message.match(/from \{[^\}]+\}/).to_s + assert_match /:bad_param=>"foo"/, from_match + assert_match /:action=>"show"/, from_match + assert_match /:controller=>"post"/, from_match + + expected_match = exception.message.match(/expected: \{[^\}]+\}/).to_s + assert_no_match /:bad_param=>"foo"/, expected_match + assert_match /:action=>"show"/, expected_match + assert_match /:controller=>"post"/, expected_match + + diff_match = exception.message.match(/diff: \{[^\}]+\}/).to_s + assert_match /:bad_param=>"foo"/, diff_match + assert_no_match /:action=>"show"/, diff_match + assert_no_match /:controller=>"post"/, diff_match + end + + # this specifies the case where your formerly would get a very confusing error message with an empty diff + def test_should_have_better_error_message_when_options_diff_is_empty + rs.draw do |map| + map.content '/content/:query', :controller => 'content', :action => 'show' + end + + exception = assert_raise(ActionController::RoutingError) { rs.generate(:controller => 'content', :action => 'show', :use_route => "content") } + assert_match %r[:action=>"show"], exception.message + assert_match %r[:controller=>"content"], exception.message + assert_match %r[you may have ambiguous routes, or you may need to supply additional parameters for this route], exception.message + assert_match %r[content_url has the following required parameters: \["content", :query\] - are they all satisfied?], exception.message + end + + def test_dynamic_path_allowed + rs.draw do |map| + map.connect '*path', :controller => 'content', :action => 'show_file' + end + + assert_equal '/pages/boo', rs.generate(:controller => 'content', :action => 'show_file', :path => %w(pages boo)) + end + + def test_dynamic_recall_paths_allowed + rs.draw do |map| + map.connect '*path', :controller => 'content', :action => 'show_file' + end + + recall_path = ActionController::Routing::PathSegment::Result.new(%w(pages boo)) + assert_equal '/pages/boo', rs.generate({}, :controller => 'content', :action => 'show_file', :path => recall_path) + end + + def test_backwards + rs.draw do |map| + map.connect 'page/:id/:action', :controller => 'pages', :action => 'show' + map.connect ':controller/:action/:id' + end + + assert_equal '/page/20', rs.generate({:id => 20}, {:controller => 'pages', :action => 'show'}) + assert_equal '/page/20', rs.generate(:controller => 'pages', :id => 20, :action => 'show') + assert_equal '/pages/boo', rs.generate(:controller => 'pages', :action => 'boo') + end + + def test_route_with_fixnum_default + rs.draw do |map| + map.connect 'page/:id', :controller => 'content', :action => 'show_page', :id => 1 + map.connect ':controller/:action/:id' + end + + assert_equal '/page', rs.generate(:controller => 'content', :action => 'show_page') + assert_equal '/page', rs.generate(:controller => 'content', :action => 'show_page', :id => 1) + assert_equal '/page', rs.generate(:controller => 'content', :action => 'show_page', :id => '1') + assert_equal '/page/10', rs.generate(:controller => 'content', :action => 'show_page', :id => 10) + + assert_equal({:controller => "content", :action => 'show_page', :id => '1'}, rs.recognize_path("/page")) + assert_equal({:controller => "content", :action => 'show_page', :id => '1'}, rs.recognize_path("/page/1")) + assert_equal({:controller => "content", :action => 'show_page', :id => '10'}, rs.recognize_path("/page/10")) + end + + # For newer revision + def test_route_with_text_default + rs.draw do |map| + map.connect 'page/:id', :controller => 'content', :action => 'show_page', :id => 1 + map.connect ':controller/:action/:id' + end + + assert_equal '/page/foo', rs.generate(:controller => 'content', :action => 'show_page', :id => 'foo') + assert_equal({:controller => "content", :action => 'show_page', :id => 'foo'}, rs.recognize_path("/page/foo")) + + token = "\321\202\320\265\320\272\321\201\321\202" # 'text' in russian + escaped_token = CGI::escape(token) + + assert_equal '/page/' + escaped_token, rs.generate(:controller => 'content', :action => 'show_page', :id => token) + assert_equal({:controller => "content", :action => 'show_page', :id => token}, rs.recognize_path("/page/#{escaped_token}")) + end + + def test_action_expiry + assert_equal '/content', rs.generate({:controller => 'content'}, {:controller => 'content', :action => 'show'}) + end + + def test_recognition_with_uppercase_controller_name + assert_equal({:controller => "content", :action => 'index'}, rs.recognize_path("/Content")) + assert_equal({:controller => "content", :action => 'list'}, rs.recognize_path("/ConTent/list")) + assert_equal({:controller => "content", :action => 'show', :id => '10'}, rs.recognize_path("/CONTENT/show/10")) + + # these used to work, before the routes rewrite, but support for this was pulled in the new version... + #assert_equal({'controller' => "admin/news_feed", 'action' => 'index'}, rs.recognize_path("Admin/NewsFeed")) + #assert_equal({'controller' => "admin/news_feed", 'action' => 'index'}, rs.recognize_path("Admin/News_Feed")) + end + + def test_requirement_should_prevent_optional_id + rs.draw do |map| + map.post 'post/:id', :controller=> 'post', :action=> 'show', :requirements => {:id => /\d+/} + end + + assert_equal '/post/10', rs.generate(:controller => 'post', :action => 'show', :id => 10) + + assert_raises ActionController::RoutingError do + rs.generate(:controller => 'post', :action => 'show') + end + end + + def test_both_requirement_and_optional + rs.draw do |map| + map.blog('test/:year', :controller => 'post', :action => 'show', + :defaults => { :year => nil }, + :requirements => { :year => /\d{4}/ } + ) + map.connect ':controller/:action/:id' + end + + assert_equal '/test', rs.generate(:controller => 'post', :action => 'show') + assert_equal '/test', rs.generate(:controller => 'post', :action => 'show', :year => nil) + + x = setup_for_named_route + assert_equal("http://named.route.test/test", + x.send(:blog_url)) + end + + def test_set_to_nil_forgets + rs.draw do |map| + map.connect 'pages/:year/:month/:day', :controller => 'content', :action => 'list_pages', :month => nil, :day => nil + map.connect ':controller/:action/:id' + end + + assert_equal '/pages/2005', + rs.generate(:controller => 'content', :action => 'list_pages', :year => 2005) + assert_equal '/pages/2005/6', + rs.generate(:controller => 'content', :action => 'list_pages', :year => 2005, :month => 6) + assert_equal '/pages/2005/6/12', + rs.generate(:controller => 'content', :action => 'list_pages', :year => 2005, :month => 6, :day => 12) + + assert_equal '/pages/2005/6/4', + rs.generate({:day => 4}, {:controller => 'content', :action => 'list_pages', :year => '2005', :month => '6', :day => '12'}) + + assert_equal '/pages/2005/6', + rs.generate({:day => nil}, {:controller => 'content', :action => 'list_pages', :year => '2005', :month => '6', :day => '12'}) + + assert_equal '/pages/2005', + rs.generate({:day => nil, :month => nil}, {:controller => 'content', :action => 'list_pages', :year => '2005', :month => '6', :day => '12'}) + end + + def test_url_with_no_action_specified + rs.draw do |map| + map.connect '', :controller => 'content' + map.connect ':controller/:action/:id' + end + + assert_equal '/', rs.generate(:controller => 'content', :action => 'index') + assert_equal '/', rs.generate(:controller => 'content') + end + + def test_named_url_with_no_action_specified + rs.draw do |map| + map.home '', :controller => 'content' + map.connect ':controller/:action/:id' + end + + assert_equal '/', rs.generate(:controller => 'content', :action => 'index') + assert_equal '/', rs.generate(:controller => 'content') + + x = setup_for_named_route + assert_equal("http://named.route.test/", + x.send(:home_url)) + end + + def test_url_generated_when_forgetting_action + [{:controller => 'content', :action => 'index'}, {:controller => 'content'}].each do |hash| + rs.draw do |map| + map.home '', hash + map.connect ':controller/:action/:id' + end + assert_equal '/', rs.generate({:action => nil}, {:controller => 'content', :action => 'hello'}) + assert_equal '/', rs.generate({:controller => 'content'}) + assert_equal '/content/hi', rs.generate({:controller => 'content', :action => 'hi'}) + end + end + + def test_named_route_method + rs.draw do |map| + map.categories 'categories', :controller => 'content', :action => 'categories' + map.connect ':controller/:action/:id' + end + + assert_equal '/categories', rs.generate(:controller => 'content', :action => 'categories') + assert_equal '/content/hi', rs.generate({:controller => 'content', :action => 'hi'}) + end + + def test_named_routes_array + test_named_route_method + assert_equal [:categories], rs.named_routes.names + end + + def test_nil_defaults + rs.draw do |map| + map.connect 'journal', + :controller => 'content', + :action => 'list_journal', + :date => nil, :user_id => nil + map.connect ':controller/:action/:id' + end + + assert_equal '/journal', rs.generate(:controller => 'content', :action => 'list_journal', :date => nil, :user_id => nil) + end + + def setup_request_method_routes_for(method) + @request = ActionController::TestRequest.new + @request.env["REQUEST_METHOD"] = method + @request.request_uri = "/match" + + rs.draw do |r| + r.connect '/match', :controller => 'books', :action => 'get', :conditions => { :method => :get } + r.connect '/match', :controller => 'books', :action => 'post', :conditions => { :method => :post } + r.connect '/match', :controller => 'books', :action => 'put', :conditions => { :method => :put } + r.connect '/match', :controller => 'books', :action => 'delete', :conditions => { :method => :delete } + end + end + + %w(GET POST PUT DELETE).each do |request_method| + define_method("test_request_method_recognized_with_#{request_method}") do + begin + Object.const_set(:BooksController, Class.new(ActionController::Base)) + + setup_request_method_routes_for(request_method) + + assert_nothing_raised { rs.recognize(@request) } + assert_equal request_method.downcase, @request.path_parameters[:action] + ensure + Object.send(:remove_const, :BooksController) rescue nil + end + end + end + + def test_subpath_recognized + Object.const_set(:SubpathBooksController, Class.new(ActionController::Base)) + + rs.draw do |r| + r.connect '/books/:id/edit', :controller => 'subpath_books', :action => 'edit' + r.connect '/items/:id/:action', :controller => 'subpath_books' + r.connect '/posts/new/:action', :controller => 'subpath_books' + r.connect '/posts/:id', :controller => 'subpath_books', :action => "show" + end + + hash = rs.recognize_path "/books/17/edit" + assert_not_nil hash + assert_equal %w(subpath_books 17 edit), [hash[:controller], hash[:id], hash[:action]] + + hash = rs.recognize_path "/items/3/complete" + assert_not_nil hash + assert_equal %w(subpath_books 3 complete), [hash[:controller], hash[:id], hash[:action]] + + hash = rs.recognize_path "/posts/new/preview" + assert_not_nil hash + assert_equal %w(subpath_books preview), [hash[:controller], hash[:action]] + + hash = rs.recognize_path "/posts/7" + assert_not_nil hash + assert_equal %w(subpath_books show 7), [hash[:controller], hash[:action], hash[:id]] + ensure + Object.send(:remove_const, :SubpathBooksController) rescue nil + end + + def test_subpath_generated + Object.const_set(:SubpathBooksController, Class.new(ActionController::Base)) + + rs.draw do |r| + r.connect '/books/:id/edit', :controller => 'subpath_books', :action => 'edit' + r.connect '/items/:id/:action', :controller => 'subpath_books' + r.connect '/posts/new/:action', :controller => 'subpath_books' + end + + assert_equal "/books/7/edit", rs.generate(:controller => "subpath_books", :id => 7, :action => "edit") + assert_equal "/items/15/complete", rs.generate(:controller => "subpath_books", :id => 15, :action => "complete") + assert_equal "/posts/new/preview", rs.generate(:controller => "subpath_books", :action => "preview") + ensure + Object.send(:remove_const, :SubpathBooksController) rescue nil + end + + def test_failed_requirements_raises_exception_with_violated_requirements + rs.draw do |r| + r.foo_with_requirement 'foos/:id', :controller=>'foos', :requirements=>{:id=>/\d+/} + end + + x = setup_for_named_route + assert_raises(ActionController::RoutingError) do + x.send(:foo_with_requirement_url, "I am Against the requirements") + end + end +end + +class SegmentTest < Test::Unit::TestCase + + def test_first_segment_should_interpolate_for_structure + s = ROUTING::Segment.new + def s.interpolation_statement(array) 'hello' end + assert_equal 'hello', s.continue_string_structure([]) + end + + def test_interpolation_statement + s = ROUTING::StaticSegment.new + s.value = "Hello" + assert_equal "Hello", eval(s.interpolation_statement([])) + assert_equal "HelloHello", eval(s.interpolation_statement([s])) + + s2 = ROUTING::StaticSegment.new + s2.value = "-" + assert_equal "Hello-Hello", eval(s.interpolation_statement([s, s2])) + + s3 = ROUTING::StaticSegment.new + s3.value = "World" + assert_equal "Hello-World", eval(s3.interpolation_statement([s, s2])) + end + +end + +class StaticSegmentTest < Test::Unit::TestCase + + def test_interpolation_chunk_should_respect_raw + s = ROUTING::StaticSegment.new + s.value = 'Hello World' + assert ! s.raw? + assert_equal 'Hello%20World', s.interpolation_chunk + + s.raw = true + assert s.raw? + assert_equal 'Hello World', s.interpolation_chunk + end + + def test_regexp_chunk_should_escape_specials + s = ROUTING::StaticSegment.new + + s.value = 'Hello*World' + assert_equal 'Hello\*World', s.regexp_chunk + + s.value = 'HelloWorld' + assert_equal 'HelloWorld', s.regexp_chunk + end + + def test_regexp_chunk_should_add_question_mark_for_optionals + s = ROUTING::StaticSegment.new + s.value = "/" + s.is_optional = true + assert_equal "/?", s.regexp_chunk + + s.value = "hello" + assert_equal "(?:hello)?", s.regexp_chunk + end + +end + +class DynamicSegmentTest < Test::Unit::TestCase + + def segment + unless @segment + @segment = ROUTING::DynamicSegment.new + @segment.key = :a + end + @segment + end + + def test_extract_value + s = ROUTING::DynamicSegment.new + s.key = :a + + hash = {:a => '10', :b => '20'} + assert_equal '10', eval(s.extract_value) + + hash = {:b => '20'} + assert_equal nil, eval(s.extract_value) + + s.default = '20' + assert_equal '20', eval(s.extract_value) + end + + def test_default_local_name + assert_equal 'a_value', segment.local_name, + "Unexpected name -- all value_check tests will fail!" + end + + def test_presence_value_check + a_value = 10 + assert eval(segment.value_check) + end + + def test_regexp_value_check_rejects_nil + segment.regexp = /\d+/ + a_value = nil + assert ! eval(segment.value_check) + end + + def test_optional_regexp_value_check_should_accept_nil + segment.regexp = /\d+/ + segment.is_optional = true + a_value = nil + assert eval(segment.value_check) + end + + def test_regexp_value_check_rejects_no_match + segment.regexp = /\d+/ + + a_value = "Hello20World" + assert ! eval(segment.value_check) + + a_value = "20Hi" + assert ! eval(segment.value_check) + end + + def test_regexp_value_check_accepts_match + segment.regexp = /\d+/ + + a_value = "30" + assert eval(segment.value_check) + end + + def test_value_check_fails_on_nil + a_value = nil + assert ! eval(segment.value_check) + end + + def test_optional_value_needs_no_check + segment.is_optional = true + a_value = nil + assert_equal nil, segment.value_check + end + + def test_regexp_value_check_should_accept_match_with_default + segment.regexp = /\d+/ + segment.default = '200' + + a_value = '100' + assert eval(segment.value_check) + end + + def test_expiry_should_not_trigger_once_expired + expired = true + hash = merged = {:a => 2, :b => 3} + options = {:b => 3} + expire_on = Hash.new { raise 'No!!!' } + + eval(segment.expiry_statement) + rescue RuntimeError + flunk "Expiry check should not have occurred!" + end + + def test_expiry_should_occur_according_to_expire_on + expired = false + hash = merged = {:a => 2, :b => 3} + options = {:b => 3} + + expire_on = {:b => true, :a => false} + eval(segment.expiry_statement) + assert !expired + assert_equal({:a => 2, :b => 3}, hash) + + expire_on = {:b => true, :a => true} + eval(segment.expiry_statement) + assert expired + assert_equal({:b => 3}, hash) + end + + def test_extraction_code_should_return_on_nil + hash = merged = {:b => 3} + options = {:b => 3} + a_value = nil + + # Local jump because of return inside eval. + assert_raises(LocalJumpError) { eval(segment.extraction_code) } + end + + def test_extraction_code_should_return_on_mismatch + segment.regexp = /\d+/ + hash = merged = {:a => 'Hi', :b => '3'} + options = {:b => '3'} + a_value = nil + + # Local jump because of return inside eval. + assert_raises(LocalJumpError) { eval(segment.extraction_code) } + end + + def test_extraction_code_should_accept_value_and_set_local + hash = merged = {:a => 'Hi', :b => '3'} + options = {:b => '3'} + a_value = nil + expired = true + + eval(segment.extraction_code) + assert_equal 'Hi', a_value + end + + def test_extraction_should_work_without_value_check + segment.default = 'hi' + hash = merged = {:b => '3'} + options = {:b => '3'} + a_value = nil + expired = true + + eval(segment.extraction_code) + assert_equal 'hi', a_value + end + + def test_extraction_code_should_perform_expiry + expired = false + hash = merged = {:a => 'Hi', :b => '3'} + options = {:b => '3'} + expire_on = {:a => true} + a_value = nil + + eval(segment.extraction_code) + assert_equal 'Hi', a_value + assert expired + assert_equal options, hash + end + + def test_interpolation_chunk_should_replace_value + a_value = 'Hi' + assert_equal a_value, eval(%("#{segment.interpolation_chunk}")) + end + + def test_interpolation_chunk_should_accept_nil + a_value = nil + assert_equal '', eval(%("#{segment.interpolation_chunk('a_value')}")) + end + + def test_value_regexp_should_be_nil_without_regexp + assert_equal nil, segment.value_regexp + end + + def test_value_regexp_should_match_exacly + segment.regexp = /\d+/ + assert_no_match segment.value_regexp, "Hello 10 World" + assert_no_match segment.value_regexp, "Hello 10" + assert_no_match segment.value_regexp, "10 World" + assert_match segment.value_regexp, "10" + end + + def test_regexp_chunk_should_return_string + segment.regexp = /\d+/ + assert_kind_of String, segment.regexp_chunk + end + + def test_build_pattern_non_optional_with_no_captures + # Non optional + a_segment = ROUTING::DynamicSegment.new + a_segment.regexp = /\d+/ #number_of_captures is 0 + assert_equal "(\\d+)stuff", a_segment.build_pattern('stuff') + end + + def test_build_pattern_non_optional_with_captures + # Non optional + a_segment = ROUTING::DynamicSegment.new + a_segment.regexp = /(\d+)(.*?)/ #number_of_captures is 2 + assert_equal "((\\d+)(.*?))stuff", a_segment.build_pattern('stuff') + end + + def test_optionality_implied + a_segment = ROUTING::DynamicSegment.new + a_segment.key = :id + assert a_segment.optionality_implied? + + a_segment.key = :action + assert a_segment.optionality_implied? + end +end + +class ControllerSegmentTest < Test::Unit::TestCase + + def test_regexp_should_only_match_possible_controllers + ActionController::Routing.with_controllers %w(admin/accounts admin/users account pages) do + cs = ROUTING::ControllerSegment.new :controller + regexp = %r{\A#{cs.regexp_chunk}\Z} + + ActionController::Routing.possible_controllers.each do |name| + assert_match regexp, name + assert_no_match regexp, "#{name}_fake" + + match = regexp.match name + assert_equal name, match[1] + end + end + end + +end + +uses_mocha 'RouteTest' do + + class MockController + attr_accessor :routes + + def initialize(routes) + self.routes = routes + end + + def url_for(options) + only_path = options.delete(:only_path) + + port = options.delete(:port) || 80 + port_string = port == 80 ? '' : ":#{port}" + + host = options.delete(:host) || "named.route.test" + anchor = "##{options.delete(:anchor)}" if options.key?(:anchor) + + path = routes.generate(options) + + only_path ? "#{path}#{anchor}" : "http://#{host}#{port_string}#{path}#{anchor}" + end + + def request + @request ||= MockRequest.new(:host => "named.route.test", :method => :get) + end + + def relative_url_root=(value) + request.relative_url_root=value + end + end + + class MockRequest + attr_accessor :path, :path_parameters, :host, :subdomains, :domain, + :method, :relative_url_root + + def initialize(values={}) + values.each { |key, value| send("#{key}=", value) } + if values[:host] + subdomain, self.domain = values[:host].split(/\./, 2) + self.subdomains = [subdomain] + end + end + + def protocol + "http://" + end + + def host_with_port + (subdomains * '.') + '.' + domain + end + end + +class RouteTest < Test::Unit::TestCase + + def setup + @route = ROUTING::Route.new + end + + def slash_segment(is_optional = false) + returning ROUTING::DividerSegment.new('/') do |s| + s.is_optional = is_optional + end + end + + def default_route + unless defined?(@default_route) + @default_route = ROUTING::Route.new + + @default_route.segments << (s = ROUTING::StaticSegment.new) + s.value = '/' + s.raw = true + + @default_route.segments << (s = ROUTING::DynamicSegment.new) + s.key = :controller + + @default_route.segments << slash_segment(:optional) + @default_route.segments << (s = ROUTING::DynamicSegment.new) + s.key = :action + s.default = 'index' + s.is_optional = true + + @default_route.segments << slash_segment(:optional) + @default_route.segments << (s = ROUTING::DynamicSegment.new) + s.key = :id + s.is_optional = true + + @default_route.segments << slash_segment(:optional) + end + @default_route + end + + def test_default_route_recognition + expected = {:controller => 'accounts', :action => 'show', :id => '10'} + assert_equal expected, default_route.recognize('/accounts/show/10') + assert_equal expected, default_route.recognize('/accounts/show/10/') + + expected[:id] = 'jamis' + assert_equal expected, default_route.recognize('/accounts/show/jamis/') + + expected.delete :id + assert_equal expected, default_route.recognize('/accounts/show') + assert_equal expected, default_route.recognize('/accounts/show/') + + expected[:action] = 'index' + assert_equal expected, default_route.recognize('/accounts/') + assert_equal expected, default_route.recognize('/accounts') + + assert_equal nil, default_route.recognize('/') + assert_equal nil, default_route.recognize('/accounts/how/goood/it/is/to/be/free') + end + + def test_default_route_should_omit_default_action + o = {:controller => 'accounts', :action => 'index'} + assert_equal '/accounts', default_route.generate(o, o, {}) + end + + def test_default_route_should_include_default_action_when_id_present + o = {:controller => 'accounts', :action => 'index', :id => '20'} + assert_equal '/accounts/index/20', default_route.generate(o, o, {}) + end + + def test_default_route_should_work_with_action_but_no_id + o = {:controller => 'accounts', :action => 'list_all'} + assert_equal '/accounts/list_all', default_route.generate(o, o, {}) + end + + def test_default_route_should_uri_escape_pluses + expected = { :controller => 'accounts', :action => 'show', :id => 'hello world' } + assert_equal expected, default_route.recognize('/accounts/show/hello world') + assert_equal expected, default_route.recognize('/accounts/show/hello%20world') + assert_equal '/accounts/show/hello%20world', default_route.generate(expected, expected, {}) + + expected[:id] = 'hello+world' + assert_equal expected, default_route.recognize('/accounts/show/hello+world') + assert_equal expected, default_route.recognize('/accounts/show/hello%2Bworld') + assert_equal '/accounts/show/hello+world', default_route.generate(expected, expected, {}) + end + + def test_matches_controller_and_action + # requirement_for should only be called for the action and controller _once_ + @route.expects(:requirement_for).with(:controller).times(1).returns('pages') + @route.expects(:requirement_for).with(:action).times(1).returns('show') + + @route.requirements = {:controller => 'pages', :action => 'show'} + assert @route.matches_controller_and_action?('pages', 'show') + assert !@route.matches_controller_and_action?('not_pages', 'show') + assert !@route.matches_controller_and_action?('pages', 'not_show') + end + + def test_parameter_shell + page_url = ROUTING::Route.new + page_url.requirements = {:controller => 'pages', :action => 'show', :id => /\d+/} + assert_equal({:controller => 'pages', :action => 'show'}, page_url.parameter_shell) + end + + def test_defaults + route = ROUTING::RouteBuilder.new.build '/users/:id.:format', :controller => "users", :action => "show", :format => "html" + assert_equal( + { :controller => "users", :action => "show", :format => "html" }, + route.defaults) + end + + def test_builder_complains_without_controller + assert_raises(ArgumentError) do + ROUTING::RouteBuilder.new.build '/contact', :contoller => "contact", :action => "index" + end + end + + def test_significant_keys_for_default_route + keys = default_route.significant_keys.sort_by {|k| k.to_s } + assert_equal [:action, :controller, :id], keys + end + + def test_significant_keys + user_url = ROUTING::Route.new + user_url.segments << (s = ROUTING::StaticSegment.new) + s.value = '/' + s.raw = true + + user_url.segments << (s = ROUTING::StaticSegment.new) + s.value = 'user' + + user_url.segments << (s = ROUTING::StaticSegment.new) + s.value = '/' + s.raw = true + s.is_optional = true + + user_url.segments << (s = ROUTING::DynamicSegment.new) + s.key = :user + + user_url.segments << (s = ROUTING::StaticSegment.new) + s.value = '/' + s.raw = true + s.is_optional = true + + user_url.requirements = {:controller => 'users', :action => 'show'} + + keys = user_url.significant_keys.sort_by { |k| k.to_s } + assert_equal [:action, :controller, :user], keys + end + + def test_build_empty_query_string + assert_equal '', @route.build_query_string({}) + end + + def test_build_query_string_with_nil_value + assert_equal '', @route.build_query_string({:x => nil}) + end + + def test_simple_build_query_string + assert_equal '?x=1&y=2', order_query_string(@route.build_query_string(:x => '1', :y => '2')) + end + + def test_convert_ints_build_query_string + assert_equal '?x=1&y=2', order_query_string(@route.build_query_string(:x => 1, :y => 2)) + end + + def test_escape_spaces_build_query_string + assert_equal '?x=hello+world&y=goodbye+world', order_query_string(@route.build_query_string(:x => 'hello world', :y => 'goodbye world')) + end + + def test_expand_array_build_query_string + assert_equal '?x%5B%5D=1&x%5B%5D=2', order_query_string(@route.build_query_string(:x => [1, 2])) + end + + def test_escape_spaces_build_query_string_selected_keys + assert_equal '?x=hello+world', order_query_string(@route.build_query_string({:x => 'hello world', :y => 'goodbye world'}, [:x])) + end + + private + def order_query_string(qs) + '?' + qs[1..-1].split('&').sort.join('&') + end +end + +end # uses_mocha + +class RouteBuilderTest < Test::Unit::TestCase + + def builder + @builder ||= ROUTING::RouteBuilder.new + end + + def build(path, options) + builder.build(path, options) + end + + def test_options_should_not_be_modified + requirements1 = { :id => /\w+/, :controller => /(?:[a-z](?:-?[a-z]+)*)/ } + requirements2 = requirements1.dup + + assert_equal requirements1, requirements2 + + with_options(:controller => 'folder', + :requirements => requirements2) do |m| + m.build 'folders/new', :action => 'new' + end + + assert_equal requirements1, requirements2 + end + + def test_segment_for_static + segment, rest = builder.segment_for 'ulysses' + assert_equal '', rest + assert_kind_of ROUTING::StaticSegment, segment + assert_equal 'ulysses', segment.value + end + + def test_segment_for_action + segment, rest = builder.segment_for ':action' + assert_equal '', rest + assert_kind_of ROUTING::DynamicSegment, segment + assert_equal :action, segment.key + assert_equal 'index', segment.default + end + + def test_segment_for_dynamic + segment, rest = builder.segment_for ':login' + assert_equal '', rest + assert_kind_of ROUTING::DynamicSegment, segment + assert_equal :login, segment.key + assert_equal nil, segment.default + assert ! segment.optional? + end + + def test_segment_for_with_rest + segment, rest = builder.segment_for ':login/:action' + assert_equal :login, segment.key + assert_equal '/:action', rest + segment, rest = builder.segment_for rest + assert_equal '/', segment.value + assert_equal ':action', rest + segment, rest = builder.segment_for rest + assert_equal :action, segment.key + assert_equal '', rest + end + + def test_segments_for + segments = builder.segments_for_route_path '/:controller/:action/:id' + + assert_kind_of ROUTING::DividerSegment, segments[0] + assert_equal '/', segments[2].value + + assert_kind_of ROUTING::DynamicSegment, segments[1] + assert_equal :controller, segments[1].key + + assert_kind_of ROUTING::DividerSegment, segments[2] + assert_equal '/', segments[2].value + + assert_kind_of ROUTING::DynamicSegment, segments[3] + assert_equal :action, segments[3].key + + assert_kind_of ROUTING::DividerSegment, segments[4] + assert_equal '/', segments[4].value + + assert_kind_of ROUTING::DynamicSegment, segments[5] + assert_equal :id, segments[5].key + end + + def test_segment_for_action + s, r = builder.segment_for(':action/something/else') + assert_equal '/something/else', r + assert_equal :action, s.key + end + + def test_action_default_should_not_trigger_on_prefix + s, r = builder.segment_for ':action_name/something/else' + assert_equal '/something/else', r + assert_equal :action_name, s.key + assert_equal nil, s.default + end + + def test_divide_route_options + segments = builder.segments_for_route_path '/cars/:action/:person/:car/' + defaults, requirements = builder.divide_route_options(segments, + :action => 'buy', :person => /\w+/, :car => /\w+/, + :defaults => {:person => nil, :car => nil} + ) + + assert_equal({:action => 'buy', :person => nil, :car => nil}, defaults) + assert_equal({:person => /\w+/, :car => /\w+/}, requirements) + end + + def test_assign_route_options + segments = builder.segments_for_route_path '/cars/:action/:person/:car/' + defaults = {:action => 'buy', :person => nil, :car => nil} + requirements = {:person => /\w+/, :car => /\w+/} + + route_requirements = builder.assign_route_options(segments, defaults, requirements) + assert_equal({}, route_requirements) + + assert_equal :action, segments[3].key + assert_equal 'buy', segments[3].default + + assert_equal :person, segments[5].key + assert_equal %r/\w+/, segments[5].regexp + assert segments[5].optional? + + assert_equal :car, segments[7].key + assert_equal %r/\w+/, segments[7].regexp + assert segments[7].optional? + end + + def test_assign_route_options_with_anchor_chars + segments = builder.segments_for_route_path '/cars/:action/:person/:car/' + defaults = {:action => 'buy', :person => nil, :car => nil} + requirements = {:person => /\w+/, :car => /^\w+$/} + + assert_raises ArgumentError do + route_requirements = builder.assign_route_options(segments, defaults, requirements) + end + + requirements[:car] = /[^\/]+/ + route_requirements = builder.assign_route_options(segments, defaults, requirements) + end + + + def test_optional_segments_preceding_required_segments + segments = builder.segments_for_route_path '/cars/:action/:person/:car/' + defaults = {:action => 'buy', :person => nil, :car => "model-t"} + assert builder.assign_route_options(segments, defaults, {}).empty? + + 0.upto(1) { |i| assert !segments[i].optional?, "segment #{i} is optional and it shouldn't be" } + assert segments[2].optional? + + assert_equal nil, builder.warn_output # should only warn on the :person segment + end + + def test_segmentation_of_dot_path + segments = builder.segments_for_route_path '/books/:action.rss' + assert builder.assign_route_options(segments, {}, {}).empty? + assert_equal 6, segments.length # "/", "books", "/", ":action", ".", "rss" + assert !segments.any? { |seg| seg.optional? } + end + + def test_segmentation_of_dynamic_dot_path + segments = builder.segments_for_route_path '/books/:action.:format' + assert builder.assign_route_options(segments, {}, {}).empty? + assert_equal 6, segments.length # "/", "books", "/", ":action", ".", ":format" + assert !segments.any? { |seg| seg.optional? } + assert_kind_of ROUTING::DynamicSegment, segments.last + end + + def test_assignment_of_default_options + segments = builder.segments_for_route_path '/:controller/:action/:id/' + action, id = segments[-4], segments[-2] + + assert_equal :action, action.key + assert_equal :id, id.key + assert ! action.optional? + assert ! id.optional? + + builder.assign_default_route_options(segments) + + assert_equal 'index', action.default + assert action.optional? + assert id.optional? + end + + def test_assignment_of_default_options_respects_existing_defaults + segments = builder.segments_for_route_path '/:controller/:action/:id/' + action, id = segments[-4], segments[-2] + + assert_equal :action, action.key + assert_equal :id, id.key + action.default = 'show' + action.is_optional = true + + id.default = 'Welcome' + id.is_optional = true + + builder.assign_default_route_options(segments) + + assert_equal 'show', action.default + assert action.optional? + assert_equal 'Welcome', id.default + assert id.optional? + end + + def test_assignment_of_default_options_respects_regexps + segments = builder.segments_for_route_path '/:controller/:action/:id/' + action = segments[-4] + + assert_equal :action, action.key + action.regexp = /show|in/ # Use 'in' to check partial matches + + builder.assign_default_route_options(segments) + + assert_equal nil, action.default + assert ! action.optional? + end + + def test_assignment_of_is_optional_when_default + segments = builder.segments_for_route_path '/books/:action.rss' + assert_equal segments[3].key, :action + segments[3].default = 'changes' + builder.ensure_required_segments(segments) + assert ! segments[3].optional? + end + + def test_is_optional_is_assigned_to_default_segments + segments = builder.segments_for_route_path '/books/:action' + builder.assign_route_options(segments, {:action => 'index'}, {}) + + assert_equal segments[3].key, :action + assert segments[3].optional? + assert_kind_of ROUTING::DividerSegment, segments[2] + assert segments[2].optional? + end + + # XXX is optional not being set right? + # /blah/:defaulted_segment <-- is the second slash optional? it should be. + + def test_route_build + ActionController::Routing.with_controllers %w(users pages) do + r = builder.build '/:controller/:action/:id/', :action => nil + + [0, 2, 4].each do |i| + assert_kind_of ROUTING::DividerSegment, r.segments[i] + assert_equal '/', r.segments[i].value + assert r.segments[i].optional? if i > 1 + end + + assert_kind_of ROUTING::DynamicSegment, r.segments[1] + assert_equal :controller, r.segments[1].key + assert_equal nil, r.segments[1].default + + assert_kind_of ROUTING::DynamicSegment, r.segments[3] + assert_equal :action, r.segments[3].key + assert_equal 'index', r.segments[3].default + + assert_kind_of ROUTING::DynamicSegment, r.segments[5] + assert_equal :id, r.segments[5].key + assert r.segments[5].optional? + end + end + + def test_slashes_are_implied + routes = [ + builder.build('/:controller/:action/:id/', :action => nil), + builder.build('/:controller/:action/:id', :action => nil), + builder.build(':controller/:action/:id', :action => nil), + builder.build('/:controller/:action/:id/', :action => nil) + ] + expected = routes.first.segments.length + routes.each_with_index do |route, i| + found = route.segments.length + assert_equal expected, found, "Route #{i + 1} has #{found} segments, expected #{expected}" + end + end + +end + + + + +class RouteSetTest < Test::Unit::TestCase + + def set + @set ||= ROUTING::RouteSet.new + end + + def request + @request ||= MockRequest.new(:host => "named.routes.test", :method => :get) + end + + def test_generate_extras + set.draw { |m| m.connect ':controller/:action/:id' } + path, extras = set.generate_extras(:controller => "foo", :action => "bar", :id => 15, :this => "hello", :that => "world") + assert_equal "/foo/bar/15", path + assert_equal %w(that this), extras.map(&:to_s).sort + end + + def test_extra_keys + set.draw { |m| m.connect ':controller/:action/:id' } + extras = set.extra_keys(:controller => "foo", :action => "bar", :id => 15, :this => "hello", :that => "world") + assert_equal %w(that this), extras.map(&:to_s).sort + end + + def test_generate_extras_not_first + set.draw do |map| + map.connect ':controller/:action/:id.:format' + map.connect ':controller/:action/:id' + end + path, extras = set.generate_extras(:controller => "foo", :action => "bar", :id => 15, :this => "hello", :that => "world") + assert_equal "/foo/bar/15", path + assert_equal %w(that this), extras.map(&:to_s).sort + end + + def test_generate_not_first + set.draw do |map| + map.connect ':controller/:action/:id.:format' + map.connect ':controller/:action/:id' + end + assert_equal "/foo/bar/15?this=hello", set.generate(:controller => "foo", :action => "bar", :id => 15, :this => "hello") + end + + def test_extra_keys_not_first + set.draw do |map| + map.connect ':controller/:action/:id.:format' + map.connect ':controller/:action/:id' + end + extras = set.extra_keys(:controller => "foo", :action => "bar", :id => 15, :this => "hello", :that => "world") + assert_equal %w(that this), extras.map(&:to_s).sort + end + + def test_draw + assert_equal 0, set.routes.size + set.draw do |map| + map.connect '/hello/world', :controller => 'a', :action => 'b' + end + assert_equal 1, set.routes.size + end + + def test_named_draw + assert_equal 0, set.routes.size + set.draw do |map| + map.hello '/hello/world', :controller => 'a', :action => 'b' + end + assert_equal 1, set.routes.size + assert_equal set.routes.first, set.named_routes[:hello] + end + + def test_later_named_routes_take_precedence + set.draw do |map| + map.hello '/hello/world', :controller => 'a', :action => 'b' + map.hello '/hello', :controller => 'a', :action => 'b' + end + assert_equal set.routes.last, set.named_routes[:hello] + end + + def setup_named_route_test + set.draw do |map| + map.show '/people/:id', :controller => 'people', :action => 'show' + map.index '/people', :controller => 'people', :action => 'index' + map.multi '/people/go/:foo/:bar/joe/:id', :controller => 'people', :action => 'multi' + map.users '/admin/users', :controller => 'admin/users', :action => 'index' + end + + klass = Class.new(MockController) + set.install_helpers(klass) + klass.new(set) + end + + def test_named_route_hash_access_method + controller = setup_named_route_test + + assert_equal( + { :controller => 'people', :action => 'show', :id => 5, :use_route => :show, :only_path => false }, + controller.send(:hash_for_show_url, :id => 5)) + + assert_equal( + { :controller => 'people', :action => 'index', :use_route => :index, :only_path => false }, + controller.send(:hash_for_index_url)) + + assert_equal( + { :controller => 'people', :action => 'show', :id => 5, :use_route => :show, :only_path => true }, + controller.send(:hash_for_show_path, :id => 5) + ) + end + + def test_named_route_url_method + controller = setup_named_route_test + + assert_equal "http://named.route.test/people/5", controller.send(:show_url, :id => 5) + assert_equal "/people/5", controller.send(:show_path, :id => 5) + + assert_equal "http://named.route.test/people", controller.send(:index_url) + assert_equal "/people", controller.send(:index_path) + + assert_equal "http://named.route.test/admin/users", controller.send(:users_url) + assert_equal '/admin/users', controller.send(:users_path) + assert_equal '/admin/users', set.generate(controller.send(:hash_for_users_url), {:controller => 'users', :action => 'index'}) + end + + def test_named_route_url_method_with_anchor + controller = setup_named_route_test + + assert_equal "http://named.route.test/people/5#location", controller.send(:show_url, :id => 5, :anchor => 'location') + assert_equal "/people/5#location", controller.send(:show_path, :id => 5, :anchor => 'location') + + assert_equal "http://named.route.test/people#location", controller.send(:index_url, :anchor => 'location') + assert_equal "/people#location", controller.send(:index_path, :anchor => 'location') + + assert_equal "http://named.route.test/admin/users#location", controller.send(:users_url, :anchor => 'location') + assert_equal '/admin/users#location', controller.send(:users_path, :anchor => 'location') + + assert_equal "http://named.route.test/people/go/7/hello/joe/5#location", + controller.send(:multi_url, 7, "hello", 5, :anchor => 'location') + + assert_equal "http://named.route.test/people/go/7/hello/joe/5?baz=bar#location", + controller.send(:multi_url, 7, "hello", 5, :baz => "bar", :anchor => 'location') + + assert_equal "http://named.route.test/people?baz=bar#location", + controller.send(:index_url, :baz => "bar", :anchor => 'location') + end + + def test_named_route_url_method_with_port + controller = setup_named_route_test + assert_equal "http://named.route.test:8080/people/5", controller.send(:show_url, 5, :port=>8080) + end + + def test_named_route_url_method_with_host + controller = setup_named_route_test + assert_equal "http://some.example.com/people/5", controller.send(:show_url, 5, :host=>"some.example.com") + end + + + def test_named_route_url_method_with_ordered_parameters + controller = setup_named_route_test + assert_equal "http://named.route.test/people/go/7/hello/joe/5", + controller.send(:multi_url, 7, "hello", 5) + end + + def test_named_route_url_method_with_ordered_parameters_and_hash + controller = setup_named_route_test + assert_equal "http://named.route.test/people/go/7/hello/joe/5?baz=bar", + controller.send(:multi_url, 7, "hello", 5, :baz => "bar") + end + + def test_named_route_url_method_with_no_positional_arguments + controller = setup_named_route_test + assert_equal "http://named.route.test/people?baz=bar", + controller.send(:index_url, :baz => "bar") + end + + def test_draw_default_route + ActionController::Routing.with_controllers(['users']) do + set.draw do |map| + map.connect '/:controller/:action/:id' + end + + assert_equal 1, set.routes.size + route = set.routes.first + + assert route.segments.last.optional? + + assert_equal '/users/show/10', set.generate(:controller => 'users', :action => 'show', :id => 10) + assert_equal '/users/index/10', set.generate(:controller => 'users', :id => 10) + + assert_equal({:controller => 'users', :action => 'index', :id => '10'}, set.recognize_path('/users/index/10')) + assert_equal({:controller => 'users', :action => 'index', :id => '10'}, set.recognize_path('/users/index/10/')) + end + end + + def test_draw_default_route_with_default_controller + ActionController::Routing.with_controllers(['users']) do + set.draw do |map| + map.connect '/:controller/:action/:id', :controller => 'users' + end + assert_equal({:controller => 'users', :action => 'index'}, set.recognize_path('/')) + end + end + + def test_route_with_parameter_shell + ActionController::Routing.with_controllers(['users', 'pages']) do + set.draw do |map| + map.connect 'page/:id', :controller => 'pages', :action => 'show', :id => /\d+/ + map.connect '/:controller/:action/:id' + end + + assert_equal({:controller => 'pages', :action => 'index'}, set.recognize_path('/pages')) + assert_equal({:controller => 'pages', :action => 'index'}, set.recognize_path('/pages/index')) + assert_equal({:controller => 'pages', :action => 'list'}, set.recognize_path('/pages/list')) + + assert_equal({:controller => 'pages', :action => 'show', :id => '10'}, set.recognize_path('/pages/show/10')) + assert_equal({:controller => 'pages', :action => 'show', :id => '10'}, set.recognize_path('/page/10')) + end + end + + def test_route_requirements_with_anchor_chars_are_invalid + assert_raises ArgumentError do + set.draw do |map| + map.connect 'page/:id', :controller => 'pages', :action => 'show', :id => /^\d+/ + end + end + assert_raises ArgumentError do + set.draw do |map| + map.connect 'page/:id', :controller => 'pages', :action => 'show', :id => /\A\d+/ + end + end + assert_raises ArgumentError do + set.draw do |map| + map.connect 'page/:id', :controller => 'pages', :action => 'show', :id => /\d+$/ + end + end + assert_raises ArgumentError do + set.draw do |map| + map.connect 'page/:id', :controller => 'pages', :action => 'show', :id => /\d+\Z/ + end + end + assert_raises ArgumentError do + set.draw do |map| + map.connect 'page/:id', :controller => 'pages', :action => 'show', :id => /\d+\z/ + end + end + assert_nothing_raised do + set.draw do |map| + map.connect 'page/:id', :controller => 'pages', :action => 'show', :id => /\d+/, :name => /^(david|jamis)/ + end + assert_raises ActionController::RoutingError do + set.generate :controller => 'pages', :action => 'show', :id => 10 + end + end + end + + def test_non_path_route_requirements_match_all + set.draw do |map| + map.connect 'page/37s', :controller => 'pages', :action => 'show', :name => /(jamis|david)/ + end + assert_equal '/page/37s', set.generate(:controller => 'pages', :action => 'show', :name => 'jamis') + assert_raises ActionController::RoutingError do + set.generate(:controller => 'pages', :action => 'show', :name => 'not_jamis') + end + assert_raises ActionController::RoutingError do + set.generate(:controller => 'pages', :action => 'show', :name => 'nor_jamis_and_david') + end + end + + def test_recognize_with_encoded_id_and_regex + set.draw do |map| + map.connect 'page/:id', :controller => 'pages', :action => 'show', :id => /[a-zA-Z0-9\+]+/ + end + + assert_equal({:controller => 'pages', :action => 'show', :id => '10'}, set.recognize_path('/page/10')) + assert_equal({:controller => 'pages', :action => 'show', :id => 'hello+world'}, set.recognize_path('/page/hello+world')) + end + + def test_recognize_with_conditions + Object.const_set(:PeopleController, Class.new) + + set.draw do |map| + map.with_options(:controller => "people") do |people| + people.people "/people", :action => "index", :conditions => { :method => :get } + people.connect "/people", :action => "create", :conditions => { :method => :post } + people.person "/people/:id", :action => "show", :conditions => { :method => :get } + people.connect "/people/:id", :action => "update", :conditions => { :method => :put } + people.connect "/people/:id", :action => "destroy", :conditions => { :method => :delete } + end + end + + request.path = "/people" + request.method = :get + assert_nothing_raised { set.recognize(request) } + assert_equal("index", request.path_parameters[:action]) + + request.method = :post + assert_nothing_raised { set.recognize(request) } + assert_equal("create", request.path_parameters[:action]) + + request.method = :put + assert_nothing_raised { set.recognize(request) } + assert_equal("update", request.path_parameters[:action]) + + begin + request.method = :bacon + set.recognize(request) + flunk 'Should have raised NotImplemented' + rescue ActionController::NotImplemented => e + assert_equal [:get, :post, :put, :delete], e.allowed_methods + end + + request.path = "/people/5" + request.method = :get + assert_nothing_raised { set.recognize(request) } + assert_equal("show", request.path_parameters[:action]) + assert_equal("5", request.path_parameters[:id]) + + request.method = :put + assert_nothing_raised { set.recognize(request) } + assert_equal("update", request.path_parameters[:action]) + assert_equal("5", request.path_parameters[:id]) + + request.method = :delete + assert_nothing_raised { set.recognize(request) } + assert_equal("destroy", request.path_parameters[:action]) + assert_equal("5", request.path_parameters[:id]) + + begin + request.method = :post + set.recognize(request) + flunk 'Should have raised MethodNotAllowed' + rescue ActionController::MethodNotAllowed => e + assert_equal [:get, :put, :delete], e.allowed_methods + end + + ensure + Object.send(:remove_const, :PeopleController) + end + + def test_typo_recognition + Object.const_set(:ArticlesController, Class.new) + + set.draw do |map| + map.connect 'articles/:year/:month/:day/:title', + :controller => 'articles', :action => 'permalink', + :year => /\d{4}/, :day => /\d{1,2}/, :month => /\d{1,2}/ + end + + request.path = "/articles/2005/11/05/a-very-interesting-article" + request.method = :get + assert_nothing_raised { set.recognize(request) } + assert_equal("permalink", request.path_parameters[:action]) + assert_equal("2005", request.path_parameters[:year]) + assert_equal("11", request.path_parameters[:month]) + assert_equal("05", request.path_parameters[:day]) + assert_equal("a-very-interesting-article", request.path_parameters[:title]) + + ensure + Object.send(:remove_const, :ArticlesController) + end + + def test_routing_traversal_does_not_load_extra_classes + assert !Object.const_defined?("Profiler__"), "Profiler should not be loaded" + set.draw do |map| + map.connect '/profile', :controller => 'profile' + end + + request.path = '/profile' + + set.recognize(request) rescue nil + + assert !Object.const_defined?("Profiler__"), "Profiler should not be loaded" + end + + def test_recognize_with_conditions_and_format + Object.const_set(:PeopleController, Class.new) + + set.draw do |map| + map.with_options(:controller => "people") do |people| + people.person "/people/:id", :action => "show", :conditions => { :method => :get } + people.connect "/people/:id", :action => "update", :conditions => { :method => :put } + people.connect "/people/:id.:_format", :action => "show", :conditions => { :method => :get } + end + end + + request.path = "/people/5" + request.method = :get + assert_nothing_raised { set.recognize(request) } + assert_equal("show", request.path_parameters[:action]) + assert_equal("5", request.path_parameters[:id]) + + request.method = :put + assert_nothing_raised { set.recognize(request) } + assert_equal("update", request.path_parameters[:action]) + + request.path = "/people/5.png" + request.method = :get + assert_nothing_raised { set.recognize(request) } + assert_equal("show", request.path_parameters[:action]) + assert_equal("5", request.path_parameters[:id]) + assert_equal("png", request.path_parameters[:_format]) + ensure + Object.send(:remove_const, :PeopleController) + end + + def test_generate_with_default_action + set.draw do |map| + map.connect "/people", :controller => "people" + map.connect "/people/list", :controller => "people", :action => "list" + end + + url = set.generate(:controller => "people", :action => "list") + assert_equal "/people/list", url + end + + def test_root_map + Object.const_set(:PeopleController, Class.new) + + set.draw { |map| map.root :controller => "people" } + + request.path = "" + request.method = :get + assert_nothing_raised { set.recognize(request) } + assert_equal("people", request.path_parameters[:controller]) + assert_equal("index", request.path_parameters[:action]) + ensure + Object.send(:remove_const, :PeopleController) + end + + + def test_namespace + Object.const_set(:Api, Module.new { |m| m.const_set(:ProductsController, Class.new) }) + + set.draw do |map| + + map.namespace 'api' do |api| + api.route 'inventory', :controller => "products", :action => 'inventory' + end + + end + + request.path = "/api/inventory" + request.method = :get + assert_nothing_raised { set.recognize(request) } + assert_equal("api/products", request.path_parameters[:controller]) + assert_equal("inventory", request.path_parameters[:action]) + ensure + Object.send(:remove_const, :Api) + end + + + def test_namespaced_root_map + Object.const_set(:Api, Module.new { |m| m.const_set(:ProductsController, Class.new) }) + + set.draw do |map| + + map.namespace 'api' do |api| + api.root :controller => "products" + end + + end + + request.path = "/api" + request.method = :get + assert_nothing_raised { set.recognize(request) } + assert_equal("api/products", request.path_parameters[:controller]) + assert_equal("index", request.path_parameters[:action]) + ensure + Object.send(:remove_const, :Api) + end + + def test_generate_finds_best_fit + set.draw do |map| + map.connect "/people", :controller => "people", :action => "index" + map.connect "/ws/people", :controller => "people", :action => "index", :ws => true + end + + url = set.generate(:controller => "people", :action => "index", :ws => true) + assert_equal "/ws/people", url + end + + def test_generate_changes_controller_module + set.draw { |map| map.connect ':controller/:action/:id' } + current = { :controller => "bling/bloop", :action => "bap", :id => 9 } + url = set.generate({:controller => "foo/bar", :action => "baz", :id => 7}, current) + assert_equal "/foo/bar/baz/7", url + end + + def test_id_is_not_impossibly_sticky + set.draw do |map| + map.connect 'foo/:number', :controller => "people", :action => "index" + map.connect ':controller/:action/:id' + end + + url = set.generate({:controller => "people", :action => "index", :number => 3}, + {:controller => "people", :action => "index", :id => "21"}) + assert_equal "/foo/3", url + end + + def test_id_is_sticky_when_it_ought_to_be + set.draw do |map| + map.connect ':controller/:id/:action' + end + + url = set.generate({:action => "destroy"}, {:controller => "people", :action => "show", :id => "7"}) + assert_equal "/people/7/destroy", url + end + + def test_use_static_path_when_possible + set.draw do |map| + map.connect 'about', :controller => "welcome", :action => "about" + map.connect ':controller/:action/:id' + end + + url = set.generate({:controller => "welcome", :action => "about"}, + {:controller => "welcome", :action => "get", :id => "7"}) + assert_equal "/about", url + end + + def test_generate + set.draw { |map| map.connect ':controller/:action/:id' } + + args = { :controller => "foo", :action => "bar", :id => "7", :x => "y" } + assert_equal "/foo/bar/7?x=y", set.generate(args) + assert_equal ["/foo/bar/7", [:x]], set.generate_extras(args) + assert_equal [:x], set.extra_keys(args) + end + + def test_named_routes_are_never_relative_to_modules + set.draw do |map| + map.connect "/connection/manage/:action", :controller => 'connection/manage' + map.connect "/connection/connection", :controller => "connection/connection" + map.family_connection "/connection", :controller => "connection" + end + + url = set.generate({:controller => "connection"}, {:controller => 'connection/manage'}) + assert_equal "/connection/connection", url + + url = set.generate({:use_route => :family_connection, :controller => "connection"}, {:controller => 'connection/manage'}) + assert_equal "/connection", url + end + + def test_action_left_off_when_id_is_recalled + set.draw do |map| + map.connect ':controller/:action/:id' + end + assert_equal '/post', set.generate( + {:controller => 'post', :action => 'index'}, + {:controller => 'post', :action => 'show', :id => '10'} + ) + end + + def test_query_params_will_be_shown_when_recalled + set.draw do |map| + map.connect 'show_post/:parameter', :controller => 'post', :action => 'show' + map.connect ':controller/:action/:id' + end + assert_equal '/post/edit?parameter=1', set.generate( + {:action => 'edit', :parameter => 1}, + {:controller => 'post', :action => 'show', :parameter => 1} + ) + end + + def test_expiry_determination_should_consider_values_with_to_param + set.draw { |map| map.connect 'projects/:project_id/:controller/:action' } + assert_equal '/projects/1/post/show', set.generate( + {:action => 'show', :project_id => 1}, + {:controller => 'post', :action => 'show', :project_id => '1'}) + end + + def test_generate_all + set.draw do |map| + map.connect 'show_post/:id', :controller => 'post', :action => 'show' + map.connect ':controller/:action/:id' + end + all = set.generate( + {:action => 'show', :id => 10, :generate_all => true}, + {:controller => 'post', :action => 'show'} + ) + assert_equal 2, all.length + assert_equal '/show_post/10', all.first + assert_equal '/post/show/10', all.last + end + + def test_named_route_in_nested_resource + set.draw do |map| + map.resources :projects do |project| + project.milestones 'milestones', :controller => 'milestones', :action => 'index' + end + end + + request.path = "/projects/1/milestones" + request.method = :get + assert_nothing_raised { set.recognize(request) } + assert_equal("milestones", request.path_parameters[:controller]) + assert_equal("index", request.path_parameters[:action]) + end + + def test_setting_root_in_namespace_using_symbol + assert_nothing_raised do + set.draw do |map| + map.namespace :admin do |admin| + admin.root :controller => 'home' + end + end + end + end + + def test_setting_root_in_namespace_using_string + assert_nothing_raised do + set.draw do |map| + map.namespace 'admin' do |admin| + admin.root :controller => 'home' + end + end + end + end + +end + +class RoutingTest < Test::Unit::TestCase + + def test_possible_controllers + true_controller_paths = ActionController::Routing.controller_paths + + ActionController::Routing.use_controllers! nil + + silence_warnings do + Object.send(:const_set, :RAILS_ROOT, File.dirname(__FILE__) + '/controller_fixtures') + end + + ActionController::Routing.controller_paths = [ + RAILS_ROOT, RAILS_ROOT + '/app/controllers', RAILS_ROOT + '/vendor/plugins/bad_plugin/lib' + ] + + assert_equal ["admin/user", "plugin", "user"], ActionController::Routing.possible_controllers.sort + ensure + if true_controller_paths + ActionController::Routing.controller_paths = true_controller_paths + end + ActionController::Routing.use_controllers! nil + Object.send(:remove_const, :RAILS_ROOT) rescue nil + end + + def test_possible_controllers_are_reset_on_each_load + true_possible_controllers = ActionController::Routing.possible_controllers + true_controller_paths = ActionController::Routing.controller_paths + + ActionController::Routing.use_controllers! nil + root = File.dirname(__FILE__) + '/controller_fixtures' + + ActionController::Routing.controller_paths = [] + assert_equal [], ActionController::Routing.possible_controllers + + ActionController::Routing::Routes.load! + ActionController::Routing.controller_paths = [ + root, root + '/app/controllers', root + '/vendor/plugins/bad_plugin/lib' + ] + + assert_equal ["admin/user", "plugin", "user"], ActionController::Routing.possible_controllers.sort + ensure + ActionController::Routing.controller_paths = true_controller_paths + ActionController::Routing.use_controllers! true_possible_controllers + Object.send(:remove_const, :RAILS_ROOT) rescue nil + + ActionController::Routing::Routes.clear! + ActionController::Routing::Routes.load_routes! + end + + def test_with_controllers + c = %w(admin/accounts admin/users account pages) + ActionController::Routing.with_controllers c do + assert_equal c, ActionController::Routing.possible_controllers + end + end + + def test_normalize_unix_paths + load_paths = %w(. config/../app/controllers config/../app//helpers script/../config/../vendor/rails/actionpack/lib vendor/rails/railties/builtin/rails_info app/models lib script/../config/../foo/bar/../../app/models) + paths = ActionController::Routing.normalize_paths(load_paths) + assert_equal %w(vendor/rails/railties/builtin/rails_info vendor/rails/actionpack/lib app/controllers app/helpers app/models lib .), paths + end + + def test_normalize_windows_paths + load_paths = %w(. config\\..\\app\\controllers config\\..\\app\\\\helpers script\\..\\config\\..\\vendor\\rails\\actionpack\\lib vendor\\rails\\railties\\builtin\\rails_info app\\models lib script\\..\\config\\..\\foo\\bar\\..\\..\\app\\models) + paths = ActionController::Routing.normalize_paths(load_paths) + assert_equal %w(vendor\\rails\\railties\\builtin\\rails_info vendor\\rails\\actionpack\\lib app\\controllers app\\helpers app\\models lib .), paths + end + + def test_routing_helper_module + assert_kind_of Module, ActionController::Routing::Helpers + + h = ActionController::Routing::Helpers + c = Class.new + assert ! c.ancestors.include?(h) + ActionController::Routing::Routes.install_helpers c + assert c.ancestors.include?(h) + end + +end + +uses_mocha 'route loading' do + class RouteLoadingTest < Test::Unit::TestCase + + def setup + routes.instance_variable_set '@routes_last_modified', nil + silence_warnings { Object.const_set :RAILS_ROOT, '.' } + + @stat = stub_everything + end + + def teardown + Object.send :remove_const, :RAILS_ROOT + end + + def test_load + File.expects(:stat).returns(@stat) + routes.expects(:load).with(regexp_matches(/routes\.rb$/)) + + routes.reload + end + + def test_no_reload_when_not_modified + @stat.expects(:mtime).times(2).returns(1) + File.expects(:stat).times(2).returns(@stat) + routes.expects(:load).with(regexp_matches(/routes\.rb$/)).at_most_once + + 2.times { routes.reload } + end + + def test_reload_when_modified + @stat.expects(:mtime).at_least(2).returns(1, 2) + File.expects(:stat).at_least(2).returns(@stat) + routes.expects(:load).with(regexp_matches(/routes\.rb$/)).times(2) + + 2.times { routes.reload } + end + + def test_bang_forces_reload + @stat.expects(:mtime).at_least(2).returns(1) + File.expects(:stat).at_least(2).returns(@stat) + routes.expects(:load).with(regexp_matches(/routes\.rb$/)).times(2) + + 2.times { routes.reload! } + end + + def test_adding_inflections_forces_reload + Inflector::Inflections.instance.expects(:uncountable).with('equipment') + routes.expects(:reload!) + + Inflector.inflections { |inflect| inflect.uncountable('equipment') } + end + + private + def routes + ActionController::Routing::Routes + end + + end +end diff --git a/vendor/rails-2.0.2/actionpack/test/controller/selector_test.rb b/vendor/rails-2.0.2/actionpack/test/controller/selector_test.rb new file mode 100644 index 000000000..ca106ba23 --- /dev/null +++ b/vendor/rails-2.0.2/actionpack/test/controller/selector_test.rb @@ -0,0 +1,628 @@ +#-- +# Copyright (c) 2006 Assaf Arkin (http://labnotes.org) +# Under MIT and/or CC By license. +#++ + +require "#{File.dirname(__FILE__)}/../abstract_unit" +require "#{File.dirname(__FILE__)}/fake_controllers" + +class SelectorTest < Test::Unit::TestCase + # + # Basic selector: element, id, class, attributes. + # + + def test_element + parse(%Q{<div id="1"></div><p></p><div id="2"></div>}) + # Match element by name. + select("div") + assert_equal 2, @matches.size + assert_equal "1", @matches[0].attributes["id"] + assert_equal "2", @matches[1].attributes["id"] + # Not case sensitive. + select("DIV") + assert_equal 2, @matches.size + assert_equal "1", @matches[0].attributes["id"] + assert_equal "2", @matches[1].attributes["id"] + # Universal match (all elements). + select("*") + assert_equal 3, @matches.size + assert_equal "1", @matches[0].attributes["id"] + assert_equal nil, @matches[1].attributes["id"] + assert_equal "2", @matches[2].attributes["id"] + end + + + def test_identifier + parse(%Q{<div id="1"></div><p></p><div id="2"></div>}) + # Match element by ID. + select("div#1") + assert_equal 1, @matches.size + assert_equal "1", @matches[0].attributes["id"] + # Match element by ID, substitute value. + select("div#?", 2) + assert_equal 1, @matches.size + assert_equal "2", @matches[0].attributes["id"] + # Element name does not match ID. + select("p#?", 2) + assert_equal 0, @matches.size + # Use regular expression. + select("#?", /\d/) + assert_equal 2, @matches.size + end + + + def test_class_name + parse(%Q{<div id="1" class=" foo "></div><p id="2" class=" foo bar "></p><div id="3" class="bar"></div>}) + # Match element with specified class. + select("div.foo") + assert_equal 1, @matches.size + assert_equal "1", @matches[0].attributes["id"] + # Match any element with specified class. + select("*.foo") + assert_equal 2, @matches.size + assert_equal "1", @matches[0].attributes["id"] + assert_equal "2", @matches[1].attributes["id"] + # Match elements with other class. + select("*.bar") + assert_equal 2, @matches.size + assert_equal "2", @matches[0].attributes["id"] + assert_equal "3", @matches[1].attributes["id"] + # Match only element with both class names. + select("*.bar.foo") + assert_equal 1, @matches.size + assert_equal "2", @matches[0].attributes["id"] + end + + + def test_attribute + parse(%Q{<div id="1"></div><p id="2" title="" bar="foo"></p><div id="3" title="foo"></div>}) + # Match element with attribute. + select("div[title]") + assert_equal 1, @matches.size + assert_equal "3", @matches[0].attributes["id"] + # Match any element with attribute. + select("*[title]") + assert_equal 2, @matches.size + assert_equal "2", @matches[0].attributes["id"] + assert_equal "3", @matches[1].attributes["id"] + # Match element with attribute value. + select("*[title=foo]") + assert_equal 1, @matches.size + assert_equal "3", @matches[0].attributes["id"] + # Match element with attribute and attribute value. + select("[bar=foo][title]") + assert_equal 1, @matches.size + assert_equal "2", @matches[0].attributes["id"] + # Not case sensitive. + select("[BAR=foo][TiTle]") + assert_equal 1, @matches.size + assert_equal "2", @matches[0].attributes["id"] + end + + + def test_attribute_quoted + parse(%Q{<div id="1" title="foo"></div><div id="2" title="bar"></div><div id="3" title=" bar "></div>}) + # Match without quotes. + select("[title = bar]") + assert_equal 1, @matches.size + assert_equal "2", @matches[0].attributes["id"] + # Match with single quotes. + select("[title = 'bar' ]") + assert_equal 1, @matches.size + assert_equal "2", @matches[0].attributes["id"] + # Match with double quotes. + select("[title = \"bar\" ]") + assert_equal 1, @matches.size + assert_equal "2", @matches[0].attributes["id"] + # Match with spaces. + select("[title = \" bar \" ]") + assert_equal 1, @matches.size + assert_equal "3", @matches[0].attributes["id"] + end + + + def test_attribute_equality + parse(%Q{<div id="1" title="foo bar"></div><div id="2" title="barbaz"></div>}) + # Match (fail) complete value. + select("[title=bar]") + assert_equal 0, @matches.size + # Match space-separate word. + select("[title~=foo]") + assert_equal 1, @matches.size + assert_equal "1", @matches[0].attributes["id"] + select("[title~=bar]") + assert_equal 1, @matches.size + assert_equal "1", @matches[0].attributes["id"] + # Match beginning of value. + select("[title^=ba]") + assert_equal 1, @matches.size + assert_equal "2", @matches[0].attributes["id"] + # Match end of value. + select("[title$=ar]") + assert_equal 1, @matches.size + assert_equal "1", @matches[0].attributes["id"] + # Match text in value. + select("[title*=bar]") + assert_equal 2, @matches.size + assert_equal "1", @matches[0].attributes["id"] + assert_equal "2", @matches[1].attributes["id"] + # Match first space separated word. + select("[title|=foo]") + assert_equal 1, @matches.size + assert_equal "1", @matches[0].attributes["id"] + select("[title|=bar]") + assert_equal 0, @matches.size + end + + + # + # Selector composition: groups, sibling, children + # + + + def test_selector_group + parse(%Q{<h1 id="1"></h1><h2 id="2"></h2><h3 id="3"></h3>}) + # Simple group selector. + select("h1,h3") + assert_equal 2, @matches.size + assert_equal "1", @matches[0].attributes["id"] + assert_equal "3", @matches[1].attributes["id"] + select("h1 , h3") + assert_equal 2, @matches.size + assert_equal "1", @matches[0].attributes["id"] + assert_equal "3", @matches[1].attributes["id"] + # Complex group selector. + parse(%Q{<h1 id="1"><a href="foo"></a></h1><h2 id="2"><a href="bar"></a></h2><h3 id="2"><a href="baz"></a></h3>}) + select("h1 a, h3 a") + assert_equal 2, @matches.size + assert_equal "foo", @matches[0].attributes["href"] + assert_equal "baz", @matches[1].attributes["href"] + # And now for the three selector challenge. + parse(%Q{<h1 id="1"><a href="foo"></a></h1><h2 id="2"><a href="bar"></a></h2><h3 id="2"><a href="baz"></a></h3>}) + select("h1 a, h2 a, h3 a") + assert_equal 3, @matches.size + assert_equal "foo", @matches[0].attributes["href"] + assert_equal "bar", @matches[1].attributes["href"] + assert_equal "baz", @matches[2].attributes["href"] + end + + + def test_sibling_selector + parse(%Q{<h1 id="1"></h1><h2 id="2"></h2><h3 id="3"></h3>}) + # Test next sibling. + select("h1+*") + assert_equal 1, @matches.size + assert_equal "2", @matches[0].attributes["id"] + select("h1+h2") + assert_equal 1, @matches.size + assert_equal "2", @matches[0].attributes["id"] + select("h1+h3") + assert_equal 0, @matches.size + select("*+h3") + assert_equal 1, @matches.size + assert_equal "3", @matches[0].attributes["id"] + # Test any sibling. + select("h1~*") + assert_equal 2, @matches.size + assert_equal "2", @matches[0].attributes["id"] + assert_equal "3", @matches[1].attributes["id"] + select("h2~*") + assert_equal 1, @matches.size + assert_equal "3", @matches[0].attributes["id"] + end + + + def test_children_selector + parse(%Q{<div><p id="1"><span id="2"></span></p></div><div><p id="3"><span id="4" class="foo"></span></p></div>}) + # Test child selector. + select("div>p") + assert_equal 2, @matches.size + assert_equal "1", @matches[0].attributes["id"] + assert_equal "3", @matches[1].attributes["id"] + select("div>span") + assert_equal 0, @matches.size + select("div>p#3") + assert_equal 1, @matches.size + assert_equal "3", @matches[0].attributes["id"] + select("div>p>span") + assert_equal 2, @matches.size + assert_equal "2", @matches[0].attributes["id"] + assert_equal "4", @matches[1].attributes["id"] + # Test descendant selector. + select("div p") + assert_equal 2, @matches.size + assert_equal "1", @matches[0].attributes["id"] + assert_equal "3", @matches[1].attributes["id"] + select("div span") + assert_equal 2, @matches.size + assert_equal "2", @matches[0].attributes["id"] + assert_equal "4", @matches[1].attributes["id"] + select("div *#3") + assert_equal 1, @matches.size + assert_equal "3", @matches[0].attributes["id"] + select("div *#4") + assert_equal 1, @matches.size + assert_equal "4", @matches[0].attributes["id"] + # This is here because it failed before when whitespaces + # were not properly stripped. + select("div .foo") + assert_equal 1, @matches.size + assert_equal "4", @matches[0].attributes["id"] + end + + + # + # Pseudo selectors: root, nth-child, empty, content, etc + # + + + def test_root_selector + parse(%Q{<div id="1"><div id="2"></div></div>}) + # Can only find element if it's root. + select(":root") + assert_equal 1, @matches.size + assert_equal "1", @matches[0].attributes["id"] + select("#1:root") + assert_equal 1, @matches.size + assert_equal "1", @matches[0].attributes["id"] + select("#2:root") + assert_equal 0, @matches.size + # Opposite for nth-child. + select("#1:nth-child(1)") + assert_equal 0, @matches.size + end + + + def test_nth_child_odd_even + parse(%Q{<table><tr id="1"></tr><tr id="2"></tr><tr id="3"></tr><tr id="4"></tr></table>}) + # Test odd nth children. + select("tr:nth-child(odd)") + assert_equal 2, @matches.size + assert_equal "1", @matches[0].attributes["id"] + assert_equal "3", @matches[1].attributes["id"] + # Test even nth children. + select("tr:nth-child(even)") + assert_equal 2, @matches.size + assert_equal "2", @matches[0].attributes["id"] + assert_equal "4", @matches[1].attributes["id"] + end + + + def test_nth_child_a_is_zero + parse(%Q{<table><tr id="1"></tr><tr id="2"></tr><tr id="3"></tr><tr id="4"></tr></table>}) + # Test the third child. + select("tr:nth-child(0n+3)") + assert_equal 1, @matches.size + assert_equal "3", @matches[0].attributes["id"] + # Same but an can be omitted when zero. + select("tr:nth-child(3)") + assert_equal 1, @matches.size + assert_equal "3", @matches[0].attributes["id"] + # Second element (but not every second element). + select("tr:nth-child(0n+2)") + assert_equal 1, @matches.size + assert_equal "2", @matches[0].attributes["id"] + # Before first and past last returns nothing.: + assert_raises(ArgumentError) { select("tr:nth-child(-1)") } + select("tr:nth-child(0)") + assert_equal 0, @matches.size + select("tr:nth-child(5)") + assert_equal 0, @matches.size + end + + + def test_nth_child_a_is_one + parse(%Q{<table><tr id="1"></tr><tr id="2"></tr><tr id="3"></tr><tr id="4"></tr></table>}) + # a is group of one, pick every element in group. + select("tr:nth-child(1n+0)") + assert_equal 4, @matches.size + # Same but a can be omitted when one. + select("tr:nth-child(n+0)") + assert_equal 4, @matches.size + # Same but b can be omitted when zero. + select("tr:nth-child(n)") + assert_equal 4, @matches.size + end + + + def test_nth_child_b_is_zero + parse(%Q{<table><tr id="1"></tr><tr id="2"></tr><tr id="3"></tr><tr id="4"></tr></table>}) + # If b is zero, pick the n-th element (here each one). + select("tr:nth-child(n+0)") + assert_equal 4, @matches.size + # If b is zero, pick the n-th element (here every second). + select("tr:nth-child(2n+0)") + assert_equal 2, @matches.size + assert_equal "1", @matches[0].attributes["id"] + assert_equal "3", @matches[1].attributes["id"] + # If a and b are both zero, no element selected. + select("tr:nth-child(0n+0)") + assert_equal 0, @matches.size + select("tr:nth-child(0)") + assert_equal 0, @matches.size + end + + + def test_nth_child_a_is_negative + parse(%Q{<table><tr id="1"></tr><tr id="2"></tr><tr id="3"></tr><tr id="4"></tr></table>}) + # Since a is -1, picks the first three elements. + select("tr:nth-child(-n+3)") + assert_equal 3, @matches.size + assert_equal "1", @matches[0].attributes["id"] + assert_equal "2", @matches[1].attributes["id"] + assert_equal "3", @matches[2].attributes["id"] + # Since a is -2, picks the first in every second of first four elements. + select("tr:nth-child(-2n+3)") + assert_equal 2, @matches.size + assert_equal "1", @matches[0].attributes["id"] + assert_equal "3", @matches[1].attributes["id"] + # Since a is -2, picks the first in every second of first three elements. + select("tr:nth-child(-2n+2)") + assert_equal 1, @matches.size + assert_equal "1", @matches[0].attributes["id"] + end + + + def test_nth_child_b_is_negative + parse(%Q{<table><tr id="1"></tr><tr id="2"></tr><tr id="3"></tr><tr id="4"></tr></table>}) + # Select last of four. + select("tr:nth-child(4n-1)") + assert_equal 1, @matches.size + assert_equal "4", @matches[0].attributes["id"] + # Select first of four. + select("tr:nth-child(4n-4)") + assert_equal 1, @matches.size + assert_equal "1", @matches[0].attributes["id"] + # Select last of every second. + select("tr:nth-child(2n-1)") + assert_equal 2, @matches.size + assert_equal "2", @matches[0].attributes["id"] + assert_equal "4", @matches[1].attributes["id"] + # Select nothing since an+b always < 0 + select("tr:nth-child(-1n-1)") + assert_equal 0, @matches.size + end + + + def test_nth_child_substitution_values + parse(%Q{<table><tr id="1"></tr><tr id="2"></tr><tr id="3"></tr><tr id="4"></tr></table>}) + # Test with ?n?. + select("tr:nth-child(?n?)", 2, 1) + assert_equal 2, @matches.size + assert_equal "1", @matches[0].attributes["id"] + assert_equal "3", @matches[1].attributes["id"] + select("tr:nth-child(?n?)", 2, 2) + assert_equal 2, @matches.size + assert_equal "2", @matches[0].attributes["id"] + assert_equal "4", @matches[1].attributes["id"] + select("tr:nth-child(?n?)", 4, 2) + assert_equal 1, @matches.size + assert_equal "2", @matches[0].attributes["id"] + # Test with ? (b only). + select("tr:nth-child(?)", 3) + assert_equal 1, @matches.size + assert_equal "3", @matches[0].attributes["id"] + select("tr:nth-child(?)", 5) + assert_equal 0, @matches.size + end + + + def test_nth_last_child + parse(%Q{<table><tr id="1"></tr><tr id="2"></tr><tr id="3"></tr><tr id="4"></tr></table>}) + # Last two elements. + select("tr:nth-last-child(-n+2)") + assert_equal 2, @matches.size + assert_equal "3", @matches[0].attributes["id"] + assert_equal "4", @matches[1].attributes["id"] + # All old elements counting from last one. + select("tr:nth-last-child(odd)") + assert_equal 2, @matches.size + assert_equal "2", @matches[0].attributes["id"] + assert_equal "4", @matches[1].attributes["id"] + end + + + def test_nth_of_type + parse(%Q{<table><thead></thead><tr id="1"></tr><tr id="2"></tr><tr id="3"></tr><tr id="4"></tr></table>}) + # First two elements. + select("tr:nth-of-type(-n+2)") + assert_equal 2, @matches.size + assert_equal "1", @matches[0].attributes["id"] + assert_equal "2", @matches[1].attributes["id"] + # All old elements counting from last one. + select("tr:nth-last-of-type(odd)") + assert_equal 2, @matches.size + assert_equal "2", @matches[0].attributes["id"] + assert_equal "4", @matches[1].attributes["id"] + end + + + def test_first_and_last + parse(%Q{<table><thead></thead><tr id="1"></tr><tr id="2"></tr><tr id="3"></tr><tr id="4"></tr></table>}) + # First child. + select("tr:first-child") + assert_equal 0, @matches.size + select(":first-child") + assert_equal 1, @matches.size + assert_equal "thead", @matches[0].name + # First of type. + select("tr:first-of-type") + assert_equal 1, @matches.size + assert_equal "1", @matches[0].attributes["id"] + select("thead:first-of-type") + assert_equal 1, @matches.size + assert_equal "thead", @matches[0].name + select("div:first-of-type") + assert_equal 0, @matches.size + # Last child. + select("tr:last-child") + assert_equal 1, @matches.size + assert_equal "4", @matches[0].attributes["id"] + # Last of type. + select("tr:last-of-type") + assert_equal 1, @matches.size + assert_equal "4", @matches[0].attributes["id"] + select("thead:last-of-type") + assert_equal 1, @matches.size + assert_equal "thead", @matches[0].name + select("div:last-of-type") + assert_equal 0, @matches.size + end + + + def test_first_and_last + # Only child. + parse(%Q{<table><tr></tr></table>}) + select("table:only-child") + assert_equal 0, @matches.size + select("tr:only-child") + assert_equal 1, @matches.size + assert_equal "tr", @matches[0].name + parse(%Q{<table><tr></tr><tr></tr></table>}) + select("tr:only-child") + assert_equal 0, @matches.size + # Only of type. + parse(%Q{<table><thead></thead><tr></tr><tr></tr></table>}) + select("thead:only-of-type") + assert_equal 1, @matches.size + assert_equal "thead", @matches[0].name + select("td:only-of-type") + assert_equal 0, @matches.size + end + + + def test_empty + parse(%Q{<table><tr></tr></table>}) + select("table:empty") + assert_equal 0, @matches.size + select("tr:empty") + assert_equal 1, @matches.size + parse(%Q{<div> </div>}) + select("div:empty") + assert_equal 1, @matches.size + end + + + def test_content + parse(%Q{<div> </div>}) + select("div:content()") + assert_equal 1, @matches.size + parse(%Q{<div>something </div>}) + select("div:content()") + assert_equal 0, @matches.size + select("div:content(something)") + assert_equal 1, @matches.size + select("div:content( 'something' )") + assert_equal 1, @matches.size + select("div:content( \"something\" )") + assert_equal 1, @matches.size + select("div:content(?)", "something") + assert_equal 1, @matches.size + select("div:content(?)", /something/) + assert_equal 1, @matches.size + end + + + # + # Test negation. + # + + + def test_element_negation + parse(%Q{<p></p><div></div>}) + select("*") + assert_equal 2, @matches.size + select("*:not(p)") + assert_equal 1, @matches.size + assert_equal "div", @matches[0].name + select("*:not(div)") + assert_equal 1, @matches.size + assert_equal "p", @matches[0].name + select("*:not(span)") + assert_equal 2, @matches.size + end + + + def test_id_negation + parse(%Q{<p id="1"></p><p id="2"></p>}) + select("p") + assert_equal 2, @matches.size + select(":not(#1)") + assert_equal 1, @matches.size + assert_equal "2", @matches[0].attributes["id"] + select(":not(#2)") + assert_equal 1, @matches.size + assert_equal "1", @matches[0].attributes["id"] + end + + + def test_class_name_negation + parse(%Q{<p class="foo"></p><p class="bar"></p>}) + select("p") + assert_equal 2, @matches.size + select(":not(.foo)") + assert_equal 1, @matches.size + assert_equal "bar", @matches[0].attributes["class"] + select(":not(.bar)") + assert_equal 1, @matches.size + assert_equal "foo", @matches[0].attributes["class"] + end + + + def test_attribute_negation + parse(%Q{<p title="foo"></p><p title="bar"></p>}) + select("p") + assert_equal 2, @matches.size + select(":not([title=foo])") + assert_equal 1, @matches.size + assert_equal "bar", @matches[0].attributes["title"] + select(":not([title=bar])") + assert_equal 1, @matches.size + assert_equal "foo", @matches[0].attributes["title"] + end + + + def test_pseudo_class_negation + parse(%Q{<div><p id="1"></p><p id="2"></p></div>}) + select("p") + assert_equal 2, @matches.size + select("p:not(:first-child)") + assert_equal 1, @matches.size + assert_equal "2", @matches[0].attributes["id"] + select("p:not(:nth-child(2))") + assert_equal 1, @matches.size + assert_equal "1", @matches[0].attributes["id"] + end + + + def test_negation_details + parse(%Q{<p id="1"></p><p id="2"></p><p id="3"></p>}) + assert_raises(ArgumentError) { select(":not(") } + assert_raises(ArgumentError) { select(":not(:not())") } + select("p:not(#1):not(#3)") + assert_equal 1, @matches.size + assert_equal "2", @matches[0].attributes["id"] + end + + + def test_select_from_element + parse(%Q{<div><p id="1"></p><p id="2"></p></div>}) + select("div") + @matches = @matches[0].select("p") + assert_equal 2, @matches.size + assert_equal "1", @matches[0].attributes["id"] + assert_equal "2", @matches[1].attributes["id"] + end + + +protected + + def parse(html) + @html = HTML::Document.new(html).root + end + + def select(*selector) + @matches = HTML.selector(*selector).select(@html) + end + +end diff --git a/vendor/rails-2.0.2/actionpack/test/controller/send_file_test.rb b/vendor/rails-2.0.2/actionpack/test/controller/send_file_test.rb new file mode 100644 index 000000000..2d876c1bb --- /dev/null +++ b/vendor/rails-2.0.2/actionpack/test/controller/send_file_test.rb @@ -0,0 +1,127 @@ +require File.join(File.dirname(__FILE__), '..', 'abstract_unit') + + +module TestFileUtils + def file_name() File.basename(__FILE__) end + def file_path() File.expand_path(__FILE__) end + def file_data() File.open(file_path, 'rb') { |f| f.read } end +end + + +class SendFileController < ActionController::Base + include TestFileUtils + layout "layouts/standard" # to make sure layouts don't interfere + + attr_writer :options + def options() @options ||= {} end + + def file() send_file(file_path, options) end + def data() send_data(file_data, options) end + + def rescue_action(e) raise end +end + +SendFileController.view_paths = [ File.dirname(__FILE__) + "/../fixtures/" ] + +class SendFileTest < Test::Unit::TestCase + include TestFileUtils + + Mime::Type.register "image/png", :png unless defined? Mime::PNG + + def setup + @controller = SendFileController.new + @request = ActionController::TestRequest.new + @response = ActionController::TestResponse.new + end + + def test_file_nostream + @controller.options = { :stream => false } + response = nil + assert_nothing_raised { response = process('file') } + assert_not_nil response + assert_kind_of String, response.body + assert_equal file_data, response.body + end + + def test_file_stream + response = nil + assert_nothing_raised { response = process('file') } + assert_not_nil response + assert_kind_of Proc, response.body + + require 'stringio' + output = StringIO.new + output.binmode + assert_nothing_raised { response.body.call(response, output) } + assert_equal file_data, output.string + end + + def test_file_url_based_filename + @controller.options = { :url_based_filename => true } + response = nil + assert_nothing_raised { response = process('file') } + assert_not_nil response + assert_equal "attachment", response.headers["Content-Disposition"] + end + + def test_data + response = nil + assert_nothing_raised { response = process('data') } + assert_not_nil response + + assert_kind_of String, response.body + assert_equal file_data, response.body + end + + def test_headers_after_send_shouldnt_include_charset + response = process('data') + assert_equal "application/octet-stream", response.content_type + + response = process('file') + assert_equal "application/octet-stream", response.content_type + end + + # Test that send_file_headers! is setting the correct HTTP headers. + def test_send_file_headers! + options = { + :length => 1, + :type => Mime::PNG, + :disposition => 'disposition', + :filename => 'filename' + } + + # Do it a few times: the resulting headers should be identical + # no matter how many times you send with the same options. + # Test resolving Ticket #458. + @controller.headers = {} + @controller.send(:send_file_headers!, options) + @controller.send(:send_file_headers!, options) + @controller.send(:send_file_headers!, options) + + h = @controller.headers + assert_equal 1, h['Content-Length'] + assert_equal 'image/png', h['Content-Type'] + assert_equal 'disposition; filename="filename"', h['Content-Disposition'] + assert_equal 'binary', h['Content-Transfer-Encoding'] + + # test overriding Cache-Control: no-cache header to fix IE open/save dialog + @controller.headers = { 'Cache-Control' => 'no-cache' } + @controller.send(:send_file_headers!, options) + h = @controller.headers + assert_equal 'private', h['Cache-Control'] + end + + %w(file data).each do |method| + define_method "test_send_#{method}_status" do + @controller.options = { :stream => false, :status => 500 } + assert_nothing_raised { assert_not_nil process(method) } + assert_equal '500 Internal Server Error', @response.headers['Status'] + end + + define_method "test_default_send_#{method}_status" do + @controller.options = { :stream => false } + assert_nothing_raised { assert_not_nil process(method) } + assert_equal ActionController::Base::DEFAULT_RENDER_STATUS_CODE, @response.headers['Status'] + end + end +end diff --git a/vendor/rails-2.0.2/actionpack/test/controller/session/cookie_store_test.rb b/vendor/rails-2.0.2/actionpack/test/controller/session/cookie_store_test.rb new file mode 100755 index 000000000..b2655c72d --- /dev/null +++ b/vendor/rails-2.0.2/actionpack/test/controller/session/cookie_store_test.rb @@ -0,0 +1,246 @@ +require "#{File.dirname(__FILE__)}/../../abstract_unit" +require 'action_controller/cgi_process' +require 'action_controller/cgi_ext' + +require 'stringio' + + +class CGI::Session::CookieStore + def ensure_secret_secure_with_test_hax(secret) + if secret == CookieStoreTest.default_session_options['secret'] + return true + else + ensure_secret_secure_without_test_hax(secret) + end + end + alias_method_chain :ensure_secret_secure, :test_hax +end + + +# Expose for tests. +class CGI + attr_reader :output_cookies, :output_hidden + + class Session + attr_reader :dbman + + class CookieStore + attr_reader :data, :original, :cookie_options + end + end +end + +class CookieStoreTest < Test::Unit::TestCase + def self.default_session_options + { 'database_manager' => CGI::Session::CookieStore, + 'session_key' => '_myapp_session', + 'secret' => 'Keep it secret; keep it safe.', + 'no_cookies' => true, + 'no_hidden' => true } + end + + def self.cookies + { :empty => ['BAgw--0686dcaccc01040f4bd4f35fe160afe9bc04c330', {}], + :a_one => ['BAh7BiIGYWkG--5689059497d7f122a7119f171aef81dcfd807fec', { 'a' => 1 }], + :typical => ['BAh7ByIMdXNlcl9pZGkBeyIKZmxhc2h7BiILbm90aWNlIgxIZXkgbm93--9d20154623b9eeea05c62ab819be0e2483238759', { 'user_id' => 123, 'flash' => { 'notice' => 'Hey now' }}], + :flashed => ['BAh7ByIMdXNlcl9pZGkBeyIKZmxhc2h7AA%3D%3D--bf9785a666d3c4ac09f7fe3353496b437546cfbf', { 'user_id' => 123, 'flash' => {} }] } + end + + def setup + ENV.delete('HTTP_COOKIE') + end + + def test_raises_argument_error_if_missing_session_key + [nil, ''].each do |blank| + assert_raise(ArgumentError, blank.inspect) { new_session 'session_key' => blank } + end + end + + def test_raises_argument_error_if_missing_secret + [nil, ''].each do |blank| + assert_raise(ArgumentError, blank.inspect) { new_session 'secret' => blank } + end + end + + def test_raises_argument_error_if_secret_is_probably_insecure + ["password", "secret", "12345678901234567890123456789"].each do |blank| + assert_raise(ArgumentError, blank.inspect) { new_session 'secret' => blank } + end + end + + def test_reconfigures_session_to_omit_id_cookie_and_hidden_field + new_session do |session| + assert_equal true, @options['no_hidden'] + assert_equal true, @options['no_cookies'] + end + end + + def test_restore_unmarshals_missing_cookie_as_empty_hash + new_session do |session| + assert_nil session.dbman.data + assert_nil session['test'] + assert_equal Hash.new, session.dbman.data + end + end + + def test_restore_unmarshals_good_cookies + cookies(:empty, :a_one, :typical).each do |value, expected| + set_cookie! value + new_session do |session| + assert_nil session['lazy loads the data hash'] + assert_equal expected, session.dbman.data + end + end + end + + def test_restore_deletes_tampered_cookies + set_cookie! 'a--b' + new_session do |session| + assert_raise(CGI::Session::CookieStore::TamperedWithCookie) { session['fail'] } + assert_cookie_deleted session + end + end + + def test_close_doesnt_write_cookie_if_data_is_blank + new_session do |session| + assert_no_cookies session + session.close + assert_no_cookies session + end + end + + def test_close_doesnt_write_cookie_if_data_is_unchanged + set_cookie! cookie_value(:typical) + new_session do |session| + assert_no_cookies session + session['user_id'] = session['user_id'] + session.close + assert_no_cookies session + end + end + + def test_close_raises_when_data_overflows + set_cookie! cookie_value(:empty) + new_session do |session| + session['overflow'] = 'bye!' * 1024 + assert_raise(CGI::Session::CookieStore::CookieOverflow) { session.close } + assert_no_cookies session + end + end + + def test_close_marshals_and_writes_cookie + set_cookie! cookie_value(:typical) + new_session do |session| + assert_no_cookies session + session['flash'] = {} + assert_no_cookies session + session.close + assert_equal 1, session.cgi.output_cookies.size + cookie = session.cgi.output_cookies.first + assert_cookie cookie, cookie_value(:flashed) + end + end + + def test_delete_writes_expired_empty_cookie_and_sets_data_to_nil + set_cookie! cookie_value(:typical) + new_session do |session| + assert_no_cookies session + session.delete + assert_cookie_deleted session + + # @data is set to nil so #close doesn't send another cookie. + session.close + assert_cookie_deleted session + end + end + + def test_new_session_doesnt_reuse_deleted_cookie_data + set_cookie! cookie_value(:typical) + + new_session do |session| + assert_not_nil session['user_id'] + session.delete + + # Start a new session using the same CGI instance. + post_delete_session = CGI::Session.new(session.cgi, self.class.default_session_options) + assert_nil post_delete_session['user_id'] + end + end + + private + def assert_no_cookies(session) + assert_nil session.cgi.output_cookies, session.cgi.output_cookies.inspect + end + + def assert_cookie_deleted(session, message = 'Expected session deletion cookie to be set') + assert_equal 1, session.cgi.output_cookies.size + cookie = session.cgi.output_cookies.first + assert_cookie cookie, nil, 1.year.ago.to_date, message + end + + def assert_cookie(cookie, value = nil, expires = nil, message = nil) + assert_equal '_myapp_session', cookie.name, message + assert_equal [value].compact, cookie.value, message + assert_equal expires, cookie.expires ? cookie.expires.to_date : cookie.expires, message + end + + + def cookies(*which) + self.class.cookies.values_at(*which) + end + + def cookie_value(which) + self.class.cookies[which].first + end + + def set_cookie!(value) + ENV['HTTP_COOKIE'] = "_myapp_session=#{value}" + end + + def new_session(options = {}) + with_cgi do |cgi| + assert_nil cgi.output_hidden, "Output hidden params should be empty: #{cgi.output_hidden.inspect}" + assert_nil cgi.output_cookies, "Output cookies should be empty: #{cgi.output_cookies.inspect}" + + @options = self.class.default_session_options.merge(options) + session = CGI::Session.new(cgi, @options) + + assert_nil cgi.output_hidden, "Output hidden params should be empty: #{cgi.output_hidden.inspect}" + assert_nil cgi.output_cookies, "Output cookies should be empty: #{cgi.output_cookies.inspect}" + + yield session if block_given? + session + end + end + + def with_cgi + ENV['REQUEST_METHOD'] = 'GET' + ENV['HTTP_HOST'] = 'example.com' + ENV['QUERY_STRING'] = '' + + cgi = CGI.new('query', StringIO.new('')) + yield cgi if block_given? + cgi + end +end + + +class CookieStoreWithBlockAsSecretTest < CookieStoreTest + def self.default_session_options + CookieStoreTest.default_session_options.merge 'secret' => Proc.new { 'Keep it secret; keep it safe.' } + end +end + + +class CookieStoreWithMD5DigestTest < CookieStoreTest + def self.default_session_options + CookieStoreTest.default_session_options.merge 'digest' => 'MD5' + end + + def self.cookies + { :empty => ['BAgw--0415cc0be9579b14afc22ee2d341aa21', {}], + :a_one => ['BAh7BiIGYWkG--5a0ed962089cc6600ff44168a5d59bc8', { 'a' => 1 }], + :typical => ['BAh7ByIMdXNlcl9pZGkBeyIKZmxhc2h7BiILbm90aWNlIgxIZXkgbm93--f426763f6ef435b3738b493600db8d64', { 'user_id' => 123, 'flash' => { 'notice' => 'Hey now' }}], + :flashed => ['BAh7ByIMdXNlcl9pZGkBeyIKZmxhc2h7AA%3D%3D--0af9156650dab044a53a91a4ddec2c51', { 'user_id' => 123, 'flash' => {} }] } + end +end diff --git a/vendor/rails-2.0.2/actionpack/test/controller/session/mem_cache_store_test.rb b/vendor/rails-2.0.2/actionpack/test/controller/session/mem_cache_store_test.rb new file mode 100644 index 000000000..3afb7a8ea --- /dev/null +++ b/vendor/rails-2.0.2/actionpack/test/controller/session/mem_cache_store_test.rb @@ -0,0 +1,182 @@ +require "#{File.dirname(__FILE__)}/../../abstract_unit" +require 'action_controller/cgi_process' +require 'action_controller/cgi_ext' + + +class CGI::Session + def cache + dbman.instance_variable_get(:@cache) + end +end + + +uses_mocha 'MemCacheStore tests' do +if defined? MemCache::MemCacheError + +class MemCacheStoreTest < Test::Unit::TestCase + SESSION_KEY_RE = /^session:[0-9a-z]+/ + CONN_TEST_KEY = 'connection_test' + MULTI_TEST_KEY = '0123456789' + TEST_DATA = 'Hello test' + + def self.get_mem_cache_if_available + begin + require 'memcache' + cache = MemCache.new('127.0.0.1') + # Test availability of the connection + cache.set(CONN_TEST_KEY, 1) + unless cache.get(CONN_TEST_KEY) == 1 + puts 'Warning: memcache server available but corrupted.' + return nil + end + rescue LoadError, MemCache::MemCacheError + return nil + end + return cache + end + + CACHE = get_mem_cache_if_available + + + def test_initialization + assert_raise(ArgumentError) { new_session('session_id' => '!invalid_id') } + new_session do |s| + assert_equal Hash.new, s.cache.get('session:' + s.session_id) + end + end + + + def test_storage + d = rand(0xffff) + new_session do |s| + session_key = 'session:' + s.session_id + unless CACHE + s.cache.expects(:get).with(session_key) \ + .returns(:test => d) + s.cache.expects(:set).with(session_key, + has_entry(:test, d), + 0) + end + s[:test] = d + s.close + assert_equal d, s.cache.get(session_key)[:test] + assert_equal d, s[:test] + end + end + + + def test_deletion + new_session do |s| + session_key = 'session:' + s.session_id + unless CACHE + s.cache.expects(:delete) + s.cache.expects(:get).with(session_key) \ + .returns(nil) + end + s[:test] = rand(0xffff) + s.delete + assert_nil s.cache.get(session_key) + end + end + + + def test_other_session_retrieval + new_session do |sa| + unless CACHE + sa.cache.expects(:set).with('session:' + sa.session_id, + has_entry(:test, TEST_DATA), + 0) + end + sa[:test] = TEST_DATA + sa.close + new_session('session_id' => sa.session_id) do |sb| + unless CACHE + sb.cache.expects(:[]).with('session:' + sb.session_id) \ + .returns(:test => TEST_DATA) + end + assert_equal(TEST_DATA, sb[:test]) + end + end + end + + + def test_multiple_sessions + s_slots = Array.new(10) + operation = :write + last_data = nil + reads = writes = 0 + 50.times do + current = rand(10) + s_slots[current] ||= new_session('session_id' => MULTI_TEST_KEY, + 'new_session' => true) + s = s_slots[current] + case operation + when :write + last_data = rand(0xffff) + unless CACHE + s.cache.expects(:set).with('session:' + MULTI_TEST_KEY, + { :test => last_data }, + 0) + end + s[:test] = last_data + s.close + writes += 1 + when :read + # Make CGI::Session#[] think there was no data retrieval yet. + # Normally, the session caches the data during its lifetime. + s.instance_variable_set(:@data, nil) + unless CACHE + s.cache.expects(:[]).with('session:' + MULTI_TEST_KEY) \ + .returns(:test => last_data) + end + d = s[:test] + assert_equal(last_data, d, "OK reads: #{reads}, OK writes: #{writes}") + reads += 1 + end + operation = rand(5) == 0 ? :write : :read + end + end + + + + private + def obtain_session_options + options = { 'database_manager' => CGI::Session::MemCacheStore, + 'session_key' => '_test_app_session' + } + # if don't have running memcache server we use mock instead + unless CACHE + options['cache'] = c = mock + c.stubs(:[]).with(regexp_matches(SESSION_KEY_RE)) + c.stubs(:get).with(regexp_matches(SESSION_KEY_RE)) \ + .returns(Hash.new) + c.stubs(:add).with(regexp_matches(SESSION_KEY_RE), + instance_of(Hash), + 0) + end + options + end + + + def new_session(options = {}) + with_cgi do |cgi| + @options = obtain_session_options.merge(options) + session = CGI::Session.new(cgi, @options) + yield session if block_given? + return session + end + end + + def with_cgi + ENV['REQUEST_METHOD'] = 'GET' + ENV['HTTP_HOST'] = 'example.com' + ENV['QUERY_STRING'] = '' + + cgi = CGI.new('query', StringIO.new('')) + yield cgi if block_given? + cgi + end +end + +end # defined? MemCache +end # uses_mocha diff --git a/vendor/rails-2.0.2/actionpack/test/controller/session_fixation_test.rb b/vendor/rails-2.0.2/actionpack/test/controller/session_fixation_test.rb new file mode 100644 index 000000000..34a7aa2d0 --- /dev/null +++ b/vendor/rails-2.0.2/actionpack/test/controller/session_fixation_test.rb @@ -0,0 +1,89 @@ +require File.dirname(__FILE__) + '/../abstract_unit' + + +class SessionFixationTest < Test::Unit::TestCase + class MockCGI < CGI #:nodoc: + attr_accessor :stdoutput, :env_table + + def initialize(env, data = '') + self.env_table = env + self.stdoutput = StringIO.new + super(nil, StringIO.new(data)) + end + end + + class TestController < ActionController::Base + session :session_key => '_myapp_session_id', :secret => CGI::Session.generate_unique_id, :except => :default_session_key + session :cookie_only => false, :only => :allow_session_fixation + + def default_session_key + render :text => "default_session_key" + end + + def custom_session_key + render :text => "custom_session_key: #{params[:id]}" + end + + def allow_session_fixation + render :text => "allow_session_fixation" + end + + def rescue_action(e) raise end + end + + def setup + @controller = TestController.new + end + + def test_should_be_able_to_make_a_successful_request + cgi = mock_cgi_for_request_to(:custom_session_key, :id => 1) + + assert_nothing_raised do + @controller.send(:process, ActionController::CgiRequest.new(cgi, {}), ActionController::CgiResponse.new(cgi)) + end + assert_equal 'custom_session_key: 1', @controller.response.body + assert_not_nil @controller.session + end + + def test_should_catch_session_fixation_attempt + cgi = mock_cgi_for_request_to(:custom_session_key, :_myapp_session_id => 42) + + assert_raises ActionController::CgiRequest::SessionFixationAttempt do + @controller.send(:process, ActionController::CgiRequest.new(cgi, {}), ActionController::CgiResponse.new(cgi)) + end + assert_nil @controller.session + end + + def test_should_not_catch_session_fixation_attempt_when_cookie_only_setting_is_disabled + cgi = mock_cgi_for_request_to(:allow_session_fixation, :_myapp_session_id => 42) + + assert_nothing_raised do + @controller.send(:process, ActionController::CgiRequest.new(cgi, {}), ActionController::CgiResponse.new(cgi)) + end + assert ! @controller.response.body.blank? + assert_not_nil @controller.session + end + + def test_should_catch_session_fixation_attempt_with_default_session_key + ActionController::Base.session_store = :p_store # using the default session_key is not possible with cookie store + cgi = mock_cgi_for_request_to(:default_session_key, :_session_id => 42) + + assert_raises ActionController::CgiRequest::SessionFixationAttempt do + @controller.send(:process, ActionController::CgiRequest.new(cgi, {}), ActionController::CgiResponse.new(cgi)) + end + assert @controller.response.body.blank? + assert_nil @controller.session + end + +private + + def mock_cgi_for_request_to(action, params = {}) + MockCGI.new({ + "REQUEST_METHOD" => "GET", + "QUERY_STRING" => "action=#{action}&#{params.to_query}", + "REQUEST_URI" => "/", + "SERVER_PORT" => "80", + "HTTP_HOST" => "testdomain.com" }, '') + end + +end diff --git a/vendor/rails-2.0.2/actionpack/test/controller/session_management_test.rb b/vendor/rails-2.0.2/actionpack/test/controller/session_management_test.rb new file mode 100644 index 000000000..44fb93104 --- /dev/null +++ b/vendor/rails-2.0.2/actionpack/test/controller/session_management_test.rb @@ -0,0 +1,156 @@ +require File.dirname(__FILE__) + '/../abstract_unit' + +class SessionManagementTest < Test::Unit::TestCase + class SessionOffController < ActionController::Base + session :off + + def show + render :text => "done" + end + + def tell + render :text => "done" + end + end + + class TestController < ActionController::Base + session :off, :only => :show + session :session_secure => true, :except => :show + session :off, :only => :conditional, + :if => Proc.new { |r| r.parameters[:ws] } + + def show + render :text => "done" + end + + def tell + render :text => "done" + end + + def conditional + render :text => ">>>#{params[:ws]}<<<" + end + end + + class SpecializedController < SessionOffController + session :disabled => false, :only => :something + + def something + render :text => "done" + end + + def another + render :text => "done" + end + end + + class AssociationCachingTestController < ActionController::Base + class ObjectWithAssociationCache + def initialize + @cached_associations = false + end + + def fetch_associations + @cached_associations = true + end + + def clear_association_cache + @cached_associations = false + end + + def has_cached_associations? + @cached_associations + end + end + + def show + session[:object] = ObjectWithAssociationCache.new + session[:object].fetch_associations + if session[:object].has_cached_associations? + render :text => "has cached associations" + else + render :text => "does not have cached associations" + end + end + + def tell + if session[:object] + if session[:object].has_cached_associations? + render :text => "has cached associations" + else + render :text => "does not have cached associations" + end + else + render :text => "there is no object" + end + end + end + + + def setup + @request, @response = ActionController::TestRequest.new, + ActionController::TestResponse.new + end + + def test_session_off_globally + @controller = SessionOffController.new + get :show + assert_equal false, @request.session_options + get :tell + assert_equal false, @request.session_options + end + + def test_session_off_conditionally + @controller = TestController.new + get :show + assert_equal false, @request.session_options + get :tell + assert_instance_of Hash, @request.session_options + assert @request.session_options[:session_secure] + end + + def test_controller_specialization_overrides_settings + @controller = SpecializedController.new + get :something + assert_instance_of Hash, @request.session_options + get :another + assert_equal false, @request.session_options + end + + def test_session_off_with_if + @controller = TestController.new + get :conditional + assert_instance_of Hash, @request.session_options + get :conditional, :ws => "ws" + assert_equal false, @request.session_options + end + + def test_session_store_setting + ActionController::Base.session_store = :drb_store + assert_equal CGI::Session::DRbStore, ActionController::Base.session_store + + if Object.const_defined?(:ActiveRecord) + ActionController::Base.session_store = :active_record_store + assert_equal CGI::Session::ActiveRecordStore, ActionController::Base.session_store + end + end + + def test_process_cleanup_with_session_management_support + @controller = AssociationCachingTestController.new + get :show + assert_equal "has cached associations", @response.body + get :tell + assert_equal "does not have cached associations", @response.body + end + + def test_session_is_enabled + @controller = TestController.new + get :show + assert_nothing_raised do + assert_equal false, @controller.session_enabled? + end + + get :tell + assert @controller.session_enabled? + end +end diff --git a/vendor/rails-2.0.2/actionpack/test/controller/test_test.rb b/vendor/rails-2.0.2/actionpack/test/controller/test_test.rb new file mode 100644 index 000000000..11e48da91 --- /dev/null +++ b/vendor/rails-2.0.2/actionpack/test/controller/test_test.rb @@ -0,0 +1,623 @@ +require "#{File.dirname(__FILE__)}/../abstract_unit" +require "#{File.dirname(__FILE__)}/fake_controllers" +require "action_controller/test_case" + +class TestTest < Test::Unit::TestCase + class TestController < ActionController::Base + def set_flash + flash["test"] = ">#{flash["test"]}<" + render :text => 'ignore me' + end + + def render_raw_post + raise Test::Unit::AssertionFailedError, "#raw_post is blank" if request.raw_post.blank? + render :text => request.raw_post + end + + def render_body + render :text => request.body.read + end + + def test_params + render :text => params.inspect + end + + def test_uri + render :text => request.request_uri + end + + def test_query_string + render :text => request.query_string + end + + def test_html_output + render :text => <<HTML +<html> + <body> + <a href="/"><img src="/images/button.png" /></a> + <div id="foo"> + <ul> + <li class="item">hello</li> + <li class="item">goodbye</li> + </ul> + </div> + <div id="bar"> + <form action="/somewhere"> + Name: <input type="text" name="person[name]" id="person_name" /> + </form> + </div> + </body> +</html> +HTML + end + + def test_xml_output + response.content_type = "application/xml" + render :text => <<XML +<?xml version="1.0" encoding="UTF-8"?> +<root> + <area>area is an empty tag in HTML, raising an error if not in xml mode</area> +</root> +XML + end + + def test_only_one_param + render :text => (params[:left] && params[:right]) ? "EEP, Both here!" : "OK" + end + + def test_remote_addr + render :text => (request.remote_addr || "not specified") + end + + def test_file_upload + render :text => params[:file].size + end + + def test_send_file + send_file(File.expand_path(__FILE__)) + end + + def redirect_to_same_controller + redirect_to :controller => 'test', :action => 'test_uri', :id => 5 + end + + def redirect_to_different_controller + redirect_to :controller => 'fail', :id => 5 + end + + def create + head :created, :location => 'created resource' + end + + private + def rescue_action(e) + raise e + end + + def generate_url(opts) + url_for(opts.merge(:action => "test_uri")) + end + end + + def setup + @controller = TestController.new + @request = ActionController::TestRequest.new + @response = ActionController::TestResponse.new + ActionController::Routing::Routes.reload + ActionController::Routing.use_controllers! %w(content admin/user test_test/test) + end + + def teardown + ActionController::Routing::Routes.reload + end + + def test_raw_post_handling + params = {:page => {:name => 'page name'}, 'some key' => 123} + post :render_raw_post, params.dup + + assert_equal params.to_query, @response.body + end + + def test_body_stream + params = { :page => { :name => 'page name' }, 'some key' => 123 } + + post :render_body, params.dup + + assert_equal params.to_query, @response.body + end + + def test_process_without_flash + process :set_flash + assert_equal '><', flash['test'] + end + + def test_process_with_flash + process :set_flash, nil, nil, { "test" => "value" } + assert_equal '>value<', flash['test'] + end + + def test_process_with_request_uri_with_no_params + process :test_uri + assert_equal "/test_test/test/test_uri", @response.body + end + + def test_process_with_request_uri_with_params + process :test_uri, :id => 7 + assert_equal "/test_test/test/test_uri/7", @response.body + end + + def test_process_with_request_uri_with_params_with_explicit_uri + @request.set_REQUEST_URI "/explicit/uri" + process :test_uri, :id => 7 + assert_equal "/explicit/uri", @response.body + end + + def test_process_with_query_string + process :test_query_string, :q => 'test' + assert_equal "q=test", @response.body + end + + def test_process_with_query_string_with_explicit_uri + @request.set_REQUEST_URI "/explicit/uri?q=test?extra=question" + process :test_query_string + assert_equal "q=test?extra=question", @response.body + end + + def test_multiple_calls + process :test_only_one_param, :left => true + assert_equal "OK", @response.body + process :test_only_one_param, :right => true + assert_equal "OK", @response.body + end + + def test_assert_tag_tag + process :test_html_output + + # there is a 'form' tag + assert_tag :tag => 'form' + # there is not an 'hr' tag + assert_no_tag :tag => 'hr' + end + + def test_assert_tag_attributes + process :test_html_output + + # there is a tag with an 'id' of 'bar' + assert_tag :attributes => { :id => "bar" } + # there is no tag with a 'name' of 'baz' + assert_no_tag :attributes => { :name => "baz" } + end + + def test_assert_tag_parent + process :test_html_output + + # there is a tag with a parent 'form' tag + assert_tag :parent => { :tag => "form" } + # there is no tag with a parent of 'input' + assert_no_tag :parent => { :tag => "input" } + end + + def test_assert_tag_child + process :test_html_output + + # there is a tag with a child 'input' tag + assert_tag :child => { :tag => "input" } + # there is no tag with a child 'strong' tag + assert_no_tag :child => { :tag => "strong" } + end + + def test_assert_tag_ancestor + process :test_html_output + + # there is a 'li' tag with an ancestor having an id of 'foo' + assert_tag :ancestor => { :attributes => { :id => "foo" } }, :tag => "li" + # there is no tag of any kind with an ancestor having an href matching 'foo' + assert_no_tag :ancestor => { :attributes => { :href => /foo/ } } + end + + def test_assert_tag_descendant + process :test_html_output + + # there is a tag with a descendant 'li' tag + assert_tag :descendant => { :tag => "li" } + # there is no tag with a descendant 'html' tag + assert_no_tag :descendant => { :tag => "html" } + end + + def test_assert_tag_sibling + process :test_html_output + + # there is a tag with a sibling of class 'item' + assert_tag :sibling => { :attributes => { :class => "item" } } + # there is no tag with a sibling 'ul' tag + assert_no_tag :sibling => { :tag => "ul" } + end + + def test_assert_tag_after + process :test_html_output + + # there is a tag following a sibling 'div' tag + assert_tag :after => { :tag => "div" } + # there is no tag following a sibling tag with id 'bar' + assert_no_tag :after => { :attributes => { :id => "bar" } } + end + + def test_assert_tag_before + process :test_html_output + + # there is a tag preceding a tag with id 'bar' + assert_tag :before => { :attributes => { :id => "bar" } } + # there is no tag preceding a 'form' tag + assert_no_tag :before => { :tag => "form" } + end + + def test_assert_tag_children_count + process :test_html_output + + # there is a tag with 2 children + assert_tag :children => { :count => 2 } + # in particular, there is a <ul> tag with two children (a nameless pair of <li>s) + assert_tag :tag => 'ul', :children => { :count => 2 } + # there is no tag with 4 children + assert_no_tag :children => { :count => 4 } + end + + def test_assert_tag_children_less_than + process :test_html_output + + # there is a tag with less than 5 children + assert_tag :children => { :less_than => 5 } + # there is no 'ul' tag with less than 2 children + assert_no_tag :children => { :less_than => 2 }, :tag => "ul" + end + + def test_assert_tag_children_greater_than + process :test_html_output + + # there is a 'body' tag with more than 1 children + assert_tag :children => { :greater_than => 1 }, :tag => "body" + # there is no tag with more than 10 children + assert_no_tag :children => { :greater_than => 10 } + end + + def test_assert_tag_children_only + process :test_html_output + + # there is a tag containing only one child with an id of 'foo' + assert_tag :children => { :count => 1, + :only => { :attributes => { :id => "foo" } } } + # there is no tag containing only one 'li' child + assert_no_tag :children => { :count => 1, :only => { :tag => "li" } } + end + + def test_assert_tag_content + process :test_html_output + + # the output contains the string "Name" + assert_tag :content => /Name/ + # the output does not contain the string "test" + assert_no_tag :content => /test/ + end + + def test_assert_tag_multiple + process :test_html_output + + # there is a 'div', id='bar', with an immediate child whose 'action' + # attribute matches the regexp /somewhere/. + assert_tag :tag => "div", :attributes => { :id => "bar" }, + :child => { :attributes => { :action => /somewhere/ } } + + # there is no 'div', id='foo', with a 'ul' child with more than + # 2 "li" children. + assert_no_tag :tag => "div", :attributes => { :id => "foo" }, + :child => { + :tag => "ul", + :children => { :greater_than => 2, + :only => { :tag => "li" } } } + end + + def test_assert_tag_children_without_content + process :test_html_output + + # there is a form tag with an 'input' child which is a self closing tag + assert_tag :tag => "form", + :children => { :count => 1, + :only => { :tag => "input" } } + + # the body tag has an 'a' child which in turn has an 'img' child + assert_tag :tag => "body", + :children => { :count => 1, + :only => { :tag => "a", + :children => { :count => 1, + :only => { :tag => "img" } } } } + end + + def test_should_not_impose_childless_html_tags_in_xml + process :test_xml_output + + begin + $stderr = StringIO.new + assert_select 'area' #This will cause a warning if content is processed as HTML + $stderr.rewind && err = $stderr.read + ensure + $stderr = STDERR + end + + assert err.empty? + end + + def test_assert_tag_attribute_matching + @response.body = '<input type="text" name="my_name">' + assert_tag :tag => 'input', + :attributes => { :name => /my/, :type => 'text' } + assert_no_tag :tag => 'input', + :attributes => { :name => 'my', :type => 'text' } + assert_no_tag :tag => 'input', + :attributes => { :name => /^my$/, :type => 'text' } + end + + def test_assert_tag_content_matching + @response.body = "<p>hello world</p>" + assert_tag :tag => "p", :content => "hello world" + assert_tag :tag => "p", :content => /hello/ + assert_no_tag :tag => "p", :content => "hello" + end + + def test_assert_generates + assert_generates 'controller/action/5', :controller => 'controller', :action => 'action', :id => '5' + assert_generates 'controller/action/7', {:id => "7"}, {:controller => "controller", :action => "action"} + assert_generates 'controller/action/5', {:controller => "controller", :action => "action", :id => "5", :name => "bob"}, {}, {:name => "bob"} + assert_generates 'controller/action/7', {:id => "7", :name => "bob"}, {:controller => "controller", :action => "action"}, {:name => "bob"} + assert_generates 'controller/action/7', {:id => "7"}, {:controller => "controller", :action => "action", :name => "bob"}, {} + end + + def test_assert_routing + assert_routing 'content', :controller => 'content', :action => 'index' + end + + def test_assert_routing_in_module + assert_routing 'admin/user', :controller => 'admin/user', :action => 'index' + end + + def test_params_passing + get :test_params, :page => {:name => "Page name", :month => '4', :year => '2004', :day => '6'} + parsed_params = eval(@response.body) + assert_equal( + {'controller' => 'test_test/test', 'action' => 'test_params', + 'page' => {'name' => "Page name", 'month' => '4', 'year' => '2004', 'day' => '6'}}, + parsed_params + ) + end + + def test_id_converted_to_string + get :test_params, :id => 20, :foo => Object.new + assert_kind_of String, @request.path_parameters['id'] + end + + def test_array_path_parameter_handled_properly + with_routing do |set| + set.draw do |map| + map.connect 'file/*path', :controller => 'test_test/test', :action => 'test_params' + map.connect ':controller/:action/:id' + end + + get :test_params, :path => ['hello', 'world'] + assert_equal ['hello', 'world'], @request.path_parameters['path'] + assert_equal 'hello/world', @request.path_parameters['path'].to_s + end + end + + def test_assert_realistic_path_parameters + get :test_params, :id => 20, :foo => Object.new + + # All elements of path_parameters should use string keys + @request.path_parameters.keys.each do |key| + assert_kind_of String, key + end + end + + def test_with_routing_places_routes_back + assert ActionController::Routing::Routes + routes_id = ActionController::Routing::Routes.object_id + + begin + with_routing { raise 'fail' } + fail 'Should not be here.' + rescue RuntimeError + end + + assert ActionController::Routing::Routes + assert_equal routes_id, ActionController::Routing::Routes.object_id + end + + def test_remote_addr + get :test_remote_addr + assert_equal "0.0.0.0", @response.body + + @request.remote_addr = "192.0.0.1" + get :test_remote_addr + assert_equal "192.0.0.1", @response.body + end + + def test_header_properly_reset_after_remote_http_request + xhr :get, :test_params + assert_nil @request.env['HTTP_X_REQUESTED_WITH'] + end + + def test_header_properly_reset_after_get_request + get :test_params + @request.recycle! + assert_nil @request.instance_variable_get("@request_method") + end + + %w(controller response request).each do |variable| + %w(get post put delete head process).each do |method| + define_method("test_#{variable}_missing_for_#{method}_raises_error") do + remove_instance_variable "@#{variable}" + begin + send(method, :test_remote_addr) + assert false, "expected RuntimeError, got nothing" + rescue RuntimeError => error + assert true + assert_match %r{@#{variable} is nil}, error.message + rescue => error + assert false, "expected RuntimeError, got #{error.class}" + end + end + end + end + + FILES_DIR = File.dirname(__FILE__) + '/../fixtures/multipart' + + def test_test_uploaded_file + filename = 'mona_lisa.jpg' + path = "#{FILES_DIR}/#{filename}" + content_type = 'image/png' + + file = ActionController::TestUploadedFile.new(path, content_type) + assert_equal filename, file.original_filename + assert_equal content_type, file.content_type + assert_equal file.path, file.local_path + assert_equal File.read(path), file.read + end + + def test_test_uploaded_file_with_binary + filename = 'mona_lisa.jpg' + path = "#{FILES_DIR}/#{filename}" + content_type = 'image/png' + + binary_uploaded_file = ActionController::TestUploadedFile.new(path, content_type, :binary) + assert_equal File.open(path, 'rb').read, binary_uploaded_file.read + + plain_uploaded_file = ActionController::TestUploadedFile.new(path, content_type) + assert_equal File.open(path, 'r').read, plain_uploaded_file.read + end + + def test_fixture_file_upload_with_binary + filename = 'mona_lisa.jpg' + path = "#{FILES_DIR}/#{filename}" + content_type = 'image/jpg' + + binary_file_upload = fixture_file_upload(path, content_type, :binary) + assert_equal File.open(path, 'rb').read, binary_file_upload.read + + plain_file_upload = fixture_file_upload(path, content_type) + assert_equal File.open(path, 'r').read, plain_file_upload.read + end + + def test_fixture_file_upload + post :test_file_upload, :file => fixture_file_upload(FILES_DIR + "/mona_lisa.jpg", "image/jpg") + assert_equal '159528', @response.body + end + + def test_test_uploaded_file_exception_when_file_doesnt_exist + assert_raise(RuntimeError) { ActionController::TestUploadedFile.new('non_existent_file') } + end + + def test_assert_follow_redirect_to_same_controller + with_foo_routing do |set| + get :redirect_to_same_controller + assert_response :redirect + assert_redirected_to :controller => 'test_test/test', :action => 'test_uri', :id => 5 + assert_nothing_raised { follow_redirect } + end + end + + def test_assert_follow_redirect_to_different_controller + with_foo_routing do |set| + get :redirect_to_different_controller + assert_response :redirect + assert_redirected_to :controller => 'fail', :id => 5 + assert_raise(RuntimeError) { follow_redirect } + end + end + + def test_redirect_url_only_cares_about_location_header + get :create + assert_response :created + + # Redirect url doesn't care that it wasn't a :redirect response. + assert_equal 'created resource', @response.redirect_url + assert_equal @response.redirect_url, redirect_to_url + + # Must be a :redirect response. + assert_raise(Test::Unit::AssertionFailedError) do + assert_redirected_to 'created resource' + end + end + + def test_binary_content_works_with_send_file + get :test_send_file + assert_nothing_raised(NoMethodError) { @response.binary_content } + end + + protected + def with_foo_routing + with_routing do |set| + set.draw do |map| + map.generate_url 'foo', :controller => 'test' + map.connect ':controller/:action/:id' + end + yield set + end + end +end + + +class CleanBacktraceTest < Test::Unit::TestCase + def test_should_reraise_the_same_object + exception = Test::Unit::AssertionFailedError.new('message') + clean_backtrace { raise exception } + rescue => caught + assert_equal exception.object_id, caught.object_id + assert_equal exception.message, caught.message + end + + def test_should_clean_assertion_lines_from_backtrace + path = File.expand_path("#{File.dirname(__FILE__)}/../../lib/action_controller") + exception = Test::Unit::AssertionFailedError.new('message') + exception.set_backtrace ["#{path}/abc", "#{path}/assertions/def"] + clean_backtrace { raise exception } + rescue => caught + assert_equal ["#{path}/abc"], caught.backtrace + end + + def test_should_only_clean_assertion_failure_errors + clean_backtrace do + raise "can't touch this", [File.expand_path("#{File.dirname(__FILE__)}/../../lib/action_controller/assertions/abc")] + end + rescue => caught + assert !caught.backtrace.empty? + end +end + +class InferringClassNameTest < Test::Unit::TestCase + def test_determine_controller_class + assert_equal ContentController, determine_class("ContentControllerTest") + end + + def test_determine_controller_class_with_nonsense_name + assert_raises ActionController::NonInferrableControllerError do + determine_class("HelloGoodBye") + end + end + + def test_determine_controller_class_with_sensible_name_where_no_controller_exists + assert_raises ActionController::NonInferrableControllerError do + determine_class("NoControllerWithThisNameTest") + end + end + + private + def determine_class(name) + ActionController::TestCase.determine_default_controller_class(name) + end +end + +class CrazyNameTest < ActionController::TestCase + tests ContentController + def test_controller_class_can_be_set_manually_not_just_inferred + assert_equal ContentController, self.class.controller_class + end +end + diff --git a/vendor/rails-2.0.2/actionpack/test/controller/url_rewriter_test.rb b/vendor/rails-2.0.2/actionpack/test/controller/url_rewriter_test.rb new file mode 100644 index 000000000..75497c832 --- /dev/null +++ b/vendor/rails-2.0.2/actionpack/test/controller/url_rewriter_test.rb @@ -0,0 +1,246 @@ +require File.dirname(__FILE__) + '/../abstract_unit' + +ActionController::UrlRewriter + +class UrlRewriterTests < Test::Unit::TestCase + def setup + @request = ActionController::TestRequest.new + @params = {} + @rewriter = ActionController::UrlRewriter.new(@request, @params) + end + + def test_port + assert_equal('http://test.host:1271/c/a/i', + @rewriter.rewrite(:controller => 'c', :action => 'a', :id => 'i', :port => 1271) + ) + end + + def test_protocol_with_and_without_separator + assert_equal('https://test.host/c/a/i', + @rewriter.rewrite(:protocol => 'https', :controller => 'c', :action => 'a', :id => 'i') + ) + + assert_equal('https://test.host/c/a/i', + @rewriter.rewrite(:protocol => 'https://', :controller => 'c', :action => 'a', :id => 'i') + ) + end + + def test_user_name_and_password + assert_equal( + 'http://david:secret@test.host/c/a/i', + @rewriter.rewrite(:user => "david", :password => "secret", :controller => 'c', :action => 'a', :id => 'i') + ) + end + + def test_user_name_and_password_with_escape_codes + assert_equal( + 'http://openid.aol.com%2Fnextangler:one+two%3F@test.host/c/a/i', + @rewriter.rewrite(:user => "openid.aol.com/nextangler", :password => "one two?", :controller => 'c', :action => 'a', :id => 'i') + ) + end + + def test_anchor + assert_equal( + 'http://test.host/c/a/i#anchor', + @rewriter.rewrite(:controller => 'c', :action => 'a', :id => 'i', :anchor => 'anchor') + ) + end + + def test_overwrite_params + @params[:controller] = 'hi' + @params[:action] = 'bye' + @params[:id] = '2' + + assert_equal '/hi/hi/2', @rewriter.rewrite(:only_path => true, :overwrite_params => {:action => 'hi'}) + u = @rewriter.rewrite(:only_path => false, :overwrite_params => {:action => 'hi'}) + assert_match %r(/hi/hi/2$), u + end + + def test_overwrite_removes_original + @params[:controller] = 'search' + @params[:action] = 'list' + @params[:list_page] = 1 + + assert_equal '/search/list?list_page=2', @rewriter.rewrite(:only_path => true, :overwrite_params => {"list_page" => 2}) + u = @rewriter.rewrite(:only_path => false, :overwrite_params => {:list_page => 2}) + assert_equal 'http://test.host/search/list?list_page=2', u + end + + def test_to_str + @params[:controller] = 'hi' + @params[:action] = 'bye' + @request.parameters[:id] = '2' + + assert_equal 'http://, test.host, /, hi, bye, {"id"=>"2"}', @rewriter.to_str + end + + def test_trailing_slash + options = {:controller => 'foo', :action => 'bar', :id => '3', :only_path => true} + assert_equal '/foo/bar/3', @rewriter.rewrite(options) + assert_equal '/foo/bar/3?query=string', @rewriter.rewrite(options.merge({:query => 'string'})) + options.update({:trailing_slash => true}) + assert_equal '/foo/bar/3/', @rewriter.rewrite(options) + options.update({:query => 'string'}) + assert_equal '/foo/bar/3/?query=string', @rewriter.rewrite(options) + end +end + +class UrlWriterTests < Test::Unit::TestCase + + class W + include ActionController::UrlWriter + end + + def teardown + W.default_url_options.clear + end + + def add_host! + W.default_url_options[:host] = 'www.basecamphq.com' + end + + def test_exception_is_thrown_without_host + assert_raises RuntimeError do + W.new.url_for :controller => 'c', :action => 'a', :id => 'i' + end + end + + def test_anchor + assert_equal('/c/a#anchor', + W.new.url_for(:only_path => true, :controller => 'c', :action => 'a', :anchor => 'anchor') + ) + end + + def test_default_host + add_host! + assert_equal('http://www.basecamphq.com/c/a/i', + W.new.url_for(:controller => 'c', :action => 'a', :id => 'i') + ) + end + + def test_host_may_be_overridden + add_host! + assert_equal('http://37signals.basecamphq.com/c/a/i', + W.new.url_for(:host => '37signals.basecamphq.com', :controller => 'c', :action => 'a', :id => 'i') + ) + end + + def test_port + add_host! + assert_equal('http://www.basecamphq.com:3000/c/a/i', + W.new.url_for(:controller => 'c', :action => 'a', :id => 'i', :port => 3000) + ) + end + + def test_protocol + add_host! + assert_equal('https://www.basecamphq.com/c/a/i', + W.new.url_for(:controller => 'c', :action => 'a', :id => 'i', :protocol => 'https') + ) + end + + def test_protocol_with_and_without_separator + add_host! + assert_equal('https://www.basecamphq.com/c/a/i', + W.new.url_for(:controller => 'c', :action => 'a', :id => 'i', :protocol => 'https') + ) + assert_equal('https://www.basecamphq.com/c/a/i', + W.new.url_for(:controller => 'c', :action => 'a', :id => 'i', :protocol => 'https://') + ) + end + + def test_named_route + ActionController::Routing::Routes.draw do |map| + map.no_args '/this/is/verbose', :controller => 'home', :action => 'index' + map.home '/home/sweet/home/:user', :controller => 'home', :action => 'index' + map.connect ':controller/:action/:id' + end + + # We need to create a new class in order to install the new named route. + kls = Class.new { include ActionController::UrlWriter } + controller = kls.new + assert controller.respond_to?(:home_url) + assert_equal 'http://www.basecamphq.com/home/sweet/home/again', + controller.send(:home_url, :host => 'www.basecamphq.com', :user => 'again') + + assert_equal("/home/sweet/home/alabama", controller.send(:home_path, :user => 'alabama', :host => 'unused')) + assert_equal("http://www.basecamphq.com/home/sweet/home/alabama", controller.send(:home_url, :user => 'alabama', :host => 'www.basecamphq.com')) + assert_equal("http://www.basecamphq.com/this/is/verbose", controller.send(:no_args_url, :host=>'www.basecamphq.com')) + ensure + ActionController::Routing::Routes.load! + end + + def test_only_path + ActionController::Routing::Routes.draw do |map| + map.home '/home/sweet/home/:user', :controller => 'home', :action => 'index' + map.connect ':controller/:action/:id' + end + + # We need to create a new class in order to install the new named route. + kls = Class.new { include ActionController::UrlWriter } + controller = kls.new + assert controller.respond_to?(:home_url) + assert_equal '/brave/new/world', + controller.send(:url_for, :controller => 'brave', :action => 'new', :id => 'world', :only_path => true) + + assert_equal("/home/sweet/home/alabama", controller.send(:home_url, :user => 'alabama', :host => 'unused', :only_path => true)) + assert_equal("/home/sweet/home/alabama", controller.send(:home_path, 'alabama')) + ensure + ActionController::Routing::Routes.load! + end + + def test_one_parameter + assert_equal('/c/a?param=val', + W.new.url_for(:only_path => true, :controller => 'c', :action => 'a', :param => 'val') + ) + end + + def test_two_parameters + url = W.new.url_for(:only_path => true, :controller => 'c', :action => 'a', :p1 => 'X1', :p2 => 'Y2') + params = extract_params(url) + assert_equal params[0], { :p1 => 'X1' }.to_query + assert_equal params[1], { :p2 => 'Y2' }.to_query + end + + def test_hash_parameter + url = W.new.url_for(:only_path => true, :controller => 'c', :action => 'a', :query => {:name => 'Bob', :category => 'prof'}) + params = extract_params(url) + assert_equal params[0], { 'query[category]' => 'prof' }.to_query + assert_equal params[1], { 'query[name]' => 'Bob' }.to_query + end + + def test_array_parameter + url = W.new.url_for(:only_path => true, :controller => 'c', :action => 'a', :query => ['Bob', 'prof']) + params = extract_params(url) + assert_equal params[0], { 'query[]' => 'Bob' }.to_query + assert_equal params[1], { 'query[]' => 'prof' }.to_query + end + + def test_hash_recursive_parameters + url = W.new.url_for(:only_path => true, :controller => 'c', :action => 'a', :query => {:person => {:name => 'Bob', :position => 'prof'}, :hobby => 'piercing'}) + params = extract_params(url) + assert_equal params[0], { 'query[hobby]' => 'piercing' }.to_query + assert_equal params[1], { 'query[person][name]' => 'Bob' }.to_query + assert_equal params[2], { 'query[person][position]' => 'prof' }.to_query + end + + def test_hash_recursive_and_array_parameters + url = W.new.url_for(:only_path => true, :controller => 'c', :action => 'a', :id => 101, :query => {:person => {:name => 'Bob', :position => ['prof', 'art director']}, :hobby => 'piercing'}) + assert_match %r(^/c/a/101), url + params = extract_params(url) + assert_equal params[0], { 'query[hobby]' => 'piercing' }.to_query + assert_equal params[1], { 'query[person][name]' => 'Bob' }.to_query + assert_equal params[2], { 'query[person][position][]' => 'prof' }.to_query + assert_equal params[3], { 'query[person][position][]' => 'art director' }.to_query + end + + def test_path_generation_for_symbol_parameter_keys + assert_generates("/image", :controller=> :image) + end + + private + def extract_params(url) + url.split('?', 2).last.split('&') + end + +end diff --git a/vendor/rails-2.0.2/actionpack/test/controller/verification_test.rb b/vendor/rails-2.0.2/actionpack/test/controller/verification_test.rb new file mode 100644 index 000000000..e61bd5ccc --- /dev/null +++ b/vendor/rails-2.0.2/actionpack/test/controller/verification_test.rb @@ -0,0 +1,253 @@ +require File.dirname(__FILE__) + '/../abstract_unit' + +class VerificationTest < Test::Unit::TestCase + class TestController < ActionController::Base + verify :only => :guarded_one, :params => "one", + :add_flash => { :error => 'unguarded' }, + :redirect_to => { :action => "unguarded" } + + verify :only => :guarded_two, :params => %w( one two ), + :redirect_to => { :action => "unguarded" } + + verify :only => :guarded_with_flash, :params => "one", + :add_flash => { :notice => "prereqs failed" }, + :redirect_to => { :action => "unguarded" } + + verify :only => :guarded_in_session, :session => "one", + :redirect_to => { :action => "unguarded" } + + verify :only => [:multi_one, :multi_two], :session => %w( one two ), + :redirect_to => { :action => "unguarded" } + + verify :only => :guarded_by_method, :method => :post, + :redirect_to => { :action => "unguarded" } + + verify :only => :guarded_by_xhr, :xhr => true, + :redirect_to => { :action => "unguarded" } + + verify :only => :guarded_by_not_xhr, :xhr => false, + :redirect_to => { :action => "unguarded" } + + before_filter :unconditional_redirect, :only => :two_redirects + verify :only => :two_redirects, :method => :post, + :redirect_to => { :action => "unguarded" } + + verify :only => :must_be_post, :method => :post, :render => { :status => 405, :text => "Must be post" }, :add_headers => { "Allow" => "POST" } + + verify :only => :guarded_one_for_named_route_test, :params => "one", + :redirect_to => :foo_url + + verify :only => :no_default_action, :params => "santa" + + def guarded_one + render :text => "#{params[:one]}" + end + + def guarded_one_for_named_route_test + render :text => "#{params[:one]}" + end + + def guarded_with_flash + render :text => "#{params[:one]}" + end + + def guarded_two + render :text => "#{params[:one]}:#{params[:two]}" + end + + def guarded_in_session + render :text => "#{session["one"]}" + end + + def multi_one + render :text => "#{session["one"]}:#{session["two"]}" + end + + def multi_two + render :text => "#{session["two"]}:#{session["one"]}" + end + + def guarded_by_method + render :text => "#{request.method}" + end + + def guarded_by_xhr + render :text => "#{request.xhr?}" + end + + def guarded_by_not_xhr + render :text => "#{request.xhr?}" + end + + def unguarded + render :text => "#{params[:one]}" + end + + def two_redirects + render :nothing => true + end + + def must_be_post + render :text => "Was a post!" + end + + def no_default_action + # Will never run + end + + protected + def rescue_action(e) raise end + + def unconditional_redirect + redirect_to :action => "unguarded" + end + end + + def setup + @controller = TestController.new + @request = ActionController::TestRequest.new + @response = ActionController::TestResponse.new + ActionController::Routing::Routes.add_named_route :foo, '/foo', :controller => 'test', :action => 'foo' + end + + def test_no_deprecation_warning_for_named_route + assert_not_deprecated do + get :guarded_one_for_named_route_test, :two => "not one" + assert_redirected_to '/foo' + end + end + + def test_guarded_one_with_prereqs + get :guarded_one, :one => "here" + assert_equal "here", @response.body + end + + def test_guarded_one_without_prereqs + get :guarded_one + assert_redirected_to :action => "unguarded" + assert_equal 'unguarded', flash[:error] + end + + def test_guarded_with_flash_with_prereqs + get :guarded_with_flash, :one => "here" + assert_equal "here", @response.body + assert flash.empty? + end + + def test_guarded_with_flash_without_prereqs + get :guarded_with_flash + assert_redirected_to :action => "unguarded" + assert_equal "prereqs failed", flash[:notice] + end + + def test_guarded_two_with_prereqs + get :guarded_two, :one => "here", :two => "there" + assert_equal "here:there", @response.body + end + + def test_guarded_two_without_prereqs_one + get :guarded_two, :two => "there" + assert_redirected_to :action => "unguarded" + end + + def test_guarded_two_without_prereqs_two + get :guarded_two, :one => "here" + assert_redirected_to :action => "unguarded" + end + + def test_guarded_two_without_prereqs_both + get :guarded_two + assert_redirected_to :action => "unguarded" + end + + def test_unguarded_with_params + get :unguarded, :one => "here" + assert_equal "here", @response.body + end + + def test_unguarded_without_params + get :unguarded + assert_equal "", @response.body + end + + def test_guarded_in_session_with_prereqs + get :guarded_in_session, {}, "one" => "here" + assert_equal "here", @response.body + end + + def test_guarded_in_session_without_prereqs + get :guarded_in_session + assert_redirected_to :action => "unguarded" + end + + def test_multi_one_with_prereqs + get :multi_one, {}, "one" => "here", "two" => "there" + assert_equal "here:there", @response.body + end + + def test_multi_one_without_prereqs + get :multi_one + assert_redirected_to :action => "unguarded" + end + + def test_multi_two_with_prereqs + get :multi_two, {}, "one" => "here", "two" => "there" + assert_equal "there:here", @response.body + end + + def test_multi_two_without_prereqs + get :multi_two + assert_redirected_to :action => "unguarded" + end + + def test_guarded_by_method_with_prereqs + post :guarded_by_method + assert_equal "post", @response.body + end + + def test_guarded_by_method_without_prereqs + get :guarded_by_method + assert_redirected_to :action => "unguarded" + end + + def test_guarded_by_xhr_with_prereqs + xhr :post, :guarded_by_xhr + assert_equal "true", @response.body + end + + def test_guarded_by_xhr_without_prereqs + get :guarded_by_xhr + assert_redirected_to :action => "unguarded" + end + + def test_guarded_by_not_xhr_with_prereqs + get :guarded_by_not_xhr + assert_equal "false", @response.body + end + + def test_guarded_by_not_xhr_without_prereqs + xhr :post, :guarded_by_not_xhr + assert_redirected_to :action => "unguarded" + end + + def test_guarded_post_and_calls_render_succeeds + post :must_be_post + assert_equal "Was a post!", @response.body + end + + def test_default_failure_should_be_a_bad_request + post :no_default_action + assert_response :bad_request + end + + def test_guarded_post_and_calls_render_fails_and_sets_allow_header + get :must_be_post + assert_response 405 + assert_equal "Must be post", @response.body + assert_equal "POST", @response.headers["Allow"] + end + + def test_second_redirect + assert_nothing_raised { get :two_redirects } + end +end diff --git a/vendor/rails-2.0.2/actionpack/test/controller/view_paths_test.rb b/vendor/rails-2.0.2/actionpack/test/controller/view_paths_test.rb new file mode 100644 index 000000000..e29e2b9f3 --- /dev/null +++ b/vendor/rails-2.0.2/actionpack/test/controller/view_paths_test.rb @@ -0,0 +1,137 @@ +require File.dirname(__FILE__) + '/../abstract_unit' + +class ViewLoadPathsTest < Test::Unit::TestCase + + LOAD_PATH_ROOT = File.join(File.dirname(__FILE__), '..', 'fixtures') + + ActionController::Base.view_paths = [ LOAD_PATH_ROOT ] + + class TestController < ActionController::Base + def self.controller_path() "test" end + def rescue_action(e) raise end + + before_filter :add_view_path, :only => :hello_world_at_request_time + + def hello_world() end + def hello_world_at_request_time() render(:action => 'hello_world') end + private + def add_view_path + self.class.view_paths.unshift "#{LOAD_PATH_ROOT}/override" + end + end + + class Test::SubController < ActionController::Base + layout 'test/sub' + def hello_world; render(:template => 'test/hello_world'); end + end + + def setup + TestController.view_paths = nil + ActionView::Base.cache_template_extensions = false + @controller = TestController.new + @request = ActionController::TestRequest.new + @response = ActionController::TestResponse.new + + # Track the last warning. + @old_behavior = ActiveSupport::Deprecation.behavior + @last_message = nil + ActiveSupport::Deprecation.behavior = Proc.new { |message, callback| @last_message = message } + end + + def teardown + ActiveSupport::Deprecation.behavior = @old_behavior + ActionView::Base.cache_template_extensions = true + end + + def test_template_load_path_was_set_correctly + assert_equal [ LOAD_PATH_ROOT ], @controller.view_paths + end + + def test_controller_appends_view_path_correctly + TestController.append_view_path 'foo' + assert_equal [LOAD_PATH_ROOT, 'foo'], @controller.view_paths + + TestController.append_view_path(%w(bar baz)) + assert_equal [LOAD_PATH_ROOT, 'foo', 'bar', 'baz'], @controller.view_paths + end + + def test_controller_prepends_view_path_correctly + TestController.prepend_view_path 'baz' + assert_equal ['baz', LOAD_PATH_ROOT], @controller.view_paths + + TestController.prepend_view_path(%w(foo bar)) + assert_equal ['foo', 'bar', 'baz', LOAD_PATH_ROOT], @controller.view_paths + end + + def test_template_appends_view_path_correctly + @controller.instance_variable_set :@template, ActionView::Base.new(TestController.view_paths, {}, @controller) + class_view_paths = TestController.view_paths + + @controller.append_view_path 'foo' + assert_equal [LOAD_PATH_ROOT, 'foo'], @controller.view_paths + + @controller.append_view_path(%w(bar baz)) + assert_equal [LOAD_PATH_ROOT, 'foo', 'bar', 'baz'], @controller.view_paths + assert_equal class_view_paths, TestController.view_paths + end + + def test_template_prepends_view_path_correctly + @controller.instance_variable_set :@template, ActionView::Base.new(TestController.view_paths, {}, @controller) + class_view_paths = TestController.view_paths + + @controller.prepend_view_path 'baz' + assert_equal ['baz', LOAD_PATH_ROOT], @controller.view_paths + + @controller.prepend_view_path(%w(foo bar)) + assert_equal ['foo', 'bar', 'baz', LOAD_PATH_ROOT], @controller.view_paths + assert_equal class_view_paths, TestController.view_paths + end + + def test_view_paths + get :hello_world + assert_response :success + assert_equal "Hello world!", @response.body + end + + def test_view_paths_override + TestController.view_paths.unshift "#{LOAD_PATH_ROOT}/override" + get :hello_world + assert_response :success + assert_equal "Hello overridden world!", @response.body + end + + def test_view_paths_override_for_layouts_in_controllers_with_a_module + @controller = Test::SubController.new + Test::SubController.view_paths = [ "#{LOAD_PATH_ROOT}/override", LOAD_PATH_ROOT, "#{LOAD_PATH_ROOT}/override2" ] + get :hello_world + assert_response :success + assert_equal "layout: Hello overridden world!", @response.body + end + + def test_view_paths_override_at_request_time + get :hello_world_at_request_time + assert_response :success + assert_equal "Hello overridden world!", @response.body + end + + def test_inheritance + original_load_paths = ActionController::Base.view_paths + + self.class.class_eval %{ + class A < ActionController::Base; end + class B < A; end + class C < ActionController::Base; end + } + + A.view_paths = [ 'a/path' ] + + assert_equal [ 'a/path' ], A.view_paths + assert_equal A.view_paths, B.view_paths + assert_equal original_load_paths, C.view_paths + + C.view_paths = [] + assert_nothing_raised { C.view_paths << 'c/path' } + assert_equal ['c/path'], C.view_paths + end + +end
\ No newline at end of file diff --git a/vendor/rails-2.0.2/actionpack/test/controller/webservice_test.rb b/vendor/rails-2.0.2/actionpack/test/controller/webservice_test.rb new file mode 100644 index 000000000..d89de5c8f --- /dev/null +++ b/vendor/rails-2.0.2/actionpack/test/controller/webservice_test.rb @@ -0,0 +1,184 @@ +require File.dirname(__FILE__) + '/../abstract_unit' + +class WebServiceTest < Test::Unit::TestCase + class MockCGI < CGI #:nodoc: + attr_accessor :stdoutput, :env_table + + def initialize(env, data = '') + self.env_table = env + self.stdoutput = StringIO.new + super(nil, StringIO.new(data)) + end + end + + class TestController < ActionController::Base + session :off + + def assign_parameters + if params[:full] + render :text => dump_params_keys + else + render :text => (params.keys - ['controller', 'action']).sort.join(", ") + end + end + + def dump_params_keys(hash=params) + hash.keys.sort.inject("") do |s, k| + value = hash[k] + value = Hash === value ? "(#{dump_params_keys(value)})" : "" + s << ", " unless s.empty? + s << "#{k}#{value}" + end + end + + def rescue_action(e) raise end + end + + def setup + @controller = TestController.new + @default_param_parsers = ActionController::Base.param_parsers.dup + end + + def teardown + ActionController::Base.param_parsers = @default_param_parsers + end + + def test_check_parameters + process('GET') + assert_equal '', @controller.response.body + end + + def test_post_xml + process('POST', 'application/xml', '<entry attributed="true"><summary>content...</summary></entry>') + + assert_equal 'entry', @controller.response.body + assert @controller.params.has_key?(:entry) + assert_equal 'content...', @controller.params["entry"]['summary'] + assert_equal 'true', @controller.params["entry"]['attributed'] + end + + def test_put_xml + process('PUT', 'application/xml', '<entry attributed="true"><summary>content...</summary></entry>') + + assert_equal 'entry', @controller.response.body + assert @controller.params.has_key?(:entry) + assert_equal 'content...', @controller.params["entry"]['summary'] + assert_equal 'true', @controller.params["entry"]['attributed'] + end + + def test_register_and_use_yaml + ActionController::Base.param_parsers[Mime::YAML] = Proc.new { |d| YAML.load(d) } + process('POST', 'application/x-yaml', {"entry" => "loaded from yaml"}.to_yaml) + assert_equal 'entry', @controller.response.body + assert @controller.params.has_key?(:entry) + assert_equal 'loaded from yaml', @controller.params["entry"] + end + + def test_register_and_use_yaml_as_symbol + ActionController::Base.param_parsers[Mime::YAML] = :yaml + process('POST', 'application/x-yaml', {"entry" => "loaded from yaml"}.to_yaml) + assert_equal 'entry', @controller.response.body + assert @controller.params.has_key?(:entry) + assert_equal 'loaded from yaml', @controller.params["entry"] + end + + def test_register_and_use_xml_simple + ActionController::Base.param_parsers[Mime::XML] = Proc.new { |data| XmlSimple.xml_in(data, 'ForceArray' => false) } + process('POST', 'application/xml', '<request><summary>content...</summary><title>SimpleXml</title></request>' ) + assert_equal 'summary, title', @controller.response.body + assert @controller.params.has_key?(:summary) + assert @controller.params.has_key?(:title) + assert_equal 'content...', @controller.params["summary"] + assert_equal 'SimpleXml', @controller.params["title"] + end + + def test_use_xml_ximple_with_empty_request + ActionController::Base.param_parsers[Mime::XML] = :xml_simple + assert_nothing_raised { process('POST', 'application/xml', "") } + assert_equal "", @controller.response.body + end + + def test_dasherized_keys_as_xml + ActionController::Base.param_parsers[Mime::XML] = :xml_simple + process('POST', 'application/xml', "<first-key>\n<sub-key>...</sub-key>\n</first-key>", true) + assert_equal 'action, controller, first_key(sub_key), full', @controller.response.body + assert_equal "...", @controller.params[:first_key][:sub_key] + end + + def test_typecast_as_xml + ActionController::Base.param_parsers[Mime::XML] = :xml_simple + process('POST', 'application/xml', <<-XML) + <data> + <a type="integer">15</a> + <b type="boolean">false</b> + <c type="boolean">true</c> + <d type="date">2005-03-17</d> + <e type="datetime">2005-03-17T21:41:07Z</e> + <f>unparsed</f> + <g type="integer">1</g> + <g>hello</g> + <g type="date">1974-07-25</g> + </data> + XML + params = @controller.params + assert_equal 15, params[:data][:a] + assert_equal false, params[:data][:b] + assert_equal true, params[:data][:c] + assert_equal Date.new(2005,3,17), params[:data][:d] + assert_equal Time.utc(2005,3,17,21,41,7), params[:data][:e] + assert_equal "unparsed", params[:data][:f] + assert_equal [1, "hello", Date.new(1974,7,25)], params[:data][:g] + end + + def test_entities_unescaped_as_xml_simple + ActionController::Base.param_parsers[Mime::XML] = :xml_simple + process('POST', 'application/xml', <<-XML) + <data><foo "bar's" & friends></data> + XML + assert_equal %(<foo "bar's" & friends>), @controller.params[:data] + end + + def test_typecast_as_yaml + ActionController::Base.param_parsers[Mime::YAML] = :yaml + process('POST', 'application/x-yaml', <<-YAML) + --- + data: + a: 15 + b: false + c: true + d: 2005-03-17 + e: 2005-03-17T21:41:07Z + f: unparsed + g: + - 1 + - hello + - 1974-07-25 + YAML + params = @controller.params + assert_equal 15, params[:data][:a] + assert_equal false, params[:data][:b] + assert_equal true, params[:data][:c] + assert_equal Date.new(2005,3,17), params[:data][:d] + assert_equal Time.utc(2005,3,17,21,41,7), params[:data][:e] + assert_equal "unparsed", params[:data][:f] + assert_equal [1, "hello", Date.new(1974,7,25)], params[:data][:g] + end + + private + + def process(verb, content_type = 'application/x-www-form-urlencoded', data = '', full=false) + + cgi = MockCGI.new({ + 'REQUEST_METHOD' => verb, + 'CONTENT_TYPE' => content_type, + 'QUERY_STRING' => "action=assign_parameters&controller=webservicetest/test#{"&full=1" if full}", + "REQUEST_URI" => "/", + "HTTP_HOST" => 'testdomain.com', + "CONTENT_LENGTH" => data.size, + "SERVER_PORT" => "80", + "HTTPS" => "off"}, data) + + @controller.send(:process, ActionController::CgiRequest.new(cgi, {}), ActionController::CgiResponse.new(cgi)) + end + +end |